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