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