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