Merge "maintenance: Script to rename titles for Unicode uppercasing changes"
[lhc/web/wiklou.git] / tests / phpunit / includes / GlobalFunctions / GlobalTest.php
1 <?php
2
3 use MediaWiki\Logger\LegacyLogger;
4
5 /**
6 * @group Database
7 * @group GlobalFunctions
8 */
9 class GlobalTest extends MediaWikiTestCase {
10 protected function setUp() {
11 parent::setUp();
12
13 $readOnlyFile = $this->getNewTempFile();
14 unlink( $readOnlyFile );
15
16 $this->setMwGlobals( [
17 'wgReadOnly' => null,
18 'wgReadOnlyFile' => $readOnlyFile,
19 'wgUrlProtocols' => [
20 'http://',
21 'https://',
22 'mailto:',
23 '//',
24 'file://', # Non-default
25 ],
26 ] );
27 }
28
29 /**
30 * @dataProvider provideForWfArrayDiff2
31 * @covers ::wfArrayDiff2
32 */
33 public function testWfArrayDiff2( $a, $b, $expected ) {
34 $this->assertEquals(
35 wfArrayDiff2( $a, $b ), $expected
36 );
37 }
38
39 // @todo Provide more tests
40 public static function provideForWfArrayDiff2() {
41 // $a $b $expected
42 return [
43 [
44 [ 'a', 'b' ],
45 [ 'a', 'b' ],
46 [],
47 ],
48 [
49 [ [ 'a' ], [ 'a', 'b', 'c' ] ],
50 [ [ 'a' ], [ 'a', 'b' ] ],
51 [ 1 => [ 'a', 'b', 'c' ] ],
52 ],
53 ];
54 }
55
56 /*
57 * Test cases for random functions could hypothetically fail,
58 * even though they shouldn't.
59 */
60
61 /**
62 * @covers ::wfRandom
63 */
64 public function testRandom() {
65 $this->assertFalse(
66 wfRandom() == wfRandom()
67 );
68 }
69
70 /**
71 * @covers ::wfRandomString
72 */
73 public function testRandomString() {
74 $this->assertFalse(
75 wfRandomString() == wfRandomString()
76 );
77 $this->assertSame( 10, strlen( wfRandomString( 10 ) ), 'length' );
78 $this->assertSame( 1, preg_match( '/^[0-9a-f]+$/i', wfRandomString() ), 'pattern' );
79 }
80
81 /**
82 * @covers ::wfUrlencode
83 */
84 public function testUrlencode() {
85 $this->assertEquals(
86 "%E7%89%B9%E5%88%A5:Contributions/Foobar",
87 wfUrlencode( "\xE7\x89\xB9\xE5\x88\xA5:Contributions/Foobar" ) );
88 }
89
90 /**
91 * @covers ::wfExpandIRI
92 */
93 public function testExpandIRI() {
94 $this->assertEquals(
95 "https://te.wikibooks.org/wiki/ఉబుంటు_వాడుకరి_మార్గదర్శని",
96 wfExpandIRI( "https://te.wikibooks.org/wiki/"
97 . "%E0%B0%89%E0%B0%AC%E0%B1%81%E0%B0%82%E0%B0%9F%E0%B1%81_"
98 . "%E0%B0%B5%E0%B0%BE%E0%B0%A1%E0%B1%81%E0%B0%95%E0%B0%B0%E0%B0%BF_"
99 . "%E0%B0%AE%E0%B0%BE%E0%B0%B0%E0%B1%8D%E0%B0%97%E0%B0%A6%E0%B0%B0"
100 . "%E0%B1%8D%E0%B0%B6%E0%B0%A8%E0%B0%BF" ) );
101 }
102
103 /**
104 * Intended to cover the relevant bits of ServiceWiring.php, as well as GlobalFunctions.php
105 * @covers ::wfReadOnly
106 */
107 public function testReadOnlyEmpty() {
108 $this->assertFalse( wfReadOnly() );
109 $this->assertFalse( wfReadOnly() );
110 }
111
112 /**
113 * Intended to cover the relevant bits of ServiceWiring.php, as well as GlobalFunctions.php
114 * @covers ::wfReadOnly
115 */
116 public function testReadOnlySet() {
117 global $wgReadOnlyFile;
118
119 $f = fopen( $wgReadOnlyFile, "wt" );
120 fwrite( $f, 'Message' );
121 fclose( $f );
122
123 // Reset the service to avoid cached results
124 $this->overrideMwServices();
125
126 $this->assertTrue( wfReadOnly() );
127 $this->assertTrue( wfReadOnly() ); # Check cached
128 }
129
130 /**
131 * This behaviour could probably be deprecated. Several extensions rely on it as of 1.29.
132 * @covers ::wfReadOnlyReason
133 */
134 public function testReadOnlyGlobalChange() {
135 $this->assertFalse( wfReadOnlyReason() );
136
137 $this->setMwGlobals( [
138 'wgReadOnly' => 'reason'
139 ] );
140 $this->overrideMwServices();
141
142 $this->assertSame( 'reason', wfReadOnlyReason() );
143 }
144
145 public static function provideArrayToCGI() {
146 return [
147 [ [], '' ], // empty
148 [ [ 'foo' => 'bar' ], 'foo=bar' ], // string test
149 [ [ 'foo' => '' ], 'foo=' ], // empty string test
150 [ [ 'foo' => 1 ], 'foo=1' ], // number test
151 [ [ 'foo' => true ], 'foo=1' ], // true test
152 [ [ 'foo' => false ], '' ], // false test
153 [ [ 'foo' => null ], '' ], // null test
154 [ [ 'foo' => 'A&B=5+6@!"\'' ], 'foo=A%26B%3D5%2B6%40%21%22%27' ], // urlencoding test
155 [
156 [ 'foo' => 'bar', 'baz' => 'is', 'asdf' => 'qwerty' ],
157 'foo=bar&baz=is&asdf=qwerty'
158 ], // multi-item test
159 [ [ 'foo' => [ 'bar' => 'baz' ] ], 'foo%5Bbar%5D=baz' ],
160 [
161 [ 'foo' => [ 'bar' => 'baz', 'qwerty' => 'asdf' ] ],
162 'foo%5Bbar%5D=baz&foo%5Bqwerty%5D=asdf'
163 ],
164 [ [ 'foo' => [ 'bar', 'baz' ] ], 'foo%5B0%5D=bar&foo%5B1%5D=baz' ],
165 [
166 [ 'foo' => [ 'bar' => [ 'bar' => 'baz' ] ] ],
167 'foo%5Bbar%5D%5Bbar%5D=baz'
168 ],
169 ];
170 }
171
172 /**
173 * @dataProvider provideArrayToCGI
174 * @covers ::wfArrayToCgi
175 */
176 public function testArrayToCGI( $array, $result ) {
177 $this->assertEquals( $result, wfArrayToCgi( $array ) );
178 }
179
180 /**
181 * @covers ::wfArrayToCgi
182 */
183 public function testArrayToCGI2() {
184 $this->assertEquals(
185 "baz=bar&foo=bar",
186 wfArrayToCgi(
187 [ 'baz' => 'bar' ],
188 [ 'foo' => 'bar', 'baz' => 'overridden value' ] ) );
189 }
190
191 public static function provideCgiToArray() {
192 return [
193 [ '', [] ], // empty
194 [ 'foo=bar', [ 'foo' => 'bar' ] ], // string
195 [ 'foo=', [ 'foo' => '' ] ], // empty string
196 [ 'foo', [ 'foo' => '' ] ], // missing =
197 [ 'foo=bar&qwerty=asdf', [ 'foo' => 'bar', 'qwerty' => 'asdf' ] ], // multiple value
198 [ 'foo=A%26B%3D5%2B6%40%21%22%27', [ 'foo' => 'A&B=5+6@!"\'' ] ], // urldecoding test
199 [ 'foo%5Bbar%5D=baz', [ 'foo' => [ 'bar' => 'baz' ] ] ],
200 [
201 'foo%5Bbar%5D=baz&foo%5Bqwerty%5D=asdf',
202 [ 'foo' => [ 'bar' => 'baz', 'qwerty' => 'asdf' ] ]
203 ],
204 [ 'foo%5B0%5D=bar&foo%5B1%5D=baz', [ 'foo' => [ 0 => 'bar', 1 => 'baz' ] ] ],
205 [
206 'foo%5Bbar%5D%5Bbar%5D=baz',
207 [ 'foo' => [ 'bar' => [ 'bar' => 'baz' ] ] ]
208 ],
209 ];
210 }
211
212 /**
213 * @dataProvider provideCgiToArray
214 * @covers ::wfCgiToArray
215 */
216 public function testCgiToArray( $cgi, $result ) {
217 $this->assertEquals( $result, wfCgiToArray( $cgi ) );
218 }
219
220 public static function provideCgiRoundTrip() {
221 return [
222 [ '' ],
223 [ 'foo=bar' ],
224 [ 'foo=' ],
225 [ 'foo=bar&baz=biz' ],
226 [ 'foo=A%26B%3D5%2B6%40%21%22%27' ],
227 [ 'foo%5Bbar%5D=baz' ],
228 [ 'foo%5B0%5D=bar&foo%5B1%5D=baz' ],
229 [ 'foo%5Bbar%5D%5Bbar%5D=baz' ],
230 ];
231 }
232
233 /**
234 * @dataProvider provideCgiRoundTrip
235 * @covers ::wfArrayToCgi
236 */
237 public function testCgiRoundTrip( $cgi ) {
238 $this->assertEquals( $cgi, wfArrayToCgi( wfCgiToArray( $cgi ) ) );
239 }
240
241 /**
242 * @covers ::mimeTypeMatch
243 */
244 public function testMimeTypeMatch() {
245 $this->assertEquals(
246 'text/html',
247 mimeTypeMatch( 'text/html',
248 [ 'application/xhtml+xml' => 1.0,
249 'text/html' => 0.7,
250 'text/plain' => 0.3 ] ) );
251 $this->assertEquals(
252 'text/*',
253 mimeTypeMatch( 'text/html',
254 [ 'image/*' => 1.0,
255 'text/*' => 0.5 ] ) );
256 $this->assertEquals(
257 '*/*',
258 mimeTypeMatch( 'text/html',
259 [ '*/*' => 1.0 ] ) );
260 $this->assertNull(
261 mimeTypeMatch( 'text/html',
262 [ 'image/png' => 1.0,
263 'image/svg+xml' => 0.5 ] ) );
264 }
265
266 /**
267 * @covers ::wfNegotiateType
268 */
269 public function testNegotiateType() {
270 $this->assertEquals(
271 'text/html',
272 wfNegotiateType(
273 [ 'application/xhtml+xml' => 1.0,
274 'text/html' => 0.7,
275 'text/plain' => 0.5,
276 'text/*' => 0.2 ],
277 [ 'text/html' => 1.0 ] ) );
278 $this->assertEquals(
279 'application/xhtml+xml',
280 wfNegotiateType(
281 [ 'application/xhtml+xml' => 1.0,
282 'text/html' => 0.7,
283 'text/plain' => 0.5,
284 'text/*' => 0.2 ],
285 [ 'application/xhtml+xml' => 1.0,
286 'text/html' => 0.5 ] ) );
287 $this->assertEquals(
288 'text/html',
289 wfNegotiateType(
290 [ 'text/html' => 1.0,
291 'text/plain' => 0.5,
292 'text/*' => 0.5,
293 'application/xhtml+xml' => 0.2 ],
294 [ 'application/xhtml+xml' => 1.0,
295 'text/html' => 0.5 ] ) );
296 $this->assertEquals(
297 'text/html',
298 wfNegotiateType(
299 [ 'text/*' => 1.0,
300 'image/*' => 0.7,
301 '*/*' => 0.3 ],
302 [ 'application/xhtml+xml' => 1.0,
303 'text/html' => 0.5 ] ) );
304 $this->assertNull(
305 wfNegotiateType(
306 [ 'text/*' => 1.0 ],
307 [ 'application/xhtml+xml' => 1.0 ] ) );
308 }
309
310 /**
311 * @covers ::wfDebug
312 * @covers ::wfDebugMem
313 */
314 public function testDebugFunctionTest() {
315 $debugLogFile = $this->getNewTempFile();
316
317 $this->setMwGlobals( [
318 'wgDebugLogFile' => $debugLogFile,
319 #  @todo FIXME: $wgDebugTimestamps should be tested
320 'wgDebugTimestamps' => false,
321 ] );
322 $this->setLogger( 'wfDebug', new LegacyLogger( 'wfDebug' ) );
323
324 wfDebug( "This is a normal string" );
325 $this->assertEquals( "This is a normal string\n", file_get_contents( $debugLogFile ) );
326 unlink( $debugLogFile );
327
328 wfDebug( "This is nöt an ASCII string" );
329 $this->assertEquals( "This is nöt an ASCII string\n", file_get_contents( $debugLogFile ) );
330 unlink( $debugLogFile );
331
332 wfDebug( "\00305This has böth UTF and control chars\003" );
333 $this->assertEquals(
334 " 05This has böth UTF and control chars \n",
335 file_get_contents( $debugLogFile )
336 );
337 unlink( $debugLogFile );
338
339 wfDebugMem();
340 $this->assertGreaterThan(
341 1000,
342 preg_replace( '/\D/', '', file_get_contents( $debugLogFile ) )
343 );
344 unlink( $debugLogFile );
345
346 wfDebugMem( true );
347 $this->assertGreaterThan(
348 1000000,
349 preg_replace( '/\D/', '', file_get_contents( $debugLogFile ) )
350 );
351 unlink( $debugLogFile );
352 }
353
354 /**
355 * @covers ::wfClientAcceptsGzip
356 */
357 public function testClientAcceptsGzipTest() {
358 $settings = [
359 'gzip' => true,
360 'bzip' => false,
361 '*' => false,
362 'compress, gzip' => true,
363 'gzip;q=1.0' => true,
364 'foozip' => false,
365 'foo*zip' => false,
366 'gzip;q=abcde' => true, // is this REALLY valid?
367 'gzip;q=12345678.9' => true,
368 ' gzip' => true,
369 ];
370
371 if ( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) {
372 $old_server_setting = $_SERVER['HTTP_ACCEPT_ENCODING'];
373 }
374
375 foreach ( $settings as $encoding => $expect ) {
376 $_SERVER['HTTP_ACCEPT_ENCODING'] = $encoding;
377
378 $this->assertEquals( $expect, wfClientAcceptsGzip( true ),
379 "'$encoding' => " . wfBoolToStr( $expect ) );
380 }
381
382 if ( isset( $old_server_setting ) ) {
383 $_SERVER['HTTP_ACCEPT_ENCODING'] = $old_server_setting;
384 }
385 }
386
387 /**
388 * @covers ::wfPercent
389 */
390 public function testWfPercentTest() {
391 $pcts = [
392 [ 6 / 7, '0.86%', 2, false ],
393 [ 3 / 3, '1%' ],
394 [ 22 / 7, '3.14286%', 5 ],
395 [ 3 / 6, '0.5%' ],
396 [ 1 / 3, '0%', 0 ],
397 [ 10 / 3, '0%', -1 ],
398 [ 3 / 4 / 5, '0.1%', 1 ],
399 [ 6 / 7 * 8, '6.8571428571%', 10 ],
400 ];
401
402 foreach ( $pcts as $pct ) {
403 if ( !isset( $pct[2] ) ) {
404 $pct[2] = 2;
405 }
406 if ( !isset( $pct[3] ) ) {
407 $pct[3] = true;
408 }
409
410 $this->assertEquals( wfPercent( $pct[0], $pct[2], $pct[3] ), $pct[1], $pct[1] );
411 }
412 }
413
414 /**
415 * test @see wfShorthandToInteger()
416 * @dataProvider provideShorthand
417 * @covers ::wfShorthandToInteger
418 */
419 public function testWfShorthandToInteger( $shorthand, $expected ) {
420 $this->assertEquals( $expected,
421 wfShorthandToInteger( $shorthand )
422 );
423 }
424
425 public static function provideShorthand() {
426 // Syntax: [ shorthand, expected integer ]
427 return [
428 # Null, empty ...
429 [ '', -1 ],
430 [ ' ', -1 ],
431 [ null, -1 ],
432
433 # Failures returns 0 :(
434 [ 'ABCDEFG', 0 ],
435 [ 'Ak', 0 ],
436
437 # Int, strings with spaces
438 [ 1, 1 ],
439 [ ' 1 ', 1 ],
440 [ 1023, 1023 ],
441 [ ' 1023 ', 1023 ],
442
443 # kilo, Mega, Giga
444 [ '1k', 1024 ],
445 [ '1K', 1024 ],
446 [ '1m', 1024 * 1024 ],
447 [ '1M', 1024 * 1024 ],
448 [ '1g', 1024 * 1024 * 1024 ],
449 [ '1G', 1024 * 1024 * 1024 ],
450
451 # Negatives
452 [ -1, -1 ],
453 [ -500, -500 ],
454 [ '-500', -500 ],
455 [ '-1k', -1024 ],
456
457 # Zeroes
458 [ '0', 0 ],
459 [ '0k', 0 ],
460 [ '0M', 0 ],
461 [ '0G', 0 ],
462 [ '-0', 0 ],
463 [ '-0k', 0 ],
464 [ '-0M', 0 ],
465 [ '-0G', 0 ],
466 ];
467 }
468
469 /**
470 * @covers ::wfMerge
471 */
472 public function testMerge_worksWithLessParameters() {
473 $this->markTestSkippedIfNoDiff3();
474
475 $mergedText = null;
476 $successfulMerge = wfMerge( "old1\n\nold2", "old1\n\nnew2", "new1\n\nold2", $mergedText );
477
478 $mergedText = null;
479 $conflictingMerge = wfMerge( 'old', 'old and mine', 'old and yours', $mergedText );
480
481 $this->assertEquals( true, $successfulMerge );
482 $this->assertEquals( false, $conflictingMerge );
483 }
484
485 /**
486 * @param string $old Text as it was in the database
487 * @param string $mine Text submitted while user was editing
488 * @param string $yours Text submitted by the user
489 * @param bool $expectedMergeResult Whether the merge should be a success
490 * @param string $expectedText Text after merge has been completed
491 * @param string $expectedMergeAttemptResult Diff3 output if conflicts occur
492 *
493 * @dataProvider provideMerge()
494 * @group medium
495 * @covers ::wfMerge
496 */
497 public function testMerge( $old, $mine, $yours, $expectedMergeResult, $expectedText,
498 $expectedMergeAttemptResult ) {
499 $this->markTestSkippedIfNoDiff3();
500
501 $mergedText = null;
502 $attemptMergeResult = null;
503 $isMerged = wfMerge( $old, $mine, $yours, $mergedText, $mergeAttemptResult );
504
505 $msg = 'Merge should be a ';
506 $msg .= $expectedMergeResult ? 'success' : 'failure';
507 $this->assertEquals( $expectedMergeResult, $isMerged, $msg );
508 $this->assertEquals( $expectedMergeAttemptResult, $mergeAttemptResult );
509
510 if ( $isMerged ) {
511 // Verify the merged text
512 $this->assertEquals( $expectedText, $mergedText,
513 'is merged text as expected?' );
514 }
515 }
516
517 public static function provideMerge() {
518 $EXPECT_MERGE_SUCCESS = true;
519 $EXPECT_MERGE_FAILURE = false;
520
521 return [
522 // #0: clean merge
523 [
524 // old:
525 "one one one\n" . // trimmed
526 "\n" .
527 "two two two",
528
529 // mine:
530 "one one one ONE ONE\n" .
531 "\n" .
532 "two two two\n", // with tailing whitespace
533
534 // yours:
535 "one one one\n" .
536 "\n" .
537 "two two TWO TWO", // trimmed
538
539 // ok:
540 $EXPECT_MERGE_SUCCESS,
541
542 // result:
543 "one one one ONE ONE\n" .
544 "\n" .
545 "two two TWO TWO\n", // note: will always end in a newline
546
547 // mergeAttemptResult:
548 "",
549 ],
550
551 // #1: conflict, fail
552 [
553 // old:
554 "one one one", // trimmed
555
556 // mine:
557 "one one one ONE ONE\n" .
558 "\n" .
559 "bla bla\n" .
560 "\n", // with tailing whitespace
561
562 // yours:
563 "one one one\n" .
564 "\n" .
565 "two two", // trimmed
566
567 $EXPECT_MERGE_FAILURE,
568
569 // result:
570 null,
571
572 // mergeAttemptResult:
573 "1,3c\n" .
574 "one one one\n" .
575 "\n" .
576 "two two\n" .
577 ".\n",
578 ],
579 ];
580 }
581
582 /**
583 * @dataProvider provideWfMatchesDomainList
584 * @covers ::wfMatchesDomainList
585 */
586 public function testWfMatchesDomainList( $url, $domains, $expected, $description ) {
587 $actual = wfMatchesDomainList( $url, $domains );
588 $this->assertEquals( $expected, $actual, $description );
589 }
590
591 public static function provideWfMatchesDomainList() {
592 $a = [];
593 $protocols = [ 'HTTP' => 'http:', 'HTTPS' => 'https:', 'protocol-relative' => '' ];
594 foreach ( $protocols as $pDesc => $p ) {
595 $a = array_merge( $a, [
596 [
597 "$p//www.example.com",
598 [],
599 false,
600 "No matches for empty domains array, $pDesc URL"
601 ],
602 [
603 "$p//www.example.com",
604 [ 'www.example.com' ],
605 true,
606 "Exact match in domains array, $pDesc URL"
607 ],
608 [
609 "$p//www.example.com",
610 [ 'example.com' ],
611 true,
612 "Match without subdomain in domains array, $pDesc URL"
613 ],
614 [
615 "$p//www.example2.com",
616 [ 'www.example.com', 'www.example2.com', 'www.example3.com' ],
617 true,
618 "Exact match with other domains in array, $pDesc URL"
619 ],
620 [
621 "$p//www.example2.com",
622 [ 'example.com', 'example2.com', 'example3,com' ],
623 true,
624 "Match without subdomain with other domains in array, $pDesc URL"
625 ],
626 [
627 "$p//www.example4.com",
628 [ 'example.com', 'example2.com', 'example3,com' ],
629 false,
630 "Domain not in array, $pDesc URL"
631 ],
632 [
633 "$p//nds-nl.wikipedia.org",
634 [ 'nl.wikipedia.org' ],
635 false,
636 "Non-matching substring of domain, $pDesc URL"
637 ],
638 ] );
639 }
640
641 return $a;
642 }
643
644 /**
645 * @covers ::wfMkdirParents
646 */
647 public function testWfMkdirParents() {
648 // Should not return true if file exists instead of directory
649 $fname = $this->getNewTempFile();
650 Wikimedia\suppressWarnings();
651 $ok = wfMkdirParents( $fname );
652 Wikimedia\restoreWarnings();
653 $this->assertFalse( $ok );
654 }
655
656 /**
657 * @dataProvider provideWfShellWikiCmdList
658 * @covers ::wfShellWikiCmd
659 */
660 public function testWfShellWikiCmd( $script, $parameters, $options,
661 $expected, $description
662 ) {
663 if ( wfIsWindows() ) {
664 // Approximation that's good enough for our purposes just now
665 $expected = str_replace( "'", '"', $expected );
666 }
667 $actual = wfShellWikiCmd( $script, $parameters, $options );
668 $this->assertEquals( $expected, $actual, $description );
669 }
670
671 public function wfWikiID() {
672 $this->setMwGlobals( [
673 'wgDBname' => 'example',
674 'wgDBprefix' => '',
675 ] );
676 $this->assertEquals(
677 wfWikiID(),
678 'example'
679 );
680
681 $this->setMwGlobals( [
682 'wgDBname' => 'example',
683 'wgDBprefix' => 'mw_',
684 ] );
685 $this->assertEquals(
686 wfWikiID(),
687 'example-mw_'
688 );
689 }
690
691 /**
692 * @covers ::wfMemcKey
693 */
694 public function testWfMemcKey() {
695 $cache = ObjectCache::getLocalClusterInstance();
696 $this->assertEquals(
697 $cache->makeKey( 'foo', 123, 'bar' ),
698 wfMemcKey( 'foo', 123, 'bar' )
699 );
700 }
701
702 /**
703 * @covers ::wfForeignMemcKey
704 */
705 public function testWfForeignMemcKey() {
706 $cache = ObjectCache::getLocalClusterInstance();
707 $keyspace = $this->readAttribute( $cache, 'keyspace' );
708 $this->assertEquals(
709 wfForeignMemcKey( $keyspace, '', 'foo', 'bar' ),
710 $cache->makeKey( 'foo', 'bar' )
711 );
712 }
713
714 /**
715 * @covers ::wfGlobalCacheKey
716 */
717 public function testWfGlobalCacheKey() {
718 $cache = ObjectCache::getLocalClusterInstance();
719 $this->assertEquals(
720 $cache->makeGlobalKey( 'foo', 123, 'bar' ),
721 wfGlobalCacheKey( 'foo', 123, 'bar' )
722 );
723 }
724
725 public static function provideWfShellWikiCmdList() {
726 global $wgPhpCli;
727
728 return [
729 [ 'eval.php', [ '--help', '--test' ], [],
730 "'$wgPhpCli' 'eval.php' '--help' '--test'",
731 "Called eval.php --help --test" ],
732 [ 'eval.php', [ '--help', '--test space' ], [ 'php' => 'php5' ],
733 "'php5' 'eval.php' '--help' '--test space'",
734 "Called eval.php --help --test with php option" ],
735 [ 'eval.php', [ '--help', '--test', 'X' ], [ 'wrapper' => 'MWScript.php' ],
736 "'$wgPhpCli' 'MWScript.php' 'eval.php' '--help' '--test' 'X'",
737 "Called eval.php --help --test with wrapper option" ],
738 [
739 'eval.php',
740 [ '--help', '--test', 'y' ],
741 [ 'php' => 'php5', 'wrapper' => 'MWScript.php' ],
742 "'php5' 'MWScript.php' 'eval.php' '--help' '--test' 'y'",
743 "Called eval.php --help --test with wrapper and php option"
744 ],
745 ];
746 }
747 /* @todo many more! */
748 }