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