Merge "Warn if stateful ParserOutput transforms are used"
[lhc/web/wiklou.git] / tests / phpunit / maintenance / MaintenanceTest.php
1 <?php
2
3 namespace MediaWiki\Tests\Maintenance;
4
5 use Maintenance;
6 use MediaWiki\MediaWikiServices;
7 use Wikimedia\TestingAccessWrapper;
8
9 /**
10 * @covers Maintenance
11 */
12 class MaintenanceTest extends MaintenanceBaseTestCase {
13
14 /**
15 * @see MaintenanceBaseTestCase::getMaintenanceClass
16 */
17 protected function getMaintenanceClass() {
18 return Maintenance::class;
19 }
20
21 /**
22 * @see MaintenanceBaseTestCase::createMaintenance
23 *
24 * Note to extension authors looking for a model to follow: This function
25 * is normally not needed in a maintenance test, it's only overridden here
26 * because Maintenance is abstract.
27 */
28 protected function createMaintenance() {
29 $className = $this->getMaintenanceClass();
30 $obj = $this->getMockForAbstractClass( $className );
31
32 return TestingAccessWrapper::newFromObject( $obj );
33 }
34
35 // Although the following tests do not seem to be too consistent (compare for
36 // example the newlines within the test.*StringString tests, or the
37 // test.*Intermittent.* tests), the objective of these tests is not to describe
38 // consistent behavior, but rather currently existing behavior.
39
40 /**
41 * @dataProvider provideOutputData
42 */
43 function testOutput( $outputs, $expected, $extraNL ) {
44 foreach ( $outputs as $data ) {
45 if ( is_array( $data ) ) {
46 list( $msg, $channel ) = $data;
47 } else {
48 $msg = $data;
49 $channel = null;
50 }
51 $this->maintenance->output( $msg, $channel );
52 }
53 $this->assertOutputPrePostShutdown( $expected, $extraNL );
54 }
55
56 public function provideOutputData() {
57 return [
58 [ [ "" ], "", false ],
59 [ [ "foo" ], "foo", false ],
60 [ [ "foo", "bar" ], "foobar", false ],
61 [ [ "foo\n" ], "foo\n", false ],
62 [ [ "foo\n\n" ], "foo\n\n", false ],
63 [ [ "foo\nbar" ], "foo\nbar", false ],
64 [ [ "foo\nbar\n" ], "foo\nbar\n", false ],
65 [ [ "foo\n", "bar\n" ], "foo\nbar\n", false ],
66 [ [ "", "foo", "", "\n", "ba", "", "r\n" ], "foo\nbar\n", false ],
67 [ [ "", "foo", "", "\nb", "a", "", "r\n" ], "foo\nbar\n", false ],
68 [ [ [ "foo", "bazChannel" ] ], "foo", true ],
69 [ [ [ "foo\n", "bazChannel" ] ], "foo", true ],
70
71 // If this test fails, note that output takes strings with double line
72 // endings (although output's implementation in this situation calls
73 // outputChanneled with a string ending in a nl ... which is not allowed
74 // according to the documentation of outputChanneled)
75 [ [ [ "foo\n\n", "bazChannel" ] ], "foo\n", true ],
76 [ [ [ "foo\nbar", "bazChannel" ] ], "foo\nbar", true ],
77 [ [ [ "foo\nbar\n", "bazChannel" ] ], "foo\nbar", true ],
78 [
79 [
80 [ "foo\n", "bazChannel" ],
81 [ "bar\n", "bazChannel" ],
82 ],
83 "foobar",
84 true
85 ],
86 [
87 [
88 [ "", "bazChannel" ],
89 [ "foo", "bazChannel" ],
90 [ "", "bazChannel" ],
91 [ "\n", "bazChannel" ],
92 [ "ba", "bazChannel" ],
93 [ "", "bazChannel" ],
94 [ "r\n", "bazChannel" ],
95 ],
96 "foobar",
97 true
98 ],
99 [
100 [
101 [ "", "bazChannel" ],
102 [ "foo", "bazChannel" ],
103 [ "", "bazChannel" ],
104 [ "\nb", "bazChannel" ],
105 [ "a", "bazChannel" ],
106 [ "", "bazChannel" ],
107 [ "r\n", "bazChannel" ],
108 ],
109 "foo\nbar",
110 true
111 ],
112 [
113 [
114 [ "foo", "bazChannel" ],
115 [ "bar", "bazChannel" ],
116 [ "qux", "quuxChannel" ],
117 [ "corge", "bazChannel" ],
118 ],
119 "foobar\nqux\ncorge",
120 true
121 ],
122 [
123 [
124 [ "foo", "bazChannel" ],
125 [ "bar\n", "bazChannel" ],
126 [ "qux\n", "quuxChannel" ],
127 [ "corge", "bazChannel" ],
128 ],
129 "foobar\nqux\ncorge",
130 true
131 ],
132 [
133 [
134 [ "foo", null ],
135 [ "bar", "bazChannel" ],
136 [ "qux", null ],
137 [ "quux", "bazChannel" ],
138 ],
139 "foobar\nquxquux",
140 true
141 ],
142 [
143 [
144 [ "foo", "bazChannel" ],
145 [ "bar", null ],
146 [ "qux", "bazChannel" ],
147 [ "quux", null ],
148 ],
149 "foo\nbarqux\nquux",
150 false
151 ],
152 [
153 [
154 [ "foo", 1 ],
155 [ "bar", 1.0 ],
156 ],
157 "foo\nbar",
158 true
159 ],
160 [ [ "foo", "", "bar" ], "foobar", false ],
161 [ [ "foo", false, "bar" ], "foobar", false ],
162 [
163 [
164 [ "qux", "quuxChannel" ],
165 "foo",
166 false,
167 "bar"
168 ],
169 "qux\nfoobar",
170 false
171 ],
172 [
173 [
174 [ "foo", "bazChannel" ],
175 [ "", "bazChannel" ],
176 [ "bar", "bazChannel" ],
177 ],
178 "foobar",
179 true
180 ],
181 [
182 [
183 [ "foo", "bazChannel" ],
184 [ false, "bazChannel" ],
185 [ "bar", "bazChannel" ],
186 ],
187 "foobar",
188 true
189 ],
190 ];
191 }
192
193 /**
194 * @dataProvider provideOutputChanneledData
195 */
196 function testOutputChanneled( $outputs, $expected, $extraNL ) {
197 foreach ( $outputs as $data ) {
198 if ( is_array( $data ) ) {
199 list( $msg, $channel ) = $data;
200 } else {
201 $msg = $data;
202 $channel = null;
203 }
204 $this->maintenance->outputChanneled( $msg, $channel );
205 }
206 $this->assertOutputPrePostShutdown( $expected, $extraNL );
207 }
208
209 public function provideOutputChanneledData() {
210 return [
211 [ [ "" ], "\n", false ],
212 [ [ "foo" ], "foo\n", false ],
213 [ [ "foo", "bar" ], "foo\nbar\n", false ],
214 [ [ "foo\nbar" ], "foo\nbar\n", false ],
215 [ [ "", "foo", "", "\nb", "a", "", "r" ], "\nfoo\n\n\nb\na\n\nr\n", false ],
216 [ [ [ "foo", "bazChannel" ] ], "foo", true ],
217 [
218 [
219 [ "foo\nbar", "bazChannel" ]
220 ],
221 "foo\nbar",
222 true
223 ],
224 [
225 [
226 [ "foo", "bazChannel" ],
227 [ "bar", "bazChannel" ],
228 ],
229 "foobar",
230 true
231 ],
232 [
233 [
234 [ "", "bazChannel" ],
235 [ "foo", "bazChannel" ],
236 [ "", "bazChannel" ],
237 [ "\nb", "bazChannel" ],
238 [ "a", "bazChannel" ],
239 [ "", "bazChannel" ],
240 [ "r", "bazChannel" ],
241 ],
242 "foo\nbar",
243 true
244 ],
245 [
246 [
247 [ "foo", "bazChannel" ],
248 [ "bar", "bazChannel" ],
249 [ "qux", "quuxChannel" ],
250 [ "corge", "bazChannel" ],
251 ],
252 "foobar\nqux\ncorge",
253 true
254 ],
255 [
256 [
257 [ "foo", "bazChannel" ],
258 [ "bar", "bazChannel" ],
259 [ "qux", "quuxChannel" ],
260 [ "corge", "bazChannel" ],
261 ],
262 "foobar\nqux\ncorge",
263 true
264 ],
265 [
266 [
267 [ "foo", "bazChannel" ],
268 [ "bar", null ],
269 [ "qux", null ],
270 [ "corge", "bazChannel" ],
271 ],
272 "foo\nbar\nqux\ncorge",
273 true
274 ],
275 [
276 [
277 [ "foo", null ],
278 [ "bar", "bazChannel" ],
279 [ "qux", null ],
280 [ "quux", "bazChannel" ],
281 ],
282 "foo\nbar\nqux\nquux",
283 true
284 ],
285 [
286 [
287 [ "foo", "bazChannel" ],
288 [ "bar", null ],
289 [ "qux", "bazChannel" ],
290 [ "quux", null ],
291 ],
292 "foo\nbar\nqux\nquux\n",
293 false
294 ],
295 [
296 [
297 [ "foo", 1 ],
298 [ "bar", 1.0 ],
299 ],
300 "foo\nbar",
301 true
302 ],
303 [ [ "foo", "", "bar" ], "foo\n\nbar\n", false ],
304 [ [ "foo", false, "bar" ], "foo\nbar\n", false ],
305 ];
306 }
307
308 function testCleanupChanneledClean() {
309 $this->maintenance->cleanupChanneled();
310 $this->assertOutputPrePostShutdown( "", false );
311 }
312
313 function testCleanupChanneledAfterOutput() {
314 $this->maintenance->output( "foo" );
315 $this->maintenance->cleanupChanneled();
316 $this->assertOutputPrePostShutdown( "foo", false );
317 }
318
319 function testCleanupChanneledAfterOutputWNullChannel() {
320 $this->maintenance->output( "foo", null );
321 $this->maintenance->cleanupChanneled();
322 $this->assertOutputPrePostShutdown( "foo", false );
323 }
324
325 function testCleanupChanneledAfterOutputWChannel() {
326 $this->maintenance->output( "foo", "bazChannel" );
327 $this->maintenance->cleanupChanneled();
328 $this->assertOutputPrePostShutdown( "foo\n", false );
329 }
330
331 function testCleanupChanneledAfterNLOutput() {
332 $this->maintenance->output( "foo\n" );
333 $this->maintenance->cleanupChanneled();
334 $this->assertOutputPrePostShutdown( "foo\n", false );
335 }
336
337 function testCleanupChanneledAfterNLOutputWNullChannel() {
338 $this->maintenance->output( "foo\n", null );
339 $this->maintenance->cleanupChanneled();
340 $this->assertOutputPrePostShutdown( "foo\n", false );
341 }
342
343 function testCleanupChanneledAfterNLOutputWChannel() {
344 $this->maintenance->output( "foo\n", "bazChannel" );
345 $this->maintenance->cleanupChanneled();
346 $this->assertOutputPrePostShutdown( "foo\n", false );
347 }
348
349 function testCleanupChanneledAfterOutputChanneledWOChannel() {
350 $this->maintenance->outputChanneled( "foo" );
351 $this->maintenance->cleanupChanneled();
352 $this->assertOutputPrePostShutdown( "foo\n", false );
353 }
354
355 function testCleanupChanneledAfterOutputChanneledWNullChannel() {
356 $this->maintenance->outputChanneled( "foo", null );
357 $this->maintenance->cleanupChanneled();
358 $this->assertOutputPrePostShutdown( "foo\n", false );
359 }
360
361 function testCleanupChanneledAfterOutputChanneledWChannel() {
362 $this->maintenance->outputChanneled( "foo", "bazChannel" );
363 $this->maintenance->cleanupChanneled();
364 $this->assertOutputPrePostShutdown( "foo\n", false );
365 }
366
367 function testMultipleMaintenanceObjectsInteractionOutput() {
368 $m2 = $this->createMaintenance();
369
370 $this->maintenance->output( "foo" );
371 $m2->output( "bar" );
372
373 $this->assertEquals( "foobar", $this->getActualOutput(),
374 "Output before shutdown simulation (m2)" );
375 $m2->cleanupChanneled();
376 $this->assertOutputPrePostShutdown( "foobar", false );
377 }
378
379 function testMultipleMaintenanceObjectsInteractionOutputWNullChannel() {
380 $m2 = $this->createMaintenance();
381
382 $this->maintenance->output( "foo", null );
383 $m2->output( "bar", null );
384
385 $this->assertEquals( "foobar", $this->getActualOutput(),
386 "Output before shutdown simulation (m2)" );
387 $m2->cleanupChanneled();
388 $this->assertOutputPrePostShutdown( "foobar", false );
389 }
390
391 function testMultipleMaintenanceObjectsInteractionOutputWChannel() {
392 $m2 = $this->createMaintenance();
393
394 $this->maintenance->output( "foo", "bazChannel" );
395 $m2->output( "bar", "bazChannel" );
396
397 $this->assertEquals( "foobar", $this->getActualOutput(),
398 "Output before shutdown simulation (m2)" );
399 $m2->cleanupChanneled();
400 $this->assertOutputPrePostShutdown( "foobar\n", true );
401 }
402
403 function testMultipleMaintenanceObjectsInteractionOutputWNullChannelNL() {
404 $m2 = $this->createMaintenance();
405
406 $this->maintenance->output( "foo\n", null );
407 $m2->output( "bar\n", null );
408
409 $this->assertEquals( "foo\nbar\n", $this->getActualOutput(),
410 "Output before shutdown simulation (m2)" );
411 $m2->cleanupChanneled();
412 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
413 }
414
415 function testMultipleMaintenanceObjectsInteractionOutputWChannelNL() {
416 $m2 = $this->createMaintenance();
417
418 $this->maintenance->output( "foo\n", "bazChannel" );
419 $m2->output( "bar\n", "bazChannel" );
420
421 $this->assertEquals( "foobar", $this->getActualOutput(),
422 "Output before shutdown simulation (m2)" );
423 $m2->cleanupChanneled();
424 $this->assertOutputPrePostShutdown( "foobar\n", true );
425 }
426
427 function testMultipleMaintenanceObjectsInteractionOutputChanneled() {
428 $m2 = $this->createMaintenance();
429
430 $this->maintenance->outputChanneled( "foo" );
431 $m2->outputChanneled( "bar" );
432
433 $this->assertEquals( "foo\nbar\n", $this->getActualOutput(),
434 "Output before shutdown simulation (m2)" );
435 $m2->cleanupChanneled();
436 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
437 }
438
439 function testMultipleMaintenanceObjectsInteractionOutputChanneledWNullChannel() {
440 $m2 = $this->createMaintenance();
441
442 $this->maintenance->outputChanneled( "foo", null );
443 $m2->outputChanneled( "bar", null );
444
445 $this->assertEquals( "foo\nbar\n", $this->getActualOutput(),
446 "Output before shutdown simulation (m2)" );
447 $m2->cleanupChanneled();
448 $this->assertOutputPrePostShutdown( "foo\nbar\n", false );
449 }
450
451 function testMultipleMaintenanceObjectsInteractionOutputChanneledWChannel() {
452 $m2 = $this->createMaintenance();
453
454 $this->maintenance->outputChanneled( "foo", "bazChannel" );
455 $m2->outputChanneled( "bar", "bazChannel" );
456
457 $this->assertEquals( "foobar", $this->getActualOutput(),
458 "Output before shutdown simulation (m2)" );
459 $m2->cleanupChanneled();
460 $this->assertOutputPrePostShutdown( "foobar\n", true );
461 }
462
463 function testMultipleMaintenanceObjectsInteractionCleanupChanneledWChannel() {
464 $m2 = $this->createMaintenance();
465
466 $this->maintenance->outputChanneled( "foo", "bazChannel" );
467 $m2->outputChanneled( "bar", "bazChannel" );
468
469 $this->assertEquals( "foobar", $this->getActualOutput(),
470 "Output before first cleanup" );
471 $this->maintenance->cleanupChanneled();
472 $this->assertEquals( "foobar\n", $this->getActualOutput(),
473 "Output after first cleanup" );
474 $m2->cleanupChanneled();
475 $this->assertEquals( "foobar\n\n", $this->getActualOutput(),
476 "Output after second cleanup" );
477
478 $m2->cleanupChanneled();
479 $this->assertOutputPrePostShutdown( "foobar\n\n", false );
480 }
481
482 /**
483 * @covers Maintenance::getConfig
484 */
485 public function testGetConfig() {
486 $this->assertInstanceOf( 'Config', $this->maintenance->getConfig() );
487 $this->assertSame(
488 MediaWikiServices::getInstance()->getMainConfig(),
489 $this->maintenance->getConfig()
490 );
491 }
492
493 /**
494 * @covers Maintenance::setConfig
495 */
496 public function testSetConfig() {
497 $conf = $this->createMock( 'Config' );
498 $this->maintenance->setConfig( $conf );
499 $this->assertSame( $conf, $this->maintenance->getConfig() );
500 }
501
502 function testParseArgs() {
503 $m2 = $this->createMaintenance();
504
505 // Create an option with an argument allowed to be specified multiple times
506 $m2->addOption( 'multi', 'This option does stuff', false, true, false, true );
507 $m2->loadWithArgv( [ '--multi', 'this1', '--multi', 'this2' ] );
508
509 $this->assertEquals( [ 'this1', 'this2' ], $m2->getOption( 'multi' ) );
510 $this->assertEquals( [ [ 'multi', 'this1' ], [ 'multi', 'this2' ] ],
511 $m2->orderedOptions );
512
513 $m2->cleanupChanneled();
514
515 $m2 = $this->createMaintenance();
516
517 $m2->addOption( 'multi', 'This option does stuff', false, false, false, true );
518 $m2->loadWithArgv( [ '--multi', '--multi' ] );
519
520 $this->assertEquals( [ 1, 1 ], $m2->getOption( 'multi' ) );
521 $this->assertEquals( [ [ 'multi', 1 ], [ 'multi', 1 ] ], $m2->orderedOptions );
522
523 $m2->cleanupChanneled();
524
525 $m2 = $this->createMaintenance();
526
527 // Create an option with an argument allowed to be specified multiple times
528 $m2->addOption( 'multi', 'This option doesn\'t actually support multiple occurrences' );
529 $m2->loadWithArgv( [ '--multi=yo' ] );
530
531 $this->assertEquals( 'yo', $m2->getOption( 'multi' ) );
532 $this->assertEquals( [ [ 'multi', 'yo' ] ], $m2->orderedOptions );
533
534 $m2->cleanupChanneled();
535 }
536 }