* Allow passing in a blacklist into wfIsBadImage()
[lhc/web/wiklou.git] / tests / phpunit / includes / GlobalFunctions / GlobalTest.php
1 <?php
2
3 class GlobalTest extends MediaWikiTestCase {
4 function setUp() {
5 global $wgReadOnlyFile, $wgUrlProtocols;
6 $this->originals['wgReadOnlyFile'] = $wgReadOnlyFile;
7 $this->originals['wgUrlProtocols'] = $wgUrlProtocols;
8 $wgReadOnlyFile = tempnam( wfTempDir(), "mwtest_readonly" );
9 $wgUrlProtocols[] = 'file://';
10 unlink( $wgReadOnlyFile );
11 }
12
13 function tearDown() {
14 global $wgReadOnlyFile, $wgUrlProtocols;
15 if ( file_exists( $wgReadOnlyFile ) ) {
16 unlink( $wgReadOnlyFile );
17 }
18 $wgReadOnlyFile = $this->originals['wgReadOnlyFile'];
19 $wgUrlProtocols = $this->originals['wgUrlProtocols'];
20 }
21
22 /** @dataProvider provideForWfArrayDiff2 */
23 public function testWfArrayDiff2( $a, $b, $expected ) {
24 $this->assertEquals(
25 wfArrayDiff2( $a, $b), $expected
26 );
27 }
28
29 // @todo Provide more tests
30 public function provideForWfArrayDiff2() {
31 // $a $b $expected
32 return array(
33 array(
34 array( 'a', 'b'),
35 array( 'a', 'b'),
36 array(),
37 ),
38 array(
39 array( array( 'a'), array( 'a', 'b', 'c' )),
40 array( array( 'a'), array( 'a', 'b' )),
41 array( 1 => array( 'a', 'b', 'c' ) ),
42 ),
43 );
44 }
45
46 function testRandom() {
47 # This could hypothetically fail, but it shouldn't ;)
48 $this->assertFalse(
49 wfRandom() == wfRandom() );
50 }
51
52 function testUrlencode() {
53 $this->assertEquals(
54 "%E7%89%B9%E5%88%A5:Contributions/Foobar",
55 wfUrlencode( "\xE7\x89\xB9\xE5\x88\xA5:Contributions/Foobar" ) );
56 }
57
58 function testReadOnlyEmpty() {
59 global $wgReadOnly;
60 $wgReadOnly = null;
61
62 $this->assertFalse( wfReadOnly() );
63 $this->assertFalse( wfReadOnly() );
64 }
65
66 function testReadOnlySet() {
67 global $wgReadOnly, $wgReadOnlyFile;
68
69 $f = fopen( $wgReadOnlyFile, "wt" );
70 fwrite( $f, 'Message' );
71 fclose( $f );
72 $wgReadOnly = null; # Check on $wgReadOnlyFile
73
74 $this->assertTrue( wfReadOnly() );
75 $this->assertTrue( wfReadOnly() ); # Check cached
76
77 unlink( $wgReadOnlyFile );
78 $wgReadOnly = null; # Clean cache
79
80 $this->assertFalse( wfReadOnly() );
81 $this->assertFalse( wfReadOnly() );
82 }
83
84 function testQuotedPrintable() {
85 $this->assertEquals(
86 "=?UTF-8?Q?=C4=88u=20legebla=3F?=",
87 UserMailer::quotedPrintable( "\xc4\x88u legebla?", "UTF-8" ) );
88 }
89
90 function testTime() {
91 $start = wfTime();
92 $this->assertInternalType( 'float', $start );
93 $end = wfTime();
94 $this->assertTrue( $end > $start, "Time is running backwards!" );
95 }
96
97 function testArrayToCGI() {
98 $this->assertEquals(
99 "baz=AT%26T&foo=bar",
100 wfArrayToCGI(
101 array( 'baz' => 'AT&T', 'ignore' => '' ),
102 array( 'foo' => 'bar', 'baz' => 'overridden value' ) ) );
103 $this->assertEquals(
104 "path%5B0%5D=wiki&path%5B1%5D=test&cfg%5Bservers%5D%5Bhttp%5D=localhost",
105 wfArrayToCGI( array(
106 'path' => array( 'wiki', 'test' ),
107 'cfg' => array( 'servers' => array( 'http' => 'localhost' ) ) ) ) );
108 }
109
110 function testCgiToArray() {
111 $this->assertEquals(
112 array( 'path' => array( 'wiki', 'test' ),
113 'cfg' => array( 'servers' => array( 'http' => 'localhost' ) ) ),
114 wfCgiToArray( 'path%5B0%5D=wiki&path%5B1%5D=test&cfg%5Bservers%5D%5Bhttp%5D=localhost' ) );
115 }
116
117 function testMimeTypeMatch() {
118 $this->assertEquals(
119 'text/html',
120 mimeTypeMatch( 'text/html',
121 array( 'application/xhtml+xml' => 1.0,
122 'text/html' => 0.7,
123 'text/plain' => 0.3 ) ) );
124 $this->assertEquals(
125 'text/*',
126 mimeTypeMatch( 'text/html',
127 array( 'image/*' => 1.0,
128 'text/*' => 0.5 ) ) );
129 $this->assertEquals(
130 '*/*',
131 mimeTypeMatch( 'text/html',
132 array( '*/*' => 1.0 ) ) );
133 $this->assertNull(
134 mimeTypeMatch( 'text/html',
135 array( 'image/png' => 1.0,
136 'image/svg+xml' => 0.5 ) ) );
137 }
138
139 function testNegotiateType() {
140 $this->assertEquals(
141 'text/html',
142 wfNegotiateType(
143 array( 'application/xhtml+xml' => 1.0,
144 'text/html' => 0.7,
145 'text/plain' => 0.5,
146 'text/*' => 0.2 ),
147 array( 'text/html' => 1.0 ) ) );
148 $this->assertEquals(
149 'application/xhtml+xml',
150 wfNegotiateType(
151 array( 'application/xhtml+xml' => 1.0,
152 'text/html' => 0.7,
153 'text/plain' => 0.5,
154 'text/*' => 0.2 ),
155 array( 'application/xhtml+xml' => 1.0,
156 'text/html' => 0.5 ) ) );
157 $this->assertEquals(
158 'text/html',
159 wfNegotiateType(
160 array( 'text/html' => 1.0,
161 'text/plain' => 0.5,
162 'text/*' => 0.5,
163 'application/xhtml+xml' => 0.2 ),
164 array( 'application/xhtml+xml' => 1.0,
165 'text/html' => 0.5 ) ) );
166 $this->assertEquals(
167 'text/html',
168 wfNegotiateType(
169 array( 'text/*' => 1.0,
170 'image/*' => 0.7,
171 '*/*' => 0.3 ),
172 array( 'application/xhtml+xml' => 1.0,
173 'text/html' => 0.5 ) ) );
174 $this->assertNull(
175 wfNegotiateType(
176 array( 'text/*' => 1.0 ),
177 array( 'application/xhtml+xml' => 1.0 ) ) );
178 }
179
180 function testTimestamp() {
181 $t = gmmktime( 12, 34, 56, 1, 15, 2001 );
182 $this->assertEquals(
183 '20010115123456',
184 wfTimestamp( TS_MW, $t ),
185 'TS_UNIX to TS_MW' );
186 $this->assertEquals(
187 '19690115123456',
188 wfTimestamp( TS_MW, -30281104 ),
189 'Negative TS_UNIX to TS_MW' );
190 $this->assertEquals(
191 979562096,
192 wfTimestamp( TS_UNIX, $t ),
193 'TS_UNIX to TS_UNIX' );
194 $this->assertEquals(
195 '2001-01-15 12:34:56',
196 wfTimestamp( TS_DB, $t ),
197 'TS_UNIX to TS_DB' );
198 $this->assertEquals(
199 '20010115T123456Z',
200 wfTimestamp( TS_ISO_8601_BASIC, $t ),
201 'TS_ISO_8601_BASIC to TS_DB' );
202
203 $this->assertEquals(
204 '20010115123456',
205 wfTimestamp( TS_MW, '20010115123456' ),
206 'TS_MW to TS_MW' );
207 $this->assertEquals(
208 979562096,
209 wfTimestamp( TS_UNIX, '20010115123456' ),
210 'TS_MW to TS_UNIX' );
211 $this->assertEquals(
212 '2001-01-15 12:34:56',
213 wfTimestamp( TS_DB, '20010115123456' ),
214 'TS_MW to TS_DB' );
215 $this->assertEquals(
216 '20010115T123456Z',
217 wfTimestamp( TS_ISO_8601_BASIC, '20010115123456' ),
218 'TS_MW to TS_ISO_8601_BASIC' );
219
220 $this->assertEquals(
221 '20010115123456',
222 wfTimestamp( TS_MW, '2001-01-15 12:34:56' ),
223 'TS_DB to TS_MW' );
224 $this->assertEquals(
225 979562096,
226 wfTimestamp( TS_UNIX, '2001-01-15 12:34:56' ),
227 'TS_DB to TS_UNIX' );
228 $this->assertEquals(
229 '2001-01-15 12:34:56',
230 wfTimestamp( TS_DB, '2001-01-15 12:34:56' ),
231 'TS_DB to TS_DB' );
232 $this->assertEquals(
233 '20010115T123456Z',
234 wfTimestamp( TS_ISO_8601_BASIC, '2001-01-15 12:34:56' ),
235 'TS_DB to TS_ISO_8601_BASIC' );
236
237 # rfc2822 section 3.3
238
239 $this->assertEquals(
240 'Mon, 15 Jan 2001 12:34:56 GMT',
241 wfTimestamp( TS_RFC2822, '20010115123456' ),
242 'TS_MW to TS_RFC2822' );
243
244 $this->assertEquals(
245 '20010115123456',
246 wfTimestamp( TS_MW, 'Mon, 15 Jan 2001 12:34:56 GMT' ),
247 'TS_RFC2822 to TS_MW' );
248
249 $this->assertEquals(
250 '20010115123456',
251 wfTimestamp( TS_MW, ' Mon, 15 Jan 2001 12:34:56 GMT' ),
252 'TS_RFC2822 with leading space to TS_MW' );
253
254 $this->assertEquals(
255 '20010115123456',
256 wfTimestamp( TS_MW, '15 Jan 2001 12:34:56 GMT' ),
257 'TS_RFC2822 without optional day-of-week to TS_MW' );
258
259 # FWS = ([*WSP CRLF] 1*WSP) / obs-FWS ; Folding white space
260 # obs-FWS = 1*WSP *(CRLF 1*WSP) ; Section 4.2
261 $this->assertEquals(
262 '20010115123456',
263 wfTimestamp( TS_MW, 'Mon, 15 Jan 2001 12:34:56 GMT' ),
264 'TS_RFC2822 to TS_MW' );
265
266 # WSP = SP / HTAB ; rfc2234
267 $this->assertEquals(
268 '20010115123456',
269 wfTimestamp( TS_MW, "Mon, 15 Jan\x092001 12:34:56 GMT" ),
270 'TS_RFC2822 with HTAB to TS_MW' );
271
272 $this->assertEquals(
273 '20010115123456',
274 wfTimestamp( TS_MW, "Mon, 15 Jan\x09 \x09 2001 12:34:56 GMT" ),
275 'TS_RFC2822 with HTAB and SP to TS_MW' );
276
277 $this->assertEquals(
278 '19941106084937',
279 wfTimestamp( TS_MW, "Sun, 6 Nov 94 08:49:37 GMT" ),
280 'TS_RFC2822 with obsolete year to TS_MW' );
281 }
282
283 /**
284 * This test checks wfTimestamp() with values outside.
285 * It needs PHP 64 bits or PHP > 5.1.
286 * See r74778 and bug 25451
287 */
288 function testOldTimestamps() {
289 $this->assertEquals( 'Fri, 13 Dec 1901 20:45:54 GMT',
290 wfTimestamp( TS_RFC2822, '19011213204554' ),
291 'Earliest time according to php documentation' );
292
293 $this->assertEquals( 'Tue, 19 Jan 2038 03:14:07 GMT',
294 wfTimestamp( TS_RFC2822, '20380119031407' ),
295 'Latest 32 bit time' );
296
297 $this->assertEquals( '-2147483648',
298 wfTimestamp( TS_UNIX, '19011213204552' ),
299 'Earliest 32 bit unix time' );
300
301 $this->assertEquals( '2147483647',
302 wfTimestamp( TS_UNIX, '20380119031407' ),
303 'Latest 32 bit unix time' );
304
305 $this->assertEquals( 'Fri, 13 Dec 1901 20:45:52 GMT',
306 wfTimestamp( TS_RFC2822, '19011213204552' ),
307 'Earliest 32 bit time' );
308
309 $this->assertEquals( 'Fri, 13 Dec 1901 20:45:51 GMT',
310 wfTimestamp( TS_RFC2822, '19011213204551' ),
311 'Earliest 32 bit time - 1' );
312
313 $this->assertEquals( 'Tue, 19 Jan 2038 03:14:08 GMT',
314 wfTimestamp( TS_RFC2822, '20380119031408' ),
315 'Latest 32 bit time + 1' );
316
317 $this->assertEquals( '19011212000000',
318 wfTimestamp(TS_MW, '19011212000000'),
319 'Convert to itself r74778#c10645' );
320
321 $this->assertEquals( '-2147483649',
322 wfTimestamp( TS_UNIX, '19011213204551' ),
323 'Earliest 32 bit unix time - 1' );
324
325 $this->assertEquals( '2147483648',
326 wfTimestamp( TS_UNIX, '20380119031408' ),
327 'Latest 32 bit unix time + 1' );
328
329 $this->assertEquals( '19011213204551',
330 wfTimestamp( TS_MW, '-2147483649' ),
331 '1901 negative unix time to MediaWiki' );
332
333 $this->assertEquals( '18010115123456',
334 wfTimestamp( TS_MW, '-5331871504' ),
335 '1801 negative unix time to MediaWiki' );
336
337 $this->assertEquals( 'Tue, 09 Aug 0117 12:34:56 GMT',
338 wfTimestamp( TS_RFC2822, '0117-08-09 12:34:56'),
339 'Death of Roman Emperor [[Trajan]]');
340
341 /* @todo FIXME: 00 to 101 years are taken as being in [1970-2069] */
342
343 $this->assertEquals( 'Sun, 01 Jan 0101 00:00:00 GMT',
344 wfTimestamp( TS_RFC2822, '-58979923200'),
345 '1/1/101');
346
347 $this->assertEquals( 'Mon, 01 Jan 0001 00:00:00 GMT',
348 wfTimestamp( TS_RFC2822, '-62135596800'),
349 'Year 1');
350
351 /* It is not clear if we should generate a year 0 or not
352 * We are completely off RFC2822 requirement of year being
353 * 1900 or later.
354 */
355 $this->assertEquals( 'Wed, 18 Oct 0000 00:00:00 GMT',
356 wfTimestamp( TS_RFC2822, '-62142076800'),
357 'ISO 8601:2004 [[year 0]], also called [[1 BC]]');
358 }
359
360 function testHttpDate() {
361 # The Resource Loader uses wfTimestamp() to convert timestamps
362 # from If-Modified-Since header.
363 # Thus it must be able to parse all rfc2616 date formats
364 # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1
365
366 $this->assertEquals(
367 '19941106084937',
368 wfTimestamp( TS_MW, 'Sun, 06 Nov 1994 08:49:37 GMT' ),
369 'RFC 822 date' );
370
371 $this->assertEquals(
372 '19941106084937',
373 wfTimestamp( TS_MW, 'Sunday, 06-Nov-94 08:49:37 GMT' ),
374 'RFC 850 date' );
375
376 $this->assertEquals(
377 '19941106084937',
378 wfTimestamp( TS_MW, 'Sun Nov 6 08:49:37 1994' ),
379 "ANSI C's asctime() format" );
380
381 // See http://www.squid-cache.org/mail-archive/squid-users/200307/0122.html and r77171
382 $this->assertEquals(
383 '20101122141242',
384 wfTimestamp( TS_MW, 'Mon, 22 Nov 2010 14:12:42 GMT; length=52626' ),
385 "Netscape extension to HTTP/1.0" );
386
387 }
388
389 function testTimestampParameter() {
390 // There are a number of assumptions in our codebase where wfTimestamp() should give
391 // the current date but it is not given a 0 there. See r71751 CR
392
393 $now = wfTimestamp( TS_UNIX );
394 // We check that wfTimestamp doesn't return false (error) and use a LessThan assert
395 // for the cases where the test is run in a second boundary.
396
397 $zero = wfTimestamp( TS_UNIX, 0 );
398 $this->assertNotEquals( false, $zero );
399 $this->assertLessThan( 5, $zero - $now );
400
401 $empty = wfTimestamp( TS_UNIX, '' );
402 $this->assertNotEquals( false, $empty );
403 $this->assertLessThan( 5, $empty - $now );
404
405 $null = wfTimestamp( TS_UNIX, null );
406 $this->assertNotEquals( false, $null );
407 $this->assertLessThan( 5, $null - $now );
408 }
409
410 function testBasename() {
411 $sets = array(
412 '' => '',
413 '/' => '',
414 '\\' => '',
415 '//' => '',
416 '\\\\' => '',
417 'a' => 'a',
418 'aaaa' => 'aaaa',
419 '/a' => 'a',
420 '\\a' => 'a',
421 '/aaaa' => 'aaaa',
422 '\\aaaa' => 'aaaa',
423 '/aaaa/' => 'aaaa',
424 '\\aaaa\\' => 'aaaa',
425 '\\aaaa\\' => 'aaaa',
426 '/mnt/upload3/wikipedia/en/thumb/8/8b/Zork_Grand_Inquisitor_box_cover.jpg/93px-Zork_Grand_Inquisitor_box_cover.jpg' => '93px-Zork_Grand_Inquisitor_box_cover.jpg',
427 'C:\\Progra~1\\Wikime~1\\Wikipe~1\\VIEWER.EXE' => 'VIEWER.EXE',
428 'Östergötland_coat_of_arms.png' => 'Östergötland_coat_of_arms.png',
429 );
430 foreach ( $sets as $from => $to ) {
431 $this->assertEquals( $to, wfBaseName( $from ),
432 "wfBaseName('$from') => '$to'" );
433 }
434 }
435
436
437 function testFallbackMbstringFunctions() {
438
439 if( !extension_loaded( 'mbstring' ) ) {
440 $this->markTestSkipped( "The mb_string functions must be installed to test the fallback functions" );
441 }
442
443 $sampleUTF = "Östergötland_coat_of_arms.png";
444
445
446 //mb_substr
447 $substr_params = array(
448 array( 0, 0 ),
449 array( 5, -4 ),
450 array( 33 ),
451 array( 100, -5 ),
452 array( -8, 10 ),
453 array( 1, 1 ),
454 array( 2, -1 )
455 );
456
457 foreach( $substr_params as $param_set ) {
458 $old_param_set = $param_set;
459 array_unshift( $param_set, $sampleUTF );
460
461 $this->assertEquals(
462 MWFunction::callArray( 'mb_substr', $param_set ),
463 MWFunction::callArray( 'Fallback::mb_substr', $param_set ),
464 'Fallback mb_substr with params ' . implode( ', ', $old_param_set )
465 );
466 }
467
468
469 //mb_strlen
470 $this->assertEquals(
471 mb_strlen( $sampleUTF ),
472 Fallback::mb_strlen( $sampleUTF ),
473 'Fallback mb_strlen'
474 );
475
476
477 //mb_str(r?)pos
478 $strpos_params = array(
479 //array( 'ter' ),
480 //array( 'Ö' ),
481 //array( 'Ö', 3 ),
482 //array( 'oat_', 100 ),
483 //array( 'c', -10 ),
484 //Broken for now
485 );
486
487 foreach( $strpos_params as $param_set ) {
488 $old_param_set = $param_set;
489 array_unshift( $param_set, $sampleUTF );
490
491 $this->assertEquals(
492 MWFunction::callArray( 'mb_strpos', $param_set ),
493 MWFunction::callArray( 'Fallback::mb_strpos', $param_set ),
494 'Fallback mb_strpos with params ' . implode( ', ', $old_param_set )
495 );
496
497 $this->assertEquals(
498 MWFunction::callArray( 'mb_strrpos', $param_set ),
499 MWFunction::callArray( 'Fallback::mb_strrpos', $param_set ),
500 'Fallback mb_strrpos with params ' . implode( ', ', $old_param_set )
501 );
502 }
503
504 }
505
506
507 function testDebugFunctionTest() {
508
509 global $wgDebugLogFile, $wgOut, $wgShowDebug, $wgDebugTimestamps;
510
511 $old_log_file = $wgDebugLogFile;
512 $wgDebugLogFile = tempnam( wfTempDir(), 'mw-' );
513 # @todo FIXME: This setting should be tested
514 $wgDebugTimestamps = false;
515
516
517
518 wfDebug( "This is a normal string" );
519 $this->assertEquals( "This is a normal string", file_get_contents( $wgDebugLogFile ) );
520 unlink( $wgDebugLogFile );
521
522
523 wfDebug( "This is nöt an ASCII string" );
524 $this->assertEquals( "This is nöt an ASCII string", file_get_contents( $wgDebugLogFile ) );
525 unlink( $wgDebugLogFile );
526
527
528 wfDebug( "\00305This has böth UTF and control chars\003" );
529 $this->assertEquals( " 05This has böth UTF and control chars ", file_get_contents( $wgDebugLogFile ) );
530 unlink( $wgDebugLogFile );
531
532
533
534 $old_wgOut = $wgOut;
535 $old_wgShowDebug = $wgShowDebug;
536
537 $wgOut = new MockOutputPage;
538
539 $wgShowDebug = true;
540
541 $message = "\00305This has böth UTF and control chars\003";
542
543 wfDebug( $message );
544
545 if( $wgOut->message == "JAJA is a stupid error message. Anyway, here's your message: $message" ) {
546 $this->assertTrue( true, 'MockOutputPage called, set the proper message.' );
547 }
548 else {
549 $this->assertTrue( false, 'MockOutputPage was not called.' );
550 }
551
552 $wgOut = $old_wgOut;
553 $wgShowDebug = $old_wgShowDebug;
554 unlink( $wgDebugLogFile );
555
556
557
558 wfDebugMem();
559 $this->assertGreaterThan( 5000, preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) ) );
560 unlink( $wgDebugLogFile );
561
562 wfDebugMem(true);
563 $this->assertGreaterThan( 5000000, preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) ) );
564 unlink( $wgDebugLogFile );
565
566
567
568 $wgDebugLogFile = $old_log_file;
569
570 }
571
572 function testClientAcceptsGzipTest() {
573
574 $settings = array(
575 'gzip' => true,
576 'bzip' => false,
577 '*' => false,
578 'compress, gzip' => true,
579 'gzip;q=1.0' => true,
580 'foozip' => false,
581 'foo*zip' => false,
582 'gzip;q=abcde' => true, //is this REALLY valid?
583 'gzip;q=12345678.9' => true,
584 ' gzip' => true,
585 );
586
587 if( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) $old_server_setting = $_SERVER['HTTP_ACCEPT_ENCODING'];
588
589 foreach ( $settings as $encoding => $expect ) {
590 $_SERVER['HTTP_ACCEPT_ENCODING'] = $encoding;
591
592 $this->assertEquals( $expect, wfClientAcceptsGzip( true ),
593 "'$encoding' => " . wfBoolToStr( $expect ) );
594 }
595
596 if( isset( $old_server_setting ) ) $_SERVER['HTTP_ACCEPT_ENCODING'] = $old_server_setting;
597
598 }
599
600
601
602 function testSwapVarsTest() {
603
604
605 $var1 = 1;
606 $var2 = 2;
607
608 $this->assertEquals( $var1, 1, 'var1 is set originally' );
609 $this->assertEquals( $var2, 2, 'var1 is set originally' );
610
611 swap( $var1, $var2 );
612
613 $this->assertEquals( $var1, 2, 'var1 is swapped' );
614 $this->assertEquals( $var2, 1, 'var2 is swapped' );
615
616 }
617
618
619 function testWfPercentTest() {
620
621 $pcts = array(
622 array( 6/7, '0.86%', 2, false ),
623 array( 3/3, '1%' ),
624 array( 22/7, '3.14286%', 5 ),
625 array( 3/6, '0.5%' ),
626 array( 1/3, '0%', 0 ),
627 array( 10/3, '0%', -1 ),
628 array( 3/4/5, '0.1%', 1 ),
629 array( 6/7*8, '6.8571428571%', 10 ),
630 );
631
632 foreach( $pcts as $pct ) {
633 if( !isset( $pct[2] ) ) $pct[2] = 2;
634 if( !isset( $pct[3] ) ) $pct[3] = true;
635
636 $this->assertEquals( wfPercent( $pct[0], $pct[2], $pct[3] ), $pct[1], $pct[1] );
637 }
638
639 }
640
641
642 function testInStringTest() {
643
644 $this->assertTrue( in_string( 'foo', 'foobar' ), 'foo is in foobar' );
645 $this->assertFalse( in_string( 'Bar', 'foobar' ), 'Case-sensitive by default' );
646 $this->assertTrue( in_string( 'Foo', 'foobar', true ), 'Case-insensitive when asked' );
647
648 }
649
650 /**
651 * test @see wfShorthandToInteger()
652 * @dataProvider provideShorthand
653 */
654 public function testWfShorthandToInteger( $shorthand, $expected ) {
655 $this->assertEquals( $expected,
656 wfShorthandToInteger( $shorthand )
657 );
658 }
659
660 /** array( shorthand, expected integer ) */
661 public function provideShorthand() {
662 return array(
663 # Null, empty ...
664 array( '', -1),
665 array( ' ', -1),
666 array( null, -1),
667
668 # Failures returns 0 :(
669 array( 'ABCDEFG', 0 ),
670 array( 'Ak', 0 ),
671
672 # Int, strings with spaces
673 array( 1, 1 ),
674 array( ' 1 ', 1 ),
675 array( 1023, 1023 ),
676 array( ' 1023 ', 1023 ),
677
678 # kilo, Mega, Giga
679 array( '1k', 1024 ),
680 array( '1K', 1024 ),
681 array( '1m', 1024 * 1024 ),
682 array( '1M', 1024 * 1024 ),
683 array( '1g', 1024 * 1024 * 1024 ),
684 array( '1G', 1024 * 1024 * 1024 ),
685
686 # Negatives
687 array( -1, -1 ),
688 array( -500, -500 ),
689 array( '-500', -500 ),
690 array( '-1k', -1024 ),
691
692 # Zeroes
693 array( '0', 0 ),
694 array( '0k', 0 ),
695 array( '0M', 0 ),
696 array( '0G', 0 ),
697 array( '-0', 0 ),
698 array( '-0k', 0 ),
699 array( '-0M', 0 ),
700 array( '-0G', 0 ),
701 );
702 }
703
704
705 /**
706 * test @see wfBCP47().
707 * Please note the BCP explicitly state that language codes are case
708 * insensitive, there are some exceptions to the rule :)
709 * This test is used to verify our formatting against all lower and
710 * all upper cases language code.
711 *
712 * @see http://tools.ietf.org/html/bcp47
713 * @dataProvider provideLanguageCodes()
714 */
715 function testBCP47( $code, $expected ) {
716 $code = strtolower( $code );
717 $this->assertEquals( $expected, wfBCP47($code),
718 "Applying BCP47 standard to lower case '$code'"
719 );
720
721 $code = strtoupper( $code );
722 $this->assertEquals( $expected, wfBCP47($code),
723 "Applying BCP47 standard to upper case '$code'"
724 );
725 }
726
727 /**
728 * Array format is ($code, $expected)
729 */
730 function provideLanguageCodes() {
731 return array(
732 // Extracted from BCP47 (list not exhaustive)
733 # 2.1.1
734 array( 'en-ca-x-ca' , 'en-CA-x-ca' ),
735 array( 'sgn-be-fr' , 'sgn-BE-FR' ),
736 array( 'az-latn-x-latn', 'az-Latn-x-latn' ),
737 # 2.2
738 array( 'sr-Latn-RS', 'sr-Latn-RS' ),
739 array( 'az-arab-ir', 'az-Arab-IR' ),
740
741 # 2.2.5
742 array( 'sl-nedis' , 'sl-nedis' ),
743 array( 'de-ch-1996', 'de-CH-1996' ),
744
745 # 2.2.6
746 array(
747 'en-latn-gb-boont-r-extended-sequence-x-private',
748 'en-Latn-GB-boont-r-extended-sequence-x-private'
749 ),
750
751 // Examples from BCP47 Appendix A
752 # Simple language subtag:
753 array( 'DE', 'de' ),
754 array( 'fR', 'fr' ),
755 array( 'ja', 'ja' ),
756
757 # Language subtag plus script subtag:
758 array( 'zh-hans', 'zh-Hans'),
759 array( 'sr-cyrl', 'sr-Cyrl'),
760 array( 'sr-latn', 'sr-Latn'),
761
762 # Extended language subtags and their primary language subtag
763 # counterparts:
764 array( 'zh-cmn-hans-cn', 'zh-cmn-Hans-CN' ),
765 array( 'cmn-hans-cn' , 'cmn-Hans-CN' ),
766 array( 'zh-yue-hk' , 'zh-yue-HK' ),
767 array( 'yue-hk' , 'yue-HK' ),
768
769 # Language-Script-Region:
770 array( 'zh-hans-cn', 'zh-Hans-CN' ),
771 array( 'sr-latn-RS', 'sr-Latn-RS' ),
772
773 # Language-Variant:
774 array( 'sl-rozaj' , 'sl-rozaj' ),
775 array( 'sl-rozaj-biske', 'sl-rozaj-biske' ),
776 array( 'sl-nedis' , 'sl-nedis' ),
777
778 # Language-Region-Variant:
779 array( 'de-ch-1901' , 'de-CH-1901' ),
780 array( 'sl-it-nedis' , 'sl-IT-nedis' ),
781
782 # Language-Script-Region-Variant:
783 array( 'hy-latn-it-arevela', 'hy-Latn-IT-arevela' ),
784
785 # Language-Region:
786 array( 'de-de' , 'de-DE' ),
787 array( 'en-us' , 'en-US' ),
788 array( 'es-419', 'es-419'),
789
790 # Private use subtags:
791 array( 'de-ch-x-phonebk' , 'de-CH-x-phonebk' ),
792 array( 'az-arab-x-aze-derbend', 'az-Arab-x-aze-derbend' ),
793 /**
794 * Previous test does not reflect the BCP which states:
795 * az-Arab-x-AZE-derbend
796 * AZE being private, it should be lower case, hence the test above
797 * should probably be:
798 #array( 'az-arab-x-aze-derbend', 'az-Arab-x-AZE-derbend' ),
799 */
800
801 # Private use registry values:
802 array( 'x-whatever', 'x-whatever' ),
803 array( 'qaa-qaaa-qm-x-southern', 'qaa-Qaaa-QM-x-southern' ),
804 array( 'de-qaaa' , 'de-Qaaa' ),
805 array( 'sr-latn-qm', 'sr-Latn-QM' ),
806 array( 'sr-qaaa-rs', 'sr-Qaaa-RS' ),
807
808 # Tags that use extensions
809 array( 'en-us-u-islamcal', 'en-US-u-islamcal' ),
810 array( 'zh-cn-a-myext-x-private', 'zh-CN-a-myext-x-private' ),
811 array( 'en-a-myext-b-another', 'en-a-myext-b-another' ),
812
813 # Invalid:
814 // de-419-DE
815 // a-DE
816 // ar-a-aaa-b-bbb-a-ccc
817
818 /*
819 // ISO 15924 :
820 array( 'sr-Cyrl', 'sr-Cyrl' ),
821 # @todo FIXME: Fix our function?
822 array( 'SR-lATN', 'sr-Latn' ),
823 array( 'fr-latn', 'fr-Latn' ),
824 // Use lowercase for single segment
825 // ISO 3166-1-alpha-2 code
826 array( 'US', 'us' ), # USA
827 array( 'uS', 'us' ), # USA
828 array( 'Fr', 'fr' ), # France
829 array( 'va', 'va' ), # Holy See (Vatican City State)
830 */);
831 }
832
833 /**
834 * @dataProvider provideMakeUrlIndex()
835 */
836 function testMakeUrlIndex( $url, $expected ) {
837 $index = wfMakeUrlIndex( $url );
838 $this->assertEquals( $expected, $index, "wfMakeUrlIndex(\"$url\")" );
839 }
840
841 function provideMakeUrlIndex() {
842 return array(
843 array(
844 // just a regular :)
845 'https://bugzilla.wikimedia.org/show_bug.cgi?id=28627',
846 'https://org.wikimedia.bugzilla./show_bug.cgi?id=28627'
847 ),
848 array(
849 // mailtos are handled special
850 // is this really right though? that final . probably belongs earlier?
851 'mailto:wiki@wikimedia.org',
852 'mailto:org.wikimedia@wiki.',
853 ),
854
855 // file URL cases per bug 28627...
856 array(
857 // three slashes: local filesystem path Unix-style
858 'file:///whatever/you/like.txt',
859 'file://./whatever/you/like.txt'
860 ),
861 array(
862 // three slashes: local filesystem path Windows-style
863 'file:///c:/whatever/you/like.txt',
864 'file://./c:/whatever/you/like.txt'
865 ),
866 array(
867 // two slashes: UNC filesystem path Windows-style
868 'file://intranet/whatever/you/like.txt',
869 'file://intranet./whatever/you/like.txt'
870 ),
871 // Multiple-slash cases that can sorta work on Mozilla
872 // if you hack it just right are kinda pathological,
873 // and unreliable cross-platform or on IE which means they're
874 // unlikely to appear on intranets.
875 //
876 // Those will survive the algorithm but with results that
877 // are less consistent.
878 );
879 }
880
881 /**
882 * @dataProvider provideWfMatchesDomainList
883 */
884 function testWfMatchesDomainList( $url, $domains, $expected, $description ) {
885 $actual = wfMatchesDomainList( $url, $domains );
886 $this->assertEquals( $expected, $actual, $description );
887 }
888
889 function provideWfMatchesDomainList() {
890 $a = array();
891 $protocols = array( 'HTTP' => 'http:', 'HTTPS' => 'https:', 'protocol-relative' => '' );
892 foreach ( $protocols as $pDesc => $p ) {
893 $a = array_merge( $a, array(
894 array( "$p//www.example.com", array(), false, "No matches for empty domains array, $pDesc URL" ),
895 array( "$p//www.example.com", array( 'www.example.com' ), true, "Exact match in domains array, $pDesc URL" ),
896 array( "$p//www.example.com", array( 'example.com' ), true, "Match without subdomain in domains array, $pDesc URL" ),
897 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" ),
898 array( "$p//www.example2.com", array( 'example.com', 'example2.com', 'example3,com' ), true, "Match without subdomain with other domains in array, $pDesc URL" ),
899 array( "$p//www.example4.com", array( 'example.com', 'example2.com', 'example3,com' ), false, "Domain not in array, $pDesc URL" ),
900
901 // FIXME: This is a bug in wfMatchesDomainList(). If and when this is fixed, update this test case
902 array( "$p//nds-nl.wikipedia.org", array( 'nl.wikipedia.org' ), true, "Substrings of domains match while they shouldn't, $pDesc URL" ),
903 ) );
904 }
905 return $a;
906 }
907
908 /**
909 * @dataProvider provideWfShellMaintenanceCmdList
910 */
911 function testWfShellMaintenanceCmd( $script, $parameters, $options, $expected, $description ) {
912 if( wfIsWindows() ) {
913 // Approximation that's good enough for our purposes just now
914 $expected = str_replace( "'", '"', $expected );
915 }
916 $actual = wfShellMaintenanceCmd( $script, $parameters, $options );
917 $this->assertEquals( $expected, $actual, $description );
918 }
919
920 function provideWfShellMaintenanceCmdList() {
921 global $wgPhpCli;
922 return array(
923 array( 'eval.php', array( '--help', '--test' ), array(),
924 "'$wgPhpCli' 'eval.php' '--help' '--test'",
925 "Called eval.php --help --test" ),
926 array( 'eval.php', array( '--help', '--test space' ), array('php' => 'php5'),
927 "'php5' 'eval.php' '--help' '--test space'",
928 "Called eval.php --help --test with php option" ),
929 array( 'eval.php', array( '--help', '--test', 'X' ), array('wrapper' => 'MWScript.php'),
930 "'$wgPhpCli' 'MWScript.php' 'eval.php' '--help' '--test' 'X'",
931 "Called eval.php --help --test with wrapper option" ),
932 array( 'eval.php', array( '--help', '--test', 'y' ), array('php' => 'php5', 'wrapper' => 'MWScript.php'),
933 "'php5' 'MWScript.php' 'eval.php' '--help' '--test' 'y'",
934 "Called eval.php --help --test with wrapper and php option" ),
935 );
936 }
937
938 /**
939 * @dataProvider provideWfIsBadImageList
940 */
941 function testWfIsBadImage( $name, $title, $blacklist, $expected, $desc ) {
942 $this->assertEquals( $expected, wfIsBadImage( $name, $title, $blacklist ), $desc );
943 }
944
945 function provideWfIsBadImageList() {
946 $blacklist = '* [[File:Bad.jpg]] except [[Nasty page]]';
947 return array(
948 array( 'Bad.jpg', false, $blacklist, true,
949 'Called on a bad image' ),
950 array( 'Bad.jpg', Title::makeTitle( NS_MAIN, 'A page' ), $blacklist, true,
951 'Called on a bad image' ),
952 array( 'NotBad.jpg', false, $blacklist, false,
953 'Called on a non-bad image' ),
954 array( 'Bad.jpg', Title::makeTitle( NS_MAIN, 'Nasty page' ), $blacklist, false,
955 'Called on a bad image but is on a whitelisted page' ),
956 array( 'File:Bad.jpg', false, $blacklist, false,
957 'Called on a bad image with File:' ),
958 );
959 }
960 /* TODO: many more! */
961 }
962
963
964 class MockOutputPage {
965
966 public $message;
967
968 function debug( $message ) {
969 $this->message = "JAJA is a stupid error message. Anyway, here's your message: $message";
970 }
971 }
972