Improve PHPUnit code coverage
[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;
6 $this->originals['wgReadOnlyFile'] = $wgReadOnlyFile;
7 $wgReadOnlyFile = tempnam( wfTempDir(), "mwtest_readonly" );
8 unlink( $wgReadOnlyFile );
9 $wgContLang = $wgLang = Language::factory( 'en' );
10 }
11
12 function tearDown() {
13 global $wgReadOnlyFile;
14 if ( file_exists( $wgReadOnlyFile ) ) {
15 unlink( $wgReadOnlyFile );
16 }
17 $wgReadOnlyFile = $this->originals['wgReadOnlyFile'];
18 }
19
20 /** @dataProvider provideForWfArrayDiff2 */
21 public function testWfArrayDiff2( $a, $b, $expected ) {
22 $this->assertEquals(
23 wfArrayDiff2( $a, $b), $expected
24 );
25 }
26
27 // @todo Provide more tests
28 public function provideForWfArrayDiff2() {
29 // $a $b $expected
30 return array(
31 array(
32 array( 'a', 'b'),
33 array( 'a', 'b'),
34 array(),
35 ),
36 array(
37 array( array( 'a'), array( 'a', 'b', 'c' )),
38 array( array( 'a'), array( 'a', 'b' )),
39 array( 1 => array( 'a', 'b', 'c' ) ),
40 ),
41 );
42 }
43
44 function testRandom() {
45 # This could hypothetically fail, but it shouldn't ;)
46 $this->assertFalse(
47 wfRandom() == wfRandom() );
48 }
49
50 function testUrlencode() {
51 $this->assertEquals(
52 "%E7%89%B9%E5%88%A5:Contributions/Foobar",
53 wfUrlencode( "\xE7\x89\xB9\xE5\x88\xA5:Contributions/Foobar" ) );
54 }
55
56 function testReadOnlyEmpty() {
57 global $wgReadOnly;
58 $wgReadOnly = null;
59
60 $this->assertFalse( wfReadOnly() );
61 $this->assertFalse( wfReadOnly() );
62 }
63
64 function testReadOnlySet() {
65 global $wgReadOnly, $wgReadOnlyFile;
66
67 $f = fopen( $wgReadOnlyFile, "wt" );
68 fwrite( $f, 'Message' );
69 fclose( $f );
70 $wgReadOnly = null; # Check on $wgReadOnlyFile
71
72 $this->assertTrue( wfReadOnly() );
73 $this->assertTrue( wfReadOnly() ); # Check cached
74
75 unlink( $wgReadOnlyFile );
76 $wgReadOnly = null; # Clean cache
77
78 $this->assertFalse( wfReadOnly() );
79 $this->assertFalse( wfReadOnly() );
80 }
81
82 function testQuotedPrintable() {
83 $this->assertEquals(
84 "=?UTF-8?Q?=C4=88u=20legebla=3F?=",
85 UserMailer::quotedPrintable( "\xc4\x88u legebla?", "UTF-8" ) );
86 }
87
88 function testTime() {
89 $start = wfTime();
90 $this->assertInternalType( 'float', $start );
91 $end = wfTime();
92 $this->assertTrue( $end > $start, "Time is running backwards!" );
93 }
94
95 function testArrayToCGI() {
96 $this->assertEquals(
97 "baz=AT%26T&foo=bar",
98 wfArrayToCGI(
99 array( 'baz' => 'AT&T', 'ignore' => '' ),
100 array( 'foo' => 'bar', 'baz' => 'overridden value' ) ) );
101 }
102
103 function testMimeTypeMatch() {
104 $this->assertEquals(
105 'text/html',
106 mimeTypeMatch( 'text/html',
107 array( 'application/xhtml+xml' => 1.0,
108 'text/html' => 0.7,
109 'text/plain' => 0.3 ) ) );
110 $this->assertEquals(
111 'text/*',
112 mimeTypeMatch( 'text/html',
113 array( 'image/*' => 1.0,
114 'text/*' => 0.5 ) ) );
115 $this->assertEquals(
116 '*/*',
117 mimeTypeMatch( 'text/html',
118 array( '*/*' => 1.0 ) ) );
119 $this->assertNull(
120 mimeTypeMatch( 'text/html',
121 array( 'image/png' => 1.0,
122 'image/svg+xml' => 0.5 ) ) );
123 }
124
125 function testNegotiateType() {
126 $this->assertEquals(
127 'text/html',
128 wfNegotiateType(
129 array( 'application/xhtml+xml' => 1.0,
130 'text/html' => 0.7,
131 'text/plain' => 0.5,
132 'text/*' => 0.2 ),
133 array( 'text/html' => 1.0 ) ) );
134 $this->assertEquals(
135 'application/xhtml+xml',
136 wfNegotiateType(
137 array( 'application/xhtml+xml' => 1.0,
138 'text/html' => 0.7,
139 'text/plain' => 0.5,
140 'text/*' => 0.2 ),
141 array( 'application/xhtml+xml' => 1.0,
142 'text/html' => 0.5 ) ) );
143 $this->assertEquals(
144 'text/html',
145 wfNegotiateType(
146 array( 'text/html' => 1.0,
147 'text/plain' => 0.5,
148 'text/*' => 0.5,
149 'application/xhtml+xml' => 0.2 ),
150 array( 'application/xhtml+xml' => 1.0,
151 'text/html' => 0.5 ) ) );
152 $this->assertEquals(
153 'text/html',
154 wfNegotiateType(
155 array( 'text/*' => 1.0,
156 'image/*' => 0.7,
157 '*/*' => 0.3 ),
158 array( 'application/xhtml+xml' => 1.0,
159 'text/html' => 0.5 ) ) );
160 $this->assertNull(
161 wfNegotiateType(
162 array( 'text/*' => 1.0 ),
163 array( 'application/xhtml+xml' => 1.0 ) ) );
164 }
165
166 function testTimestamp() {
167 $t = gmmktime( 12, 34, 56, 1, 15, 2001 );
168 $this->assertEquals(
169 '20010115123456',
170 wfTimestamp( TS_MW, $t ),
171 'TS_UNIX to TS_MW' );
172 $this->assertEquals(
173 '19690115123456',
174 wfTimestamp( TS_MW, -30281104 ),
175 'Negative TS_UNIX to TS_MW' );
176 $this->assertEquals(
177 979562096,
178 wfTimestamp( TS_UNIX, $t ),
179 'TS_UNIX to TS_UNIX' );
180 $this->assertEquals(
181 '2001-01-15 12:34:56',
182 wfTimestamp( TS_DB, $t ),
183 'TS_UNIX to TS_DB' );
184 $this->assertEquals(
185 '20010115T123456Z',
186 wfTimestamp( TS_ISO_8601_BASIC, $t ),
187 'TS_ISO_8601_BASIC to TS_DB' );
188
189 $this->assertEquals(
190 '20010115123456',
191 wfTimestamp( TS_MW, '20010115123456' ),
192 'TS_MW to TS_MW' );
193 $this->assertEquals(
194 979562096,
195 wfTimestamp( TS_UNIX, '20010115123456' ),
196 'TS_MW to TS_UNIX' );
197 $this->assertEquals(
198 '2001-01-15 12:34:56',
199 wfTimestamp( TS_DB, '20010115123456' ),
200 'TS_MW to TS_DB' );
201 $this->assertEquals(
202 '20010115T123456Z',
203 wfTimestamp( TS_ISO_8601_BASIC, '20010115123456' ),
204 'TS_MW to TS_ISO_8601_BASIC' );
205
206 $this->assertEquals(
207 '20010115123456',
208 wfTimestamp( TS_MW, '2001-01-15 12:34:56' ),
209 'TS_DB to TS_MW' );
210 $this->assertEquals(
211 979562096,
212 wfTimestamp( TS_UNIX, '2001-01-15 12:34:56' ),
213 'TS_DB to TS_UNIX' );
214 $this->assertEquals(
215 '2001-01-15 12:34:56',
216 wfTimestamp( TS_DB, '2001-01-15 12:34:56' ),
217 'TS_DB to TS_DB' );
218 $this->assertEquals(
219 '20010115T123456Z',
220 wfTimestamp( TS_ISO_8601_BASIC, '2001-01-15 12:34:56' ),
221 'TS_DB to TS_ISO_8601_BASIC' );
222
223 # rfc2822 section 3.3
224
225 $this->assertEquals(
226 'Mon, 15 Jan 2001 12:34:56 GMT',
227 wfTimestamp( TS_RFC2822, '20010115123456' ),
228 'TS_MW to TS_RFC2822' );
229
230 $this->assertEquals(
231 '20010115123456',
232 wfTimestamp( TS_MW, 'Mon, 15 Jan 2001 12:34:56 GMT' ),
233 'TS_RFC2822 to TS_MW' );
234
235 $this->assertEquals(
236 '20010115123456',
237 wfTimestamp( TS_MW, ' Mon, 15 Jan 2001 12:34:56 GMT' ),
238 'TS_RFC2822 with leading space to TS_MW' );
239
240 $this->assertEquals(
241 '20010115123456',
242 wfTimestamp( TS_MW, '15 Jan 2001 12:34:56 GMT' ),
243 'TS_RFC2822 without optional day-of-week to TS_MW' );
244
245 # FWS = ([*WSP CRLF] 1*WSP) / obs-FWS ; Folding white space
246 # obs-FWS = 1*WSP *(CRLF 1*WSP) ; Section 4.2
247 $this->assertEquals(
248 '20010115123456',
249 wfTimestamp( TS_MW, 'Mon, 15 Jan 2001 12:34:56 GMT' ),
250 'TS_RFC2822 to TS_MW' );
251
252 # WSP = SP / HTAB ; rfc2234
253 $this->assertEquals(
254 '20010115123456',
255 wfTimestamp( TS_MW, "Mon, 15 Jan\x092001 12:34:56 GMT" ),
256 'TS_RFC2822 with HTAB to TS_MW' );
257
258 $this->assertEquals(
259 '20010115123456',
260 wfTimestamp( TS_MW, "Mon, 15 Jan\x09 \x09 2001 12:34:56 GMT" ),
261 'TS_RFC2822 with HTAB and SP to TS_MW' );
262
263 $this->assertEquals(
264 '19941106084937',
265 wfTimestamp( TS_MW, "Sun, 6 Nov 94 08:49:37 GMT" ),
266 'TS_RFC2822 with obsolete year to TS_MW' );
267 }
268
269 /**
270 * This test checks wfTimestamp() with values outside.
271 * It needs PHP 64 bits or PHP > 5.1.
272 * See r74778 and bug 25451
273 */
274 function testOldTimestamps() {
275 $this->assertEquals( 'Fri, 13 Dec 1901 20:45:54 GMT',
276 wfTimestamp( TS_RFC2822, '19011213204554' ),
277 'Earliest time according to php documentation' );
278
279 $this->assertEquals( 'Tue, 19 Jan 2038 03:14:07 GMT',
280 wfTimestamp( TS_RFC2822, '20380119031407' ),
281 'Latest 32 bit time' );
282
283 $this->assertEquals( '-2147483648',
284 wfTimestamp( TS_UNIX, '19011213204552' ),
285 'Earliest 32 bit unix time' );
286
287 $this->assertEquals( '2147483647',
288 wfTimestamp( TS_UNIX, '20380119031407' ),
289 'Latest 32 bit unix time' );
290
291 $this->assertEquals( 'Fri, 13 Dec 1901 20:45:52 GMT',
292 wfTimestamp( TS_RFC2822, '19011213204552' ),
293 'Earliest 32 bit time' );
294
295 $this->assertEquals( 'Fri, 13 Dec 1901 20:45:51 GMT',
296 wfTimestamp( TS_RFC2822, '19011213204551' ),
297 'Earliest 32 bit time - 1' );
298
299 $this->assertEquals( 'Tue, 19 Jan 2038 03:14:08 GMT',
300 wfTimestamp( TS_RFC2822, '20380119031408' ),
301 'Latest 32 bit time + 1' );
302
303 $this->assertEquals( '19011212000000',
304 wfTimestamp(TS_MW, '19011212000000'),
305 'Convert to itself r74778#c10645' );
306
307 $this->assertEquals( '-2147483649',
308 wfTimestamp( TS_UNIX, '19011213204551' ),
309 'Earliest 32 bit unix time - 1' );
310
311 $this->assertEquals( '2147483648',
312 wfTimestamp( TS_UNIX, '20380119031408' ),
313 'Latest 32 bit unix time + 1' );
314
315 $this->assertEquals( '19011213204551',
316 wfTimestamp( TS_MW, '-2147483649' ),
317 '1901 negative unix time to MediaWiki' );
318
319 $this->assertEquals( '18010115123456',
320 wfTimestamp( TS_MW, '-5331871504' ),
321 '1801 negative unix time to MediaWiki' );
322
323 $this->assertEquals( 'Tue, 09 Aug 0117 12:34:56 GMT',
324 wfTimestamp( TS_RFC2822, '0117-08-09 12:34:56'),
325 'Death of Roman Emperor [[Trajan]]');
326
327 /* FIXME: 00 to 101 years are taken as being in [1970-2069] */
328
329 $this->assertEquals( 'Sun, 01 Jan 0101 00:00:00 GMT',
330 wfTimestamp( TS_RFC2822, '-58979923200'),
331 '1/1/101');
332
333 $this->assertEquals( 'Mon, 01 Jan 0001 00:00:00 GMT',
334 wfTimestamp( TS_RFC2822, '-62135596800'),
335 'Year 1');
336
337 /* It is not clear if we should generate a year 0 or not
338 * We are completely off RFC2822 requirement of year being
339 * 1900 or later.
340 */
341 $this->assertEquals( 'Wed, 18 Oct 0000 00:00:00 GMT',
342 wfTimestamp( TS_RFC2822, '-62142076800'),
343 'ISO 8601:2004 [[year 0]], also called [[1 BC]]');
344 }
345
346 function testHttpDate() {
347 # The Resource Loader uses wfTimestamp() to convert timestamps
348 # from If-Modified-Since header.
349 # Thus it must be able to parse all rfc2616 date formats
350 # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1
351
352 $this->assertEquals(
353 '19941106084937',
354 wfTimestamp( TS_MW, 'Sun, 06 Nov 1994 08:49:37 GMT' ),
355 'RFC 822 date' );
356
357 $this->assertEquals(
358 '19941106084937',
359 wfTimestamp( TS_MW, 'Sunday, 06-Nov-94 08:49:37 GMT' ),
360 'RFC 850 date' );
361
362 $this->assertEquals(
363 '19941106084937',
364 wfTimestamp( TS_MW, 'Sun Nov 6 08:49:37 1994' ),
365 "ANSI C's asctime() format" );
366
367 // See http://www.squid-cache.org/mail-archive/squid-users/200307/0122.html and r77171
368 $this->assertEquals(
369 '20101122141242',
370 wfTimestamp( TS_MW, 'Mon, 22 Nov 2010 14:12:42 GMT; length=52626' ),
371 "Netscape extension to HTTP/1.0" );
372
373 }
374
375 function testTimestampParameter() {
376 // There are a number of assumptions in our codebase where wfTimestamp() should give
377 // the current date but it is not given a 0 there. See r71751 CR
378
379 $now = wfTimestamp( TS_UNIX );
380 // We check that wfTimestamp doesn't return false (error) and use a LessThan assert
381 // for the cases where the test is run in a second boundary.
382
383 $zero = wfTimestamp( TS_UNIX, 0 );
384 $this->assertNotEquals( false, $zero );
385 $this->assertLessThan( 5, $zero - $now );
386
387 $empty = wfTimestamp( TS_UNIX, '' );
388 $this->assertNotEquals( false, $empty );
389 $this->assertLessThan( 5, $empty - $now );
390
391 $null = wfTimestamp( TS_UNIX, null );
392 $this->assertNotEquals( false, $null );
393 $this->assertLessThan( 5, $null - $now );
394 }
395
396 function testBasename() {
397 $sets = array(
398 '' => '',
399 '/' => '',
400 '\\' => '',
401 '//' => '',
402 '\\\\' => '',
403 'a' => 'a',
404 'aaaa' => 'aaaa',
405 '/a' => 'a',
406 '\\a' => 'a',
407 '/aaaa' => 'aaaa',
408 '\\aaaa' => 'aaaa',
409 '/aaaa/' => 'aaaa',
410 '\\aaaa\\' => 'aaaa',
411 '\\aaaa\\' => 'aaaa',
412 '/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',
413 'C:\\Progra~1\\Wikime~1\\Wikipe~1\\VIEWER.EXE' => 'VIEWER.EXE',
414 'Östergötland_coat_of_arms.png' => 'Östergötland_coat_of_arms.png',
415 );
416 foreach ( $sets as $from => $to ) {
417 $this->assertEquals( $to, wfBaseName( $from ),
418 "wfBaseName('$from') => '$to'" );
419 }
420 }
421
422
423 function testFallbackMbstringFunctions() {
424
425 if( !extension_loaded( 'mbstring' ) ) {
426 $this->markTestSkipped( "The mb_string functions must be installed to test the fallback functions" );
427 }
428
429 $sampleUTF = "Östergötland_coat_of_arms.png";
430
431
432 //mb_substr
433 $substr_params = array(
434 array( 0, 0 ),
435 array( 5, -4 ),
436 array( 33 ),
437 array( 100, -5 ),
438 array( -8, 10 ),
439 array( 1, 1 ),
440 array( 2, -1 )
441 );
442
443 foreach( $substr_params as $param_set ) {
444 $old_param_set = $param_set;
445 array_unshift( $param_set, $sampleUTF );
446
447 $this->assertEquals(
448 MWFunction::callArray( 'mb_substr', $param_set ),
449 MWFunction::callArray( 'Fallback::mb_substr', $param_set ),
450 'Fallback mb_substr with params ' . implode( ', ', $old_param_set )
451 );
452 }
453
454
455 //mb_strlen
456 $this->assertEquals(
457 mb_strlen( $sampleUTF ),
458 Fallback::mb_strlen( $sampleUTF ),
459 'Fallback mb_strlen'
460 );
461
462
463 //mb_str(r?)pos
464 $strpos_params = array(
465 //array( 'ter' ),
466 //array( 'Ö' ),
467 //array( 'Ö', 3 ),
468 //array( 'oat_', 100 ),
469 //array( 'c', -10 ),
470 //Broken for now
471 );
472
473 foreach( $strpos_params as $param_set ) {
474 $old_param_set = $param_set;
475 array_unshift( $param_set, $sampleUTF );
476
477 $this->assertEquals(
478 MWFunction::callArray( 'mb_strpos', $param_set ),
479 MWFunction::callArray( 'Fallback::mb_strpos', $param_set ),
480 'Fallback mb_strpos with params ' . implode( ', ', $old_param_set )
481 );
482
483 $this->assertEquals(
484 MWFunction::callArray( 'mb_strrpos', $param_set ),
485 MWFunction::callArray( 'Fallback::mb_strrpos', $param_set ),
486 'Fallback mb_strrpos with params ' . implode( ', ', $old_param_set )
487 );
488 }
489
490 }
491
492
493 function testDebugFunctionTest() {
494
495 global $wgDebugLogFile, $wgOut, $wgShowDebug;
496
497 $old_log_file = $wgDebugLogFile;
498 $wgDebugLogFile = tempnam( wfTempDir(), 'mw-' );
499
500
501
502 wfDebug( "This is a normal string" );
503 $this->assertEquals( "This is a normal string", file_get_contents( $wgDebugLogFile ) );
504 unlink( $wgDebugLogFile );
505
506
507 wfDebug( "This is nöt an ASCII string" );
508 $this->assertEquals( "This is nöt an ASCII string", file_get_contents( $wgDebugLogFile ) );
509 unlink( $wgDebugLogFile );
510
511
512 wfDebug( "\00305This has böth UTF and control chars\003" );
513 $this->assertEquals( " 05This has böth UTF and control chars ", file_get_contents( $wgDebugLogFile ) );
514 unlink( $wgDebugLogFile );
515
516
517
518 $old_wgOut = $wgOut;
519 $old_wgShowDebug = $wgShowDebug;
520
521 $wgOut = new StubObject( 'wgOut', 'MockOutputPage' );
522 $wgOut->doNothing(); //just to unstub it
523
524 $wgShowDebug = true;
525
526 $message = "\00305This has böth UTF and control chars\003";
527
528 wfDebug( $message );
529
530 if( $wgOut->message == "JAJA is a stupid error message. Anyway, here's your message: $message" ) {
531 $this->assertTrue( true, 'MockOutputPage called, set the proper message.' );
532 }
533 else {
534 $this->assertTrue( false, 'MockOutputPage was not called.' );
535 }
536
537 $wgOut = $old_wgOut;
538 $wgShowDebug = $old_wgShowDebug;
539 unlink( $wgDebugLogFile );
540
541
542
543 wfDebugMem();
544 $this->assertGreaterThan( 5000, preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) ) );
545 unlink( $wgDebugLogFile );
546
547 wfDebugMem(true);
548 $this->assertGreaterThan( 5000000, preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) ) );
549 unlink( $wgDebugLogFile );
550
551
552
553 $wgDebugLogFile = $old_log_file;
554
555 }
556
557 function testClientAcceptsGzipTest() {
558
559 $settings = array(
560 'gzip' => true,
561 'bzip' => false,
562 '*' => false,
563 'compress, gzip' => true,
564 'gzip;q=1.0' => true,
565 'foozip' => false,
566 'foo*zip' => false,
567 'gzip;q=abcde' => true, //is this REALLY valid?
568 'gzip;q=12345678.9' => true,
569 ' gzip' => true,
570 );
571
572 if( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) $old_server_setting = $_SERVER['HTTP_ACCEPT_ENCODING'];
573
574 foreach ( $settings as $encoding => $expect ) {
575 $_SERVER['HTTP_ACCEPT_ENCODING'] = $encoding;
576
577 $this->assertEquals( $expect, wfClientAcceptsGzip( true ),
578 "'$encoding' => " . wfBoolToStr( $expect ) );
579 }
580
581 if( isset( $old_server_setting ) ) $_SERVER['HTTP_ACCEPT_ENCODING'] = $old_server_setting;
582
583 }
584
585
586
587 function testSwapVarsTest() {
588
589
590 $var1 = 1;
591 $var2 = 2;
592
593 $this->assertEquals( $var1, 1, 'var1 is set originally' );
594 $this->assertEquals( $var2, 2, 'var1 is set originally' );
595
596 swap( $var1, $var2 );
597
598 $this->assertEquals( $var1, 2, 'var1 is swapped' );
599 $this->assertEquals( $var2, 1, 'var2 is swapped' );
600
601 }
602
603
604 function testWfPercentTest() {
605
606 $pcts = array(
607 array( 6/7, '0.86%', 2, false ),
608 array( 3/3, '1%' ),
609 array( 22/7, '3.14286%', 5 ),
610 array( 3/6, '0.5%' ),
611 array( 1/3, '0%', 0 ),
612 array( 10/3, '0%', -1 ),
613 array( 3/4/5, '0.1%', 1 ),
614 array( 6/7*8, '6.8571428571%', 10 ),
615 );
616
617 foreach( $pcts as $pct ) {
618 if( !isset( $pct[2] ) ) $pct[2] = 2;
619 if( !isset( $pct[3] ) ) $pct[3] = true;
620
621 $this->assertEquals( wfPercent( $pct[0], $pct[2], $pct[3] ), $pct[1], $pct[1] );
622 }
623
624 }
625
626
627 function testInStringTest() {
628
629 $this->assertTrue( in_string( 'foo', 'foobar' ), 'foo is in foobar' );
630 $this->assertFalse( in_string( 'Bar', 'foobar' ), 'Case-sensitive by default' );
631 $this->assertTrue( in_string( 'Foo', 'foobar', true ), 'Case-insensitive when asked' );
632
633 }
634
635 /* TODO: many more! */
636 }
637
638
639 class MockOutputPage {
640
641 public $message;
642
643 function debug( $message ) {
644 $this->message = "JAJA is a stupid error message. Anyway, here's your message: $message";
645 }
646
647 function doNothing() {}
648 }
649