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