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