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