Merge "parserTests: flag articles creation as internal"
[lhc/web/wiklou.git] / tests / phpunit / maintenance / MaintenanceTest.php
1 <?php
2
3 // It would be great if we were able to use PHPUnit's getMockForAbstractClass
4 // instead of the MaintenanceFixup hack below. However, we cannot do
5 // without changing the visibility and without working around hacks in
6 // Maintenance.php
7 // For the same reason, we cannot just use FakeMaintenance.
8 use MediaWiki\MediaWikiServices;
9
10 /**
11 * makes parts of the API of Maintenance that is hidden by protected visibily
12 * visible for testing, and makes up for a stream closing hack in Maintenance.php.
13 *
14 * This class is solely used for being able to test Maintenance right now
15 * without having to apply major refactorings to fix some design issues in
16 * Maintenance.php. Before adding more functions here, please consider whether
17 * this approach is correct, or a refactoring Maintenance to separate concers
18 * is more appropriate.
19 *
20 * Upon refactoring, keep in mind that besides the maintenance scrits themselves
21 * and tests right here, also at least Extension:Maintenance make use of
22 * Maintenance.
23 *
24 * Due to a hack in Maintenance.php using register_shutdown_function, be sure to
25 * finally call simulateShutdown on MaintenanceFixup instance before a test
26 * ends.
27 *
28 */
29 class MaintenanceFixup extends Maintenance {
30
31 // --- Making up for the register_shutdown_function hack in Maintenance.php
32
33 /**
34 * The test case that generated this instance.
35 *
36 * This member is motivated by allowing the destructor to check whether or not
37 * the test failed, in order to avoid unnecessary nags about omitted shutdown
38 * simulation.
39 * But as it is already available, we also usi it to flagging tests as failed
40 *
41 * @var MediaWikiTestCase
42 */
43 private $testCase;
44
45 /**
46 * shutdownSimulated === true if simulateShutdown has done it's work
47 *
48 * @var bool
49 */
50 private $shutdownSimulated = false;
51
52 /**
53 * Simulates what Maintenance wants to happen at script's end.
54 */
55 public function simulateShutdown() {
56
57 if ( $this->shutdownSimulated ) {
58 $this->testCase->fail( __METHOD__ . " called more than once" );
59 }
60
61 // The cleanup action.
62 $this->outputChanneled( false );
63
64 // Bookkeeping that we simulated the clean up.
65 $this->shutdownSimulated = true;
66 }
67
68 // Note that the "public" here does not change visibility
69 public function outputChanneled( $msg, $channel = null ) {
70 if ( $this->shutdownSimulated ) {
71 if ( $msg !== false ) {
72 $this->testCase->fail( "Already past simulated shutdown, but msg is "
73 . "not false. Did the hack in Maintenance.php change? Please "
74 . "adapt the test case or Maintenance.php" );
75 }
76
77 // The current call is the one registered via register_shutdown_function.
78 // We can safely ignore it, as we simulated this one via simulateShutdown
79 // before (if we did not, the destructor of this instance will warn about
80 // it)
81 return;
82 }
83
84 call_user_func_array( [ "parent", __FUNCTION__ ], func_get_args() );
85 }
86
87 /**
88 * Safety net around register_shutdown_function of Maintenance.php
89 */
90 public function __destruct() {
91 if ( !$this->shutdownSimulated ) {
92 // Someone generated a MaintenanceFixup instance without calling
93 // simulateShutdown. We'd have to raise a PHPUnit exception to correctly
94 // flag this illegal usage. However, we are already in a destruktor, which
95 // would trigger undefined behavior. Hence, we can only report to the
96 // error output :( Hopefully people read the PHPUnit output.
97 $name = $this->testCase->getName();
98 fwrite( STDERR, "ERROR! Instance of " . __CLASS__ . " for test $name "
99 . "destructed without calling simulateShutdown method. Call "
100 . "simulateShutdown on the instance before it gets destructed." );
101 }
102
103 // The following guard is required, as PHP does not offer default destructors :(
104 if ( is_callable( "parent::__destruct" ) ) {
105 parent::__destruct();
106 }
107 }
108
109 public function __construct( MediaWikiTestCase $testCase ) {
110 parent::__construct();
111 $this->testCase = $testCase;
112 }
113
114 // --- Making protected functions visible for test
115
116 public function output( $out, $channel = null ) {
117 // Just to make PHP not nag about signature mismatches, we copied
118 // Maintenance::output signature. However, we do not use (or rely on)
119 // those variables. Instead we pass to Maintenance::output whatever we
120 // receive at runtime.
121 return call_user_func_array( [ "parent", __FUNCTION__ ], func_get_args() );
122 }
123
124 public function addOption( $name, $description, $required = false,
125 $withArg = false, $shortName = false, $multiOccurance = false
126 ) {
127 return call_user_func_array( [ "parent", __FUNCTION__ ], func_get_args() );
128 }
129
130 public function getOption( $name, $default = null ) {
131 return call_user_func_array( [ "parent", __FUNCTION__ ], func_get_args() );
132 }
133
134 // --- Requirements for getting instance of abstract class
135
136 public function execute() {
137 $this->testCase->fail( __METHOD__ . " called unexpectedly" );
138 }
139 }
140
141 /**
142 * @covers Maintenance
143 */
144 class MaintenanceTest extends MediaWikiTestCase {
145
146 /**
147 * The main Maintenance instance that is used for testing.
148 *
149 * @var MaintenanceFixup
150 */
151 private $m;
152
153 protected function setUp() {
154 parent::setUp();
155 $this->m = new MaintenanceFixup( $this );
156 }
157
158 protected function tearDown() {
159 if ( $this->m ) {
160 $this->m->simulateShutdown();
161 $this->m = null;
162 }
163 parent::tearDown();
164 }
165
166 /**
167 * asserts the output before and after simulating shutdown
168 *
169 * This function simulates shutdown of self::m.
170 *
171 * @param string $preShutdownOutput Expected output before simulating shutdown
172 * @param bool $expectNLAppending Whether or not shutdown simulation is expected
173 * to add a newline to the output. If false, $preShutdownOutput is the
174 * expected output after shutdown simulation. Otherwise,
175 * $preShutdownOutput with an appended newline is the expected output
176 * after shutdown simulation.
177 */
178 private function assertOutputPrePostShutdown( $preShutdownOutput, $expectNLAppending ) {
179
180 $this->assertEquals( $preShutdownOutput, $this->getActualOutput(),
181 "Output before shutdown simulation" );
182
183 $this->m->simulateShutdown();
184 $this->m = null;
185
186 $postShutdownOutput = $preShutdownOutput . ( $expectNLAppending ? "\n" : "" );
187 $this->expectOutputString( $postShutdownOutput );
188 }
189
190 // Although the following tests do not seem to be too consistent (compare for
191 // example the newlines within the test.*StringString tests, or the
192 // test.*Intermittent.* tests), the objective of these tests is not to describe
193 // consistent behavior, but rather currently existing behavior.
194
195 function testOutputEmpty() {
196 $this->m->output( "" );
197 $this->assertOutputPrePostShutdown( "", false );
198 }
199
200 function testOutputString() {
201 $this->m->output( "foo" );
202 $this->assertOutputPrePostShutdown( "foo", false );
203 }
204
205 function testOutputStringString() {
206 $this->m->output( "foo" );
207 $this->m->output( "bar" );
208 $this->assertOutputPrePostShutdown( "foobar", false );
209 }
210
211 function testOutputStringNL() {
212 $this->m->output( "foo\n" );
213 $this->assertOutputPrePostShutdown( "foo\n", false );
214 }
215
216 function testOutputStringNLNL() {
217 $this->m->output( "foo\n\n" );
218 $this->assertOutputPrePostShutdown( "foo\n\n", false );
219 }
220
221 function testOutputStringNLString() {
222 $this->m->output( "foo\nbar" );
223 $this->assertOutputPrePostShutdown( "foo\nbar", false );
224 }
225
226 function testOutputStringNLStringNL() {
227 $this->m->output( "foo\nbar\n" );
228 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
229 }
230
231 function testOutputStringNLStringNLLinewise() {
232 $this->m->output( "foo\n" );
233 $this->m->output( "bar\n" );
234 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
235 }
236
237 function testOutputStringNLStringNLArbitrary() {
238 $this->m->output( "" );
239 $this->m->output( "foo" );
240 $this->m->output( "" );
241 $this->m->output( "\n" );
242 $this->m->output( "ba" );
243 $this->m->output( "" );
244 $this->m->output( "r\n" );
245 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
246 }
247
248 function testOutputStringNLStringNLArbitraryAgain() {
249 $this->m->output( "" );
250 $this->m->output( "foo" );
251 $this->m->output( "" );
252 $this->m->output( "\nb" );
253 $this->m->output( "a" );
254 $this->m->output( "" );
255 $this->m->output( "r\n" );
256 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
257 }
258
259 function testOutputWNullChannelEmpty() {
260 $this->m->output( "", null );
261 $this->assertOutputPrePostShutdown( "", false );
262 }
263
264 function testOutputWNullChannelString() {
265 $this->m->output( "foo", null );
266 $this->assertOutputPrePostShutdown( "foo", false );
267 }
268
269 function testOutputWNullChannelStringString() {
270 $this->m->output( "foo", null );
271 $this->m->output( "bar", null );
272 $this->assertOutputPrePostShutdown( "foobar", false );
273 }
274
275 function testOutputWNullChannelStringNL() {
276 $this->m->output( "foo\n", null );
277 $this->assertOutputPrePostShutdown( "foo\n", false );
278 }
279
280 function testOutputWNullChannelStringNLNL() {
281 $this->m->output( "foo\n\n", null );
282 $this->assertOutputPrePostShutdown( "foo\n\n", false );
283 }
284
285 function testOutputWNullChannelStringNLString() {
286 $this->m->output( "foo\nbar", null );
287 $this->assertOutputPrePostShutdown( "foo\nbar", false );
288 }
289
290 function testOutputWNullChannelStringNLStringNL() {
291 $this->m->output( "foo\nbar\n", null );
292 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
293 }
294
295 function testOutputWNullChannelStringNLStringNLLinewise() {
296 $this->m->output( "foo\n", null );
297 $this->m->output( "bar\n", null );
298 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
299 }
300
301 function testOutputWNullChannelStringNLStringNLArbitrary() {
302 $this->m->output( "", null );
303 $this->m->output( "foo", null );
304 $this->m->output( "", null );
305 $this->m->output( "\n", null );
306 $this->m->output( "ba", null );
307 $this->m->output( "", null );
308 $this->m->output( "r\n", null );
309 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
310 }
311
312 function testOutputWNullChannelStringNLStringNLArbitraryAgain() {
313 $this->m->output( "", null );
314 $this->m->output( "foo", null );
315 $this->m->output( "", null );
316 $this->m->output( "\nb", null );
317 $this->m->output( "a", null );
318 $this->m->output( "", null );
319 $this->m->output( "r\n", null );
320 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
321 }
322
323 function testOutputWChannelString() {
324 $this->m->output( "foo", "bazChannel" );
325 $this->assertOutputPrePostShutdown( "foo", true );
326 }
327
328 function testOutputWChannelStringNL() {
329 $this->m->output( "foo\n", "bazChannel" );
330 $this->assertOutputPrePostShutdown( "foo", true );
331 }
332
333 function testOutputWChannelStringNLNL() {
334 // If this test fails, note that output takes strings with double line
335 // endings (although output's implementation in this situation calls
336 // outputChanneled with a string ending in a nl ... which is not allowed
337 // according to the documentation of outputChanneled)
338 $this->m->output( "foo\n\n", "bazChannel" );
339 $this->assertOutputPrePostShutdown( "foo\n", true );
340 }
341
342 function testOutputWChannelStringNLString() {
343 $this->m->output( "foo\nbar", "bazChannel" );
344 $this->assertOutputPrePostShutdown( "foo\nbar", true );
345 }
346
347 function testOutputWChannelStringNLStringNL() {
348 $this->m->output( "foo\nbar\n", "bazChannel" );
349 $this->assertOutputPrePostShutdown( "foo\nbar", true );
350 }
351
352 function testOutputWChannelStringNLStringNLLinewise() {
353 $this->m->output( "foo\n", "bazChannel" );
354 $this->m->output( "bar\n", "bazChannel" );
355 $this->assertOutputPrePostShutdown( "foobar", true );
356 }
357
358 function testOutputWChannelStringNLStringNLArbitrary() {
359 $this->m->output( "", "bazChannel" );
360 $this->m->output( "foo", "bazChannel" );
361 $this->m->output( "", "bazChannel" );
362 $this->m->output( "\n", "bazChannel" );
363 $this->m->output( "ba", "bazChannel" );
364 $this->m->output( "", "bazChannel" );
365 $this->m->output( "r\n", "bazChannel" );
366 $this->assertOutputPrePostShutdown( "foobar", true );
367 }
368
369 function testOutputWChannelStringNLStringNLArbitraryAgain() {
370 $this->m->output( "", "bazChannel" );
371 $this->m->output( "foo", "bazChannel" );
372 $this->m->output( "", "bazChannel" );
373 $this->m->output( "\nb", "bazChannel" );
374 $this->m->output( "a", "bazChannel" );
375 $this->m->output( "", "bazChannel" );
376 $this->m->output( "r\n", "bazChannel" );
377 $this->assertOutputPrePostShutdown( "foo\nbar", true );
378 }
379
380 function testOutputWMultipleChannelsChannelChange() {
381 $this->m->output( "foo", "bazChannel" );
382 $this->m->output( "bar", "bazChannel" );
383 $this->m->output( "qux", "quuxChannel" );
384 $this->m->output( "corge", "bazChannel" );
385 $this->assertOutputPrePostShutdown( "foobar\nqux\ncorge", true );
386 }
387
388 function testOutputWMultipleChannelsChannelChangeNL() {
389 $this->m->output( "foo", "bazChannel" );
390 $this->m->output( "bar\n", "bazChannel" );
391 $this->m->output( "qux\n", "quuxChannel" );
392 $this->m->output( "corge", "bazChannel" );
393 $this->assertOutputPrePostShutdown( "foobar\nqux\ncorge", true );
394 }
395
396 function testOutputWAndWOChannelStringStartWO() {
397 $this->m->output( "foo" );
398 $this->m->output( "bar", "bazChannel" );
399 $this->m->output( "qux" );
400 $this->m->output( "quux", "bazChannel" );
401 $this->assertOutputPrePostShutdown( "foobar\nquxquux", true );
402 }
403
404 function testOutputWAndWOChannelStringStartW() {
405 $this->m->output( "foo", "bazChannel" );
406 $this->m->output( "bar" );
407 $this->m->output( "qux", "bazChannel" );
408 $this->m->output( "quux" );
409 $this->assertOutputPrePostShutdown( "foo\nbarqux\nquux", false );
410 }
411
412 function testOutputWChannelTypeSwitch() {
413 $this->m->output( "foo", 1 );
414 $this->m->output( "bar", 1.0 );
415 $this->assertOutputPrePostShutdown( "foo\nbar", true );
416 }
417
418 function testOutputIntermittentEmpty() {
419 $this->m->output( "foo" );
420 $this->m->output( "" );
421 $this->m->output( "bar" );
422 $this->assertOutputPrePostShutdown( "foobar", false );
423 }
424
425 function testOutputIntermittentFalse() {
426 $this->m->output( "foo" );
427 $this->m->output( false );
428 $this->m->output( "bar" );
429 $this->assertOutputPrePostShutdown( "foobar", false );
430 }
431
432 function testOutputIntermittentFalseAfterOtherChannel() {
433 $this->m->output( "qux", "quuxChannel" );
434 $this->m->output( "foo" );
435 $this->m->output( false );
436 $this->m->output( "bar" );
437 $this->assertOutputPrePostShutdown( "qux\nfoobar", false );
438 }
439
440 function testOutputWNullChannelIntermittentEmpty() {
441 $this->m->output( "foo", null );
442 $this->m->output( "", null );
443 $this->m->output( "bar", null );
444 $this->assertOutputPrePostShutdown( "foobar", false );
445 }
446
447 function testOutputWNullChannelIntermittentFalse() {
448 $this->m->output( "foo", null );
449 $this->m->output( false, null );
450 $this->m->output( "bar", null );
451 $this->assertOutputPrePostShutdown( "foobar", false );
452 }
453
454 function testOutputWChannelIntermittentEmpty() {
455 $this->m->output( "foo", "bazChannel" );
456 $this->m->output( "", "bazChannel" );
457 $this->m->output( "bar", "bazChannel" );
458 $this->assertOutputPrePostShutdown( "foobar", true );
459 }
460
461 function testOutputWChannelIntermittentFalse() {
462 $this->m->output( "foo", "bazChannel" );
463 $this->m->output( false, "bazChannel" );
464 $this->m->output( "bar", "bazChannel" );
465 $this->assertOutputPrePostShutdown( "foobar", true );
466 }
467
468 // Note that (per documentation) outputChanneled does take strings that end
469 // in \n, hence we do not test such strings.
470
471 function testOutputChanneledEmpty() {
472 $this->m->outputChanneled( "" );
473 $this->assertOutputPrePostShutdown( "\n", false );
474 }
475
476 function testOutputChanneledString() {
477 $this->m->outputChanneled( "foo" );
478 $this->assertOutputPrePostShutdown( "foo\n", false );
479 }
480
481 function testOutputChanneledStringString() {
482 $this->m->outputChanneled( "foo" );
483 $this->m->outputChanneled( "bar" );
484 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
485 }
486
487 function testOutputChanneledStringNLString() {
488 $this->m->outputChanneled( "foo\nbar" );
489 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
490 }
491
492 function testOutputChanneledStringNLStringNLArbitraryAgain() {
493 $this->m->outputChanneled( "" );
494 $this->m->outputChanneled( "foo" );
495 $this->m->outputChanneled( "" );
496 $this->m->outputChanneled( "\nb" );
497 $this->m->outputChanneled( "a" );
498 $this->m->outputChanneled( "" );
499 $this->m->outputChanneled( "r" );
500 $this->assertOutputPrePostShutdown( "\nfoo\n\n\nb\na\n\nr\n", false );
501 }
502
503 function testOutputChanneledWNullChannelEmpty() {
504 $this->m->outputChanneled( "", null );
505 $this->assertOutputPrePostShutdown( "\n", false );
506 }
507
508 function testOutputChanneledWNullChannelString() {
509 $this->m->outputChanneled( "foo", null );
510 $this->assertOutputPrePostShutdown( "foo\n", false );
511 }
512
513 function testOutputChanneledWNullChannelStringString() {
514 $this->m->outputChanneled( "foo", null );
515 $this->m->outputChanneled( "bar", null );
516 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
517 }
518
519 function testOutputChanneledWNullChannelStringNLString() {
520 $this->m->outputChanneled( "foo\nbar", null );
521 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
522 }
523
524 function testOutputChanneledWNullChannelStringNLStringNLArbitraryAgain() {
525 $this->m->outputChanneled( "", null );
526 $this->m->outputChanneled( "foo", null );
527 $this->m->outputChanneled( "", null );
528 $this->m->outputChanneled( "\nb", null );
529 $this->m->outputChanneled( "a", null );
530 $this->m->outputChanneled( "", null );
531 $this->m->outputChanneled( "r", null );
532 $this->assertOutputPrePostShutdown( "\nfoo\n\n\nb\na\n\nr\n", false );
533 }
534
535 function testOutputChanneledWChannelString() {
536 $this->m->outputChanneled( "foo", "bazChannel" );
537 $this->assertOutputPrePostShutdown( "foo", true );
538 }
539
540 function testOutputChanneledWChannelStringNLString() {
541 $this->m->outputChanneled( "foo\nbar", "bazChannel" );
542 $this->assertOutputPrePostShutdown( "foo\nbar", true );
543 }
544
545 function testOutputChanneledWChannelStringString() {
546 $this->m->outputChanneled( "foo", "bazChannel" );
547 $this->m->outputChanneled( "bar", "bazChannel" );
548 $this->assertOutputPrePostShutdown( "foobar", true );
549 }
550
551 function testOutputChanneledWChannelStringNLStringNLArbitraryAgain() {
552 $this->m->outputChanneled( "", "bazChannel" );
553 $this->m->outputChanneled( "foo", "bazChannel" );
554 $this->m->outputChanneled( "", "bazChannel" );
555 $this->m->outputChanneled( "\nb", "bazChannel" );
556 $this->m->outputChanneled( "a", "bazChannel" );
557 $this->m->outputChanneled( "", "bazChannel" );
558 $this->m->outputChanneled( "r", "bazChannel" );
559 $this->assertOutputPrePostShutdown( "foo\nbar", true );
560 }
561
562 function testOutputChanneledWMultipleChannelsChannelChange() {
563 $this->m->outputChanneled( "foo", "bazChannel" );
564 $this->m->outputChanneled( "bar", "bazChannel" );
565 $this->m->outputChanneled( "qux", "quuxChannel" );
566 $this->m->outputChanneled( "corge", "bazChannel" );
567 $this->assertOutputPrePostShutdown( "foobar\nqux\ncorge", true );
568 }
569
570 function testOutputChanneledWMultipleChannelsChannelChangeEnclosedNull() {
571 $this->m->outputChanneled( "foo", "bazChannel" );
572 $this->m->outputChanneled( "bar", null );
573 $this->m->outputChanneled( "qux", null );
574 $this->m->outputChanneled( "corge", "bazChannel" );
575 $this->assertOutputPrePostShutdown( "foo\nbar\nqux\ncorge", true );
576 }
577
578 function testOutputChanneledWMultipleChannelsChannelAfterNullChange() {
579 $this->m->outputChanneled( "foo", "bazChannel" );
580 $this->m->outputChanneled( "bar", null );
581 $this->m->outputChanneled( "qux", null );
582 $this->m->outputChanneled( "corge", "quuxChannel" );
583 $this->assertOutputPrePostShutdown( "foo\nbar\nqux\ncorge", true );
584 }
585
586 function testOutputChanneledWAndWOChannelStringStartWO() {
587 $this->m->outputChanneled( "foo" );
588 $this->m->outputChanneled( "bar", "bazChannel" );
589 $this->m->outputChanneled( "qux" );
590 $this->m->outputChanneled( "quux", "bazChannel" );
591 $this->assertOutputPrePostShutdown( "foo\nbar\nqux\nquux", true );
592 }
593
594 function testOutputChanneledWAndWOChannelStringStartW() {
595 $this->m->outputChanneled( "foo", "bazChannel" );
596 $this->m->outputChanneled( "bar" );
597 $this->m->outputChanneled( "qux", "bazChannel" );
598 $this->m->outputChanneled( "quux" );
599 $this->assertOutputPrePostShutdown( "foo\nbar\nqux\nquux\n", false );
600 }
601
602 function testOutputChanneledWChannelTypeSwitch() {
603 $this->m->outputChanneled( "foo", 1 );
604 $this->m->outputChanneled( "bar", 1.0 );
605 $this->assertOutputPrePostShutdown( "foo\nbar", true );
606 }
607
608 function testOutputChanneledWOChannelIntermittentEmpty() {
609 $this->m->outputChanneled( "foo" );
610 $this->m->outputChanneled( "" );
611 $this->m->outputChanneled( "bar" );
612 $this->assertOutputPrePostShutdown( "foo\n\nbar\n", false );
613 }
614
615 function testOutputChanneledWOChannelIntermittentFalse() {
616 $this->m->outputChanneled( "foo" );
617 $this->m->outputChanneled( false );
618 $this->m->outputChanneled( "bar" );
619 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
620 }
621
622 function testOutputChanneledWNullChannelIntermittentEmpty() {
623 $this->m->outputChanneled( "foo", null );
624 $this->m->outputChanneled( "", null );
625 $this->m->outputChanneled( "bar", null );
626 $this->assertOutputPrePostShutdown( "foo\n\nbar\n", false );
627 }
628
629 function testOutputChanneledWNullChannelIntermittentFalse() {
630 $this->m->outputChanneled( "foo", null );
631 $this->m->outputChanneled( false, null );
632 $this->m->outputChanneled( "bar", null );
633 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
634 }
635
636 function testOutputChanneledWChannelIntermittentEmpty() {
637 $this->m->outputChanneled( "foo", "bazChannel" );
638 $this->m->outputChanneled( "", "bazChannel" );
639 $this->m->outputChanneled( "bar", "bazChannel" );
640 $this->assertOutputPrePostShutdown( "foobar", true );
641 }
642
643 function testOutputChanneledWChannelIntermittentFalse() {
644 $this->m->outputChanneled( "foo", "bazChannel" );
645 $this->m->outputChanneled( false, "bazChannel" );
646 $this->m->outputChanneled( "bar", "bazChannel" );
647 $this->assertOutputPrePostShutdown( "foo\nbar", true );
648 }
649
650 function testCleanupChanneledClean() {
651 $this->m->cleanupChanneled();
652 $this->assertOutputPrePostShutdown( "", false );
653 }
654
655 function testCleanupChanneledAfterOutput() {
656 $this->m->output( "foo" );
657 $this->m->cleanupChanneled();
658 $this->assertOutputPrePostShutdown( "foo", false );
659 }
660
661 function testCleanupChanneledAfterOutputWNullChannel() {
662 $this->m->output( "foo", null );
663 $this->m->cleanupChanneled();
664 $this->assertOutputPrePostShutdown( "foo", false );
665 }
666
667 function testCleanupChanneledAfterOutputWChannel() {
668 $this->m->output( "foo", "bazChannel" );
669 $this->m->cleanupChanneled();
670 $this->assertOutputPrePostShutdown( "foo\n", false );
671 }
672
673 function testCleanupChanneledAfterNLOutput() {
674 $this->m->output( "foo\n" );
675 $this->m->cleanupChanneled();
676 $this->assertOutputPrePostShutdown( "foo\n", false );
677 }
678
679 function testCleanupChanneledAfterNLOutputWNullChannel() {
680 $this->m->output( "foo\n", null );
681 $this->m->cleanupChanneled();
682 $this->assertOutputPrePostShutdown( "foo\n", false );
683 }
684
685 function testCleanupChanneledAfterNLOutputWChannel() {
686 $this->m->output( "foo\n", "bazChannel" );
687 $this->m->cleanupChanneled();
688 $this->assertOutputPrePostShutdown( "foo\n", false );
689 }
690
691 function testCleanupChanneledAfterOutputChanneledWOChannel() {
692 $this->m->outputChanneled( "foo" );
693 $this->m->cleanupChanneled();
694 $this->assertOutputPrePostShutdown( "foo\n", false );
695 }
696
697 function testCleanupChanneledAfterOutputChanneledWNullChannel() {
698 $this->m->outputChanneled( "foo", null );
699 $this->m->cleanupChanneled();
700 $this->assertOutputPrePostShutdown( "foo\n", false );
701 }
702
703 function testCleanupChanneledAfterOutputChanneledWChannel() {
704 $this->m->outputChanneled( "foo", "bazChannel" );
705 $this->m->cleanupChanneled();
706 $this->assertOutputPrePostShutdown( "foo\n", false );
707 }
708
709 function testMultipleMaintenanceObjectsInteractionOutput() {
710 $m2 = new MaintenanceFixup( $this );
711
712 $this->m->output( "foo" );
713 $m2->output( "bar" );
714
715 $this->assertEquals( "foobar", $this->getActualOutput(),
716 "Output before shutdown simulation (m2)" );
717 $m2->simulateShutdown();
718 $this->assertOutputPrePostShutdown( "foobar", false );
719 }
720
721 function testMultipleMaintenanceObjectsInteractionOutputWNullChannel() {
722 $m2 = new MaintenanceFixup( $this );
723
724 $this->m->output( "foo", null );
725 $m2->output( "bar", null );
726
727 $this->assertEquals( "foobar", $this->getActualOutput(),
728 "Output before shutdown simulation (m2)" );
729 $m2->simulateShutdown();
730 $this->assertOutputPrePostShutdown( "foobar", false );
731 }
732
733 function testMultipleMaintenanceObjectsInteractionOutputWChannel() {
734 $m2 = new MaintenanceFixup( $this );
735
736 $this->m->output( "foo", "bazChannel" );
737 $m2->output( "bar", "bazChannel" );
738
739 $this->assertEquals( "foobar", $this->getActualOutput(),
740 "Output before shutdown simulation (m2)" );
741 $m2->simulateShutdown();
742 $this->assertOutputPrePostShutdown( "foobar\n", true );
743 }
744
745 function testMultipleMaintenanceObjectsInteractionOutputWNullChannelNL() {
746 $m2 = new MaintenanceFixup( $this );
747
748 $this->m->output( "foo\n", null );
749 $m2->output( "bar\n", null );
750
751 $this->assertEquals( "foo\nbar\n", $this->getActualOutput(),
752 "Output before shutdown simulation (m2)" );
753 $m2->simulateShutdown();
754 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
755 }
756
757 function testMultipleMaintenanceObjectsInteractionOutputWChannelNL() {
758 $m2 = new MaintenanceFixup( $this );
759
760 $this->m->output( "foo\n", "bazChannel" );
761 $m2->output( "bar\n", "bazChannel" );
762
763 $this->assertEquals( "foobar", $this->getActualOutput(),
764 "Output before shutdown simulation (m2)" );
765 $m2->simulateShutdown();
766 $this->assertOutputPrePostShutdown( "foobar\n", true );
767 }
768
769 function testMultipleMaintenanceObjectsInteractionOutputChanneled() {
770 $m2 = new MaintenanceFixup( $this );
771
772 $this->m->outputChanneled( "foo" );
773 $m2->outputChanneled( "bar" );
774
775 $this->assertEquals( "foo\nbar\n", $this->getActualOutput(),
776 "Output before shutdown simulation (m2)" );
777 $m2->simulateShutdown();
778 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
779 }
780
781 function testMultipleMaintenanceObjectsInteractionOutputChanneledWNullChannel() {
782 $m2 = new MaintenanceFixup( $this );
783
784 $this->m->outputChanneled( "foo", null );
785 $m2->outputChanneled( "bar", null );
786
787 $this->assertEquals( "foo\nbar\n", $this->getActualOutput(),
788 "Output before shutdown simulation (m2)" );
789 $m2->simulateShutdown();
790 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
791 }
792
793 function testMultipleMaintenanceObjectsInteractionOutputChanneledWChannel() {
794 $m2 = new MaintenanceFixup( $this );
795
796 $this->m->outputChanneled( "foo", "bazChannel" );
797 $m2->outputChanneled( "bar", "bazChannel" );
798
799 $this->assertEquals( "foobar", $this->getActualOutput(),
800 "Output before shutdown simulation (m2)" );
801 $m2->simulateShutdown();
802 $this->assertOutputPrePostShutdown( "foobar\n", true );
803 }
804
805 function testMultipleMaintenanceObjectsInteractionCleanupChanneledWChannel() {
806 $m2 = new MaintenanceFixup( $this );
807
808 $this->m->outputChanneled( "foo", "bazChannel" );
809 $m2->outputChanneled( "bar", "bazChannel" );
810
811 $this->assertEquals( "foobar", $this->getActualOutput(),
812 "Output before first cleanup" );
813 $this->m->cleanupChanneled();
814 $this->assertEquals( "foobar\n", $this->getActualOutput(),
815 "Output after first cleanup" );
816 $m2->cleanupChanneled();
817 $this->assertEquals( "foobar\n\n", $this->getActualOutput(),
818 "Output after second cleanup" );
819
820 $m2->simulateShutdown();
821 $this->assertOutputPrePostShutdown( "foobar\n\n", false );
822 }
823
824 /**
825 * @covers Maintenance::getConfig
826 */
827 public function testGetConfig() {
828 $this->assertInstanceOf( 'Config', $this->m->getConfig() );
829 $this->assertSame(
830 MediaWikiServices::getInstance()->getMainConfig(),
831 $this->m->getConfig()
832 );
833 }
834
835 /**
836 * @covers Maintenance::setConfig
837 */
838 public function testSetConfig() {
839 $conf = $this->getMock( 'Config' );
840 $this->m->setConfig( $conf );
841 $this->assertSame( $conf, $this->m->getConfig() );
842 }
843
844 function testParseArgs() {
845 $m2 = new MaintenanceFixup( $this );
846 // Create an option with an argument allowed to be specified multiple times
847 $m2->addOption( 'multi', 'This option does stuff', false, true, false, true );
848 $m2->loadWithArgv( [ '--multi', 'this1', '--multi', 'this2' ] );
849
850 $this->assertEquals( [ 'this1', 'this2' ], $m2->getOption( 'multi' ) );
851 $this->assertEquals( [ [ 'multi', 'this1' ], [ 'multi', 'this2' ] ],
852 $m2->orderedOptions );
853
854 $m2->simulateShutdown();
855
856 $m2 = new MaintenanceFixup( $this );
857
858 $m2->addOption( 'multi', 'This option does stuff', false, false, false, true );
859 $m2->loadWithArgv( [ '--multi', '--multi' ] );
860
861 $this->assertEquals( [ 1, 1 ], $m2->getOption( 'multi' ) );
862 $this->assertEquals( [ [ 'multi', 1 ], [ 'multi', 1 ] ], $m2->orderedOptions );
863
864 $m2->simulateShutdown();
865
866 $m2 = new MaintenanceFixup( $this );
867 // Create an option with an argument allowed to be specified multiple times
868 $m2->addOption( 'multi', 'This option doesn\'t actually support multiple occurrences' );
869 $m2->loadWithArgv( [ '--multi=yo' ] );
870
871 $this->assertEquals( 'yo', $m2->getOption( 'multi' ) );
872 $this->assertEquals( [ [ 'multi', 'yo' ] ], $m2->orderedOptions );
873
874 $m2->simulateShutdown();
875 }
876 }