Merge "(bug 43052) dblClickEdit/rightClickEdit: Trigger ca-edit click."
[lhc/web/wiklou.git] / tests / phpunit / languages / LanguageTest.php
1 <?php
2
3 class LanguageTest extends LanguageClassesTestCase {
4
5 function testLanguageConvertDoubleWidthToSingleWidth() {
6 $this->assertEquals(
7 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
8 $this->getLang()->normalizeForSearch(
9 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
10 ),
11 'convertDoubleWidth() with the full alphabet and digits'
12 );
13 }
14
15 /**
16 * @dataProvider provideFormattableTimes
17 */
18 function testFormatTimePeriod( $seconds, $format, $expected, $desc ) {
19 $this->assertEquals( $expected, $this->getLang()->formatTimePeriod( $seconds, $format ), $desc );
20 }
21
22 function provideFormattableTimes() {
23 return array(
24 array(
25 9.45,
26 array(),
27 '9.5 s',
28 'formatTimePeriod() rounding (<10s)'
29 ),
30 array(
31 9.45,
32 array( 'noabbrevs' => true ),
33 '9.5 seconds',
34 'formatTimePeriod() rounding (<10s)'
35 ),
36 array(
37 9.95,
38 array(),
39 '10 s',
40 'formatTimePeriod() rounding (<10s)'
41 ),
42 array(
43 9.95,
44 array( 'noabbrevs' => true ),
45 '10 seconds',
46 'formatTimePeriod() rounding (<10s)'
47 ),
48 array(
49 59.55,
50 array(),
51 '1 min 0 s',
52 'formatTimePeriod() rounding (<60s)'
53 ),
54 array(
55 59.55,
56 array( 'noabbrevs' => true ),
57 '1 minute 0 seconds',
58 'formatTimePeriod() rounding (<60s)'
59 ),
60 array(
61 119.55,
62 array(),
63 '2 min 0 s',
64 'formatTimePeriod() rounding (<1h)'
65 ),
66 array(
67 119.55,
68 array( 'noabbrevs' => true ),
69 '2 minutes 0 seconds',
70 'formatTimePeriod() rounding (<1h)'
71 ),
72 array(
73 3599.55,
74 array(),
75 '1 h 0 min 0 s',
76 'formatTimePeriod() rounding (<1h)'
77 ),
78 array(
79 3599.55,
80 array( 'noabbrevs' => true ),
81 '1 hour 0 minutes 0 seconds',
82 'formatTimePeriod() rounding (<1h)'
83 ),
84 array(
85 7199.55,
86 array(),
87 '2 h 0 min 0 s',
88 'formatTimePeriod() rounding (>=1h)'
89 ),
90 array(
91 7199.55,
92 array( 'noabbrevs' => true ),
93 '2 hours 0 minutes 0 seconds',
94 'formatTimePeriod() rounding (>=1h)'
95 ),
96 array(
97 7199.55,
98 'avoidseconds',
99 '2 h 0 min',
100 'formatTimePeriod() rounding (>=1h), avoidseconds'
101 ),
102 array(
103 7199.55,
104 array( 'avoid' => 'avoidseconds', 'noabbrevs' => true ),
105 '2 hours 0 minutes',
106 'formatTimePeriod() rounding (>=1h), avoidseconds'
107 ),
108 array(
109 7199.55,
110 'avoidminutes',
111 '2 h 0 min',
112 'formatTimePeriod() rounding (>=1h), avoidminutes'
113 ),
114 array(
115 7199.55,
116 array( 'avoid' => 'avoidminutes', 'noabbrevs' => true ),
117 '2 hours 0 minutes',
118 'formatTimePeriod() rounding (>=1h), avoidminutes'
119 ),
120 array(
121 172799.55,
122 'avoidseconds',
123 '48 h 0 min',
124 'formatTimePeriod() rounding (=48h), avoidseconds'
125 ),
126 array(
127 172799.55,
128 array( 'avoid' => 'avoidseconds', 'noabbrevs' => true ),
129 '48 hours 0 minutes',
130 'formatTimePeriod() rounding (=48h), avoidseconds'
131 ),
132 array(
133 259199.55,
134 'avoidminutes',
135 '3 d 0 h',
136 'formatTimePeriod() rounding (>48h), avoidminutes'
137 ),
138 array(
139 259199.55,
140 array( 'avoid' => 'avoidminutes', 'noabbrevs' => true ),
141 '3 days 0 hours',
142 'formatTimePeriod() rounding (>48h), avoidminutes'
143 ),
144 array(
145 176399.55,
146 'avoidseconds',
147 '2 d 1 h 0 min',
148 'formatTimePeriod() rounding (>48h), avoidseconds'
149 ),
150 array(
151 176399.55,
152 array( 'avoid' => 'avoidseconds', 'noabbrevs' => true ),
153 '2 days 1 hour 0 minutes',
154 'formatTimePeriod() rounding (>48h), avoidseconds'
155 ),
156 array(
157 176399.55,
158 'avoidminutes',
159 '2 d 1 h',
160 'formatTimePeriod() rounding (>48h), avoidminutes'
161 ),
162 array(
163 176399.55,
164 array( 'avoid' => 'avoidminutes', 'noabbrevs' => true ),
165 '2 days 1 hour',
166 'formatTimePeriod() rounding (>48h), avoidminutes'
167 ),
168 array(
169 259199.55,
170 'avoidseconds',
171 '3 d 0 h 0 min',
172 'formatTimePeriod() rounding (>48h), avoidseconds'
173 ),
174 array(
175 259199.55,
176 array( 'avoid' => 'avoidseconds', 'noabbrevs' => true ),
177 '3 days 0 hours 0 minutes',
178 'formatTimePeriod() rounding (>48h), avoidseconds'
179 ),
180 array(
181 172801.55,
182 'avoidseconds',
183 '2 d 0 h 0 min',
184 'formatTimePeriod() rounding, (>48h), avoidseconds'
185 ),
186 array(
187 172801.55,
188 array( 'avoid' => 'avoidseconds', 'noabbrevs' => true ),
189 '2 days 0 hours 0 minutes',
190 'formatTimePeriod() rounding, (>48h), avoidseconds'
191 ),
192 array(
193 176460.55,
194 array(),
195 '2 d 1 h 1 min 1 s',
196 'formatTimePeriod() rounding, recursion, (>48h)'
197 ),
198 array(
199 176460.55,
200 array( 'noabbrevs' => true ),
201 '2 days 1 hour 1 minute 1 second',
202 'formatTimePeriod() rounding, recursion, (>48h)'
203 ),
204 );
205
206 }
207
208 function testTruncate() {
209 $this->assertEquals(
210 "XXX",
211 $this->getLang()->truncate( "1234567890", 0, 'XXX' ),
212 'truncate prefix, len 0, small ellipsis'
213 );
214
215 $this->assertEquals(
216 "12345XXX",
217 $this->getLang()->truncate( "1234567890", 8, 'XXX' ),
218 'truncate prefix, small ellipsis'
219 );
220
221 $this->assertEquals(
222 "123456789",
223 $this->getLang()->truncate( "123456789", 5, 'XXXXXXXXXXXXXXX' ),
224 'truncate prefix, large ellipsis'
225 );
226
227 $this->assertEquals(
228 "XXX67890",
229 $this->getLang()->truncate( "1234567890", -8, 'XXX' ),
230 'truncate suffix, small ellipsis'
231 );
232
233 $this->assertEquals(
234 "123456789",
235 $this->getLang()->truncate( "123456789", -5, 'XXXXXXXXXXXXXXX' ),
236 'truncate suffix, large ellipsis'
237 );
238 }
239
240 /**
241 * @dataProvider provideHTMLTruncateData()
242 */
243 function testTruncateHtml( $len, $ellipsis, $input, $expected ) {
244 // Actual HTML...
245 $this->assertEquals(
246 $expected,
247 $this->getLang()->truncateHTML( $input, $len, $ellipsis )
248 );
249 }
250
251 /**
252 * Array format is ($len, $ellipsis, $input, $expected)
253 */
254 function provideHTMLTruncateData() {
255 return array(
256 array( 0, 'XXX', "1234567890", "XXX" ),
257 array( 8, 'XXX', "1234567890", "12345XXX" ),
258 array( 5, 'XXXXXXXXXXXXXXX', '1234567890', "1234567890" ),
259 array( 2, '***',
260 '<p><span style="font-weight:bold;"></span></p>',
261 '<p><span style="font-weight:bold;"></span></p>',
262 ),
263 array( 2, '***',
264 '<p><span style="font-weight:bold;">123456789</span></p>',
265 '<p><span style="font-weight:bold;">***</span></p>',
266 ),
267 array( 2, '***',
268 '<p><span style="font-weight:bold;">&nbsp;23456789</span></p>',
269 '<p><span style="font-weight:bold;">***</span></p>',
270 ),
271 array( 3, '***',
272 '<p><span style="font-weight:bold;">123456789</span></p>',
273 '<p><span style="font-weight:bold;">***</span></p>',
274 ),
275 array( 4, '***',
276 '<p><span style="font-weight:bold;">123456789</span></p>',
277 '<p><span style="font-weight:bold;">1***</span></p>',
278 ),
279 array( 5, '***',
280 '<tt><span style="font-weight:bold;">123456789</span></tt>',
281 '<tt><span style="font-weight:bold;">12***</span></tt>',
282 ),
283 array( 6, '***',
284 '<p><a href="www.mediawiki.org">123456789</a></p>',
285 '<p><a href="www.mediawiki.org">123***</a></p>',
286 ),
287 array( 6, '***',
288 '<p><a href="www.mediawiki.org">12&nbsp;456789</a></p>',
289 '<p><a href="www.mediawiki.org">12&nbsp;***</a></p>',
290 ),
291 array( 7, '***',
292 '<small><span style="font-weight:bold;">123<p id="#moo">456</p>789</span></small>',
293 '<small><span style="font-weight:bold;">123<p id="#moo">4***</p></span></small>',
294 ),
295 array( 8, '***',
296 '<div><span style="font-weight:bold;">123<span>4</span>56789</span></div>',
297 '<div><span style="font-weight:bold;">123<span>4</span>5***</span></div>',
298 ),
299 array( 9, '***',
300 '<p><table style="font-weight:bold;"><tr><td>123456789</td></tr></table></p>',
301 '<p><table style="font-weight:bold;"><tr><td>123456789</td></tr></table></p>',
302 ),
303 array( 10, '***',
304 '<p><font style="font-weight:bold;">123456789</font></p>',
305 '<p><font style="font-weight:bold;">123456789</font></p>',
306 ),
307 );
308 }
309
310 /**
311 * Test Language::isValidBuiltInCode()
312 * @dataProvider provideLanguageCodes
313 */
314 function testBuiltInCodeValidation( $code, $message = '' ) {
315 $this->assertTrue(
316 (bool) Language::isValidBuiltInCode( $code ),
317 "validating code $code $message"
318 );
319 }
320
321 function testBuiltInCodeValidationRejectUnderscore() {
322 $this->assertFalse(
323 (bool) Language::isValidBuiltInCode( 'be_tarask' ),
324 "reject underscore in language code"
325 );
326 }
327
328 function provideLanguageCodes() {
329 return array(
330 array( 'fr' , 'Two letters, minor case' ),
331 array( 'EN' , 'Two letters, upper case' ),
332 array( 'tyv' , 'Three letters' ),
333 array( 'tokipona' , 'long language code' ),
334 array( 'be-tarask', 'With dash' ),
335 array( 'Zh-classical', 'Begin with upper case, dash' ),
336 array( 'Be-x-old', 'With extension (two dashes)' ),
337 );
338 }
339
340 /**
341 * @dataProvider provideSprintfDateSamples
342 */
343 function testSprintfDate( $format, $ts, $expected, $msg ) {
344 $this->assertEquals(
345 $expected,
346 $this->getLang()->sprintfDate( $format, $ts ),
347 "sprintfDate('$format', '$ts'): $msg"
348 );
349 }
350 /**
351 * bug 33454. sprintfDate should always use UTC.
352 * @dataProvider provideSprintfDateSamples
353 */
354 function testSprintfDateTZ( $format, $ts, $expected, $msg ) {
355 $oldTZ = date_default_timezone_get();
356 $res = date_default_timezone_set( 'Asia/Seoul' );
357 if ( !$res ) {
358 $this->markTestSkipped( "Error setting Timezone" );
359 }
360
361 $this->assertEquals(
362 $expected,
363 $this->getLang()->sprintfDate( $format, $ts ),
364 "sprintfDate('$format', '$ts'): $msg"
365 );
366
367 date_default_timezone_set( $oldTZ );
368 }
369
370 function provideSprintfDateSamples() {
371 return array(
372 array(
373 'xiY',
374 '20111212000000',
375 '1390', // note because we're testing English locale we get Latin-standard digits
376 'Iranian calendar full year'
377 ),
378 array(
379 'xiy',
380 '20111212000000',
381 '90',
382 'Iranian calendar short year'
383 ),
384 array(
385 'o',
386 '20120101235000',
387 '2011',
388 'ISO 8601 (week) year'
389 ),
390 array(
391 'W',
392 '20120101235000',
393 '52',
394 'Week number'
395 ),
396 array(
397 'W',
398 '20120102235000',
399 '1',
400 'Week number'
401 ),
402 array(
403 'o-\\WW-N',
404 '20091231235000',
405 '2009-W53-4',
406 'leap week'
407 ),
408 // What follows is mostly copied from http://www.mediawiki.org/wiki/Help:Extension:ParserFunctions#.23time
409 array(
410 'Y',
411 '20120102090705',
412 '2012',
413 'Full year'
414 ),
415 array(
416 'y',
417 '20120102090705',
418 '12',
419 '2 digit year'
420 ),
421 array(
422 'L',
423 '20120102090705',
424 '1',
425 'Leap year'
426 ),
427 array(
428 'n',
429 '20120102090705',
430 '1',
431 'Month index, not zero pad'
432 ),
433 array(
434 'N',
435 '20120102090705',
436 '01',
437 'Month index. Zero pad'
438 ),
439 array(
440 'M',
441 '20120102090705',
442 'Jan',
443 'Month abbrev'
444 ),
445 array(
446 'F',
447 '20120102090705',
448 'January',
449 'Full month'
450 ),
451 array(
452 'xg',
453 '20120102090705',
454 'January',
455 'Genitive month name (same in EN)'
456 ),
457 array(
458 'j',
459 '20120102090705',
460 '2',
461 'Day of month (not zero pad)'
462 ),
463 array(
464 'd',
465 '20120102090705',
466 '02',
467 'Day of month (zero-pad)'
468 ),
469 array(
470 'z',
471 '20120102090705',
472 '1',
473 'Day of year (zero-indexed)'
474 ),
475 array(
476 'D',
477 '20120102090705',
478 'Mon',
479 'Day of week (abbrev)'
480 ),
481 array(
482 'l',
483 '20120102090705',
484 'Monday',
485 'Full day of week'
486 ),
487 array(
488 'N',
489 '20120101090705',
490 '7',
491 'Day of week (Mon=1, Sun=7)'
492 ),
493 array(
494 'w',
495 '20120101090705',
496 '0',
497 'Day of week (Sun=0, Sat=6)'
498 ),
499 array(
500 'N',
501 '20120102090705',
502 '1',
503 'Day of week'
504 ),
505 array(
506 'a',
507 '20120102090705',
508 'am',
509 'am vs pm'
510 ),
511 array(
512 'A',
513 '20120102120000',
514 'PM',
515 'AM vs PM'
516 ),
517 array(
518 'a',
519 '20120102000000',
520 'am',
521 'AM vs PM'
522 ),
523 array(
524 'g',
525 '20120102090705',
526 '9',
527 '12 hour, not Zero'
528 ),
529 array(
530 'h',
531 '20120102090705',
532 '09',
533 '12 hour, zero padded'
534 ),
535 array(
536 'G',
537 '20120102090705',
538 '9',
539 '24 hour, not zero'
540 ),
541 array(
542 'H',
543 '20120102090705',
544 '09',
545 '24 hour, zero'
546 ),
547 array(
548 'H',
549 '20120102110705',
550 '11',
551 '24 hour, zero'
552 ),
553 array(
554 'i',
555 '20120102090705',
556 '07',
557 'Minutes'
558 ),
559 array(
560 's',
561 '20120102090705',
562 '05',
563 'seconds'
564 ),
565 array(
566 'U',
567 '20120102090705',
568 '1325495225',
569 'unix time'
570 ),
571 array(
572 't',
573 '20120102090705',
574 '31',
575 'Days in current month'
576 ),
577 array(
578 'c',
579 '20120102090705',
580 '2012-01-02T09:07:05+00:00',
581 'ISO 8601 timestamp'
582 ),
583 array(
584 'r',
585 '20120102090705',
586 'Mon, 02 Jan 2012 09:07:05 +0000',
587 'RFC 5322'
588 ),
589 array(
590 'xmj xmF xmn xmY',
591 '20120102090705',
592 '7 Safar 2 1433',
593 'Islamic'
594 ),
595 array(
596 'xij xiF xin xiY',
597 '20120102090705',
598 '12 Dey 10 1390',
599 'Iranian'
600 ),
601 array(
602 'xjj xjF xjn xjY',
603 '20120102090705',
604 '7 Tevet 4 5772',
605 'Hebrew'
606 ),
607 array(
608 'xjt',
609 '20120102090705',
610 '29',
611 'Hebrew number of days in month'
612 ),
613 array(
614 'xjx',
615 '20120102090705',
616 'Tevet',
617 'Hebrew genitive month name (No difference in EN)'
618 ),
619 array(
620 'xkY',
621 '20120102090705',
622 '2555',
623 'Thai year'
624 ),
625 array(
626 'xoY',
627 '20120102090705',
628 '101',
629 'Minguo'
630 ),
631 array(
632 'xtY',
633 '20120102090705',
634 '平成24',
635 'nengo'
636 ),
637 array(
638 'xrxkYY',
639 '20120102090705',
640 'MMDLV2012',
641 'Roman numerals'
642 ),
643 array(
644 'xhxjYY',
645 '20120102090705',
646 \'תשע"ב2012',
647 'Hebrew numberals'
648 ),
649 array(
650 'xnY',
651 '20120102090705',
652 '2012',
653 'Raw numerals (doesn\'t mean much in EN)'
654 ),
655 array(
656 '[[Y "(yea"\\r)]] \\"xx\\"',
657 '20120102090705',
658 '[[2012 (year)]] "x"',
659 'Various escaping'
660 ),
661
662 );
663 }
664
665 /**
666 * @dataProvider provideFormatSizes
667 */
668 function testFormatSize( $size, $expected, $msg ) {
669 $this->assertEquals(
670 $expected,
671 $this->getLang()->formatSize( $size ),
672 "formatSize('$size'): $msg"
673 );
674 }
675
676 function provideFormatSizes() {
677 return array(
678 array(
679 0,
680 "0 B",
681 "Zero bytes"
682 ),
683 array(
684 1024,
685 "1 KB",
686 "1 kilobyte"
687 ),
688 array(
689 1024 * 1024,
690 "1 MB",
691 "1,024 megabytes"
692 ),
693 array(
694 1024 * 1024 * 1024,
695 "1 GB",
696 "1 gigabytes"
697 ),
698 array(
699 pow( 1024, 4 ),
700 "1 TB",
701 "1 terabyte"
702 ),
703 array(
704 pow( 1024, 5 ),
705 "1 PB",
706 "1 petabyte"
707 ),
708 array(
709 pow( 1024, 6 ),
710 "1 EB",
711 "1,024 exabyte"
712 ),
713 array(
714 pow( 1024, 7 ),
715 "1 ZB",
716 "1 zetabyte"
717 ),
718 array(
719 pow( 1024, 8 ),
720 "1 YB",
721 "1 yottabyte"
722 ),
723 // How big!? THIS BIG!
724 );
725 }
726
727 /**
728 * @dataProvider provideFormatBitrate
729 */
730 function testFormatBitrate( $bps, $expected, $msg ) {
731 $this->assertEquals(
732 $expected,
733 $this->getLang()->formatBitrate( $bps ),
734 "formatBitrate('$bps'): $msg"
735 );
736 }
737
738 function provideFormatBitrate() {
739 return array(
740 array(
741 0,
742 "0bps",
743 "0 bits per second"
744 ),
745 array(
746 999,
747 "999bps",
748 "999 bits per second"
749 ),
750 array(
751 1000,
752 "1kbps",
753 "1 kilobit per second"
754 ),
755 array(
756 1000 * 1000,
757 "1Mbps",
758 "1 megabit per second"
759 ),
760 array(
761 pow( 10, 9 ),
762 "1Gbps",
763 "1 gigabit per second"
764 ),
765 array(
766 pow( 10, 12 ),
767 "1Tbps",
768 "1 terabit per second"
769 ),
770 array(
771 pow( 10, 15 ),
772 "1Pbps",
773 "1 petabit per second"
774 ),
775 array(
776 pow( 10, 18 ),
777 "1Ebps",
778 "1 exabit per second"
779 ),
780 array(
781 pow( 10, 21 ),
782 "1Zbps",
783 "1 zetabit per second"
784 ),
785 array(
786 pow( 10, 24 ),
787 "1Ybps",
788 "1 yottabit per second"
789 ),
790 array(
791 pow( 10, 27 ),
792 "1,000Ybps",
793 "1,000 yottabits per second"
794 ),
795 );
796 }
797
798
799
800 /**
801 * @dataProvider provideFormatDuration
802 */
803 function testFormatDuration( $duration, $expected, $intervals = array() ) {
804 $this->assertEquals(
805 $expected,
806 $this->getLang()->formatDuration( $duration, $intervals ),
807 "formatDuration('$duration'): $expected"
808 );
809 }
810
811 function provideFormatDuration() {
812 return array(
813 array(
814 0,
815 '0 seconds',
816 ),
817 array(
818 1,
819 '1 second',
820 ),
821 array(
822 2,
823 '2 seconds',
824 ),
825 array(
826 60,
827 '1 minute',
828 ),
829 array(
830 2 * 60,
831 '2 minutes',
832 ),
833 array(
834 3600,
835 '1 hour',
836 ),
837 array(
838 2 * 3600,
839 '2 hours',
840 ),
841 array(
842 24 * 3600,
843 '1 day',
844 ),
845 array(
846 2 * 86400,
847 '2 days',
848 ),
849 array(
850 // ( 365 + ( 24 * 3 + 25 ) / 400 ) * 86400 = 31556952
851 ( 365 + ( 24 * 3 + 25 ) / 400.0 ) * 86400,
852 '1 year',
853 ),
854 array(
855 2 * 31556952,
856 '2 years',
857 ),
858 array(
859 10 * 31556952,
860 '1 decade',
861 ),
862 array(
863 20 * 31556952,
864 '2 decades',
865 ),
866 array(
867 100 * 31556952,
868 '1 century',
869 ),
870 array(
871 200 * 31556952,
872 '2 centuries',
873 ),
874 array(
875 1000 * 31556952,
876 '1 millennium',
877 ),
878 array(
879 2000 * 31556952,
880 '2 millennia',
881 ),
882 array(
883 9001,
884 '2 hours, 30 minutes and 1 second'
885 ),
886 array(
887 3601,
888 '1 hour and 1 second'
889 ),
890 array(
891 31556952 + 2 * 86400 + 9000,
892 '1 year, 2 days, 2 hours and 30 minutes'
893 ),
894 array(
895 42 * 1000 * 31556952 + 42,
896 '42 millennia and 42 seconds'
897 ),
898 array(
899 60,
900 '60 seconds',
901 array( 'seconds' ),
902 ),
903 array(
904 61,
905 '61 seconds',
906 array( 'seconds' ),
907 ),
908 array(
909 1,
910 '1 second',
911 array( 'seconds' ),
912 ),
913 array(
914 31556952 + 2 * 86400 + 9000,
915 '1 year, 2 days and 150 minutes',
916 array( 'years', 'days', 'minutes' ),
917 ),
918 array(
919 42,
920 '0 days',
921 array( 'years', 'days' ),
922 ),
923 array(
924 31556952 + 2 * 86400 + 9000,
925 '1 year, 2 days and 150 minutes',
926 array( 'minutes', 'days', 'years' ),
927 ),
928 array(
929 42,
930 '0 days',
931 array( 'days', 'years' ),
932 ),
933 );
934 }
935
936 /**
937 * @dataProvider provideCheckTitleEncodingData
938 */
939 function testCheckTitleEncoding( $s ) {
940 $this->assertEquals(
941 $s,
942 $this->getLang()->checkTitleEncoding($s),
943 "checkTitleEncoding('$s')"
944 );
945 }
946
947 function provideCheckTitleEncodingData() {
948 return array (
949 array( "" ),
950 array( "United States of America" ), // 7bit ASCII
951 array( rawurldecode( "S%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e" ) ),
952 array(
953 rawurldecode(
954 "Acteur%7CAlbert%20Robbins%7CAnglais%7CAnn%20Donahue%7CAnthony%20E.%20Zuiker%7CCarol%20Mendelsohn"
955 )
956 ),
957 // The following two data sets come from bug 36839. They fail if checkTitleEncoding uses a regexp to test for
958 // valid UTF-8 encoding and the pcre.recursion_limit is low (like, say, 1024). They succeed if checkTitleEncoding
959 // uses mb_check_encoding for its test.
960 array(
961 rawurldecode(
962 "Acteur%7CAlbert%20Robbins%7CAnglais%7CAnn%20Donahue%7CAnthony%20E.%20Zuiker%7CCarol%20Mendelsohn%7C"
963 . "Catherine%20Willows%7CDavid%20Hodges%7CDavid%20Phillips%7CGil%20Grissom%7CGreg%20Sanders%7CHodges%7C"
964 . "Internet%20Movie%20Database%7CJim%20Brass%7CLady%20Heather%7C"
965 . "Les%20Experts%20(s%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e)%7CLes%20Experts%20:%20Manhattan%7C"
966 . "Les%20Experts%20:%20Miami%7CListe%20des%20personnages%20des%20Experts%7C"
967 . "Liste%20des%20%C3%A9pisodes%20des%20Experts%7CMod%C3%A8le%20discussion:Palette%20Les%20Experts%7C"
968 . "Nick%20Stokes%7CPersonnage%20de%20fiction%7CPersonnage%20fictif%7CPersonnage%20de%20fiction%7C"
969 . "Personnages%20r%C3%A9currents%20dans%20Les%20Experts%7CRaymond%20Langston%7CRiley%20Adams%7C"
970 . "Saison%201%20des%20Experts%7CSaison%2010%20des%20Experts%7CSaison%2011%20des%20Experts%7C"
971 . "Saison%2012%20des%20Experts%7CSaison%202%20des%20Experts%7CSaison%203%20des%20Experts%7C"
972 . "Saison%204%20des%20Experts%7CSaison%205%20des%20Experts%7CSaison%206%20des%20Experts%7C"
973 . "Saison%207%20des%20Experts%7CSaison%208%20des%20Experts%7CSaison%209%20des%20Experts%7C"
974 . "Sara%20Sidle%7CSofia%20Curtis%7CS%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e%7CWallace%20Langham%7C"
975 . "Warrick%20Brown%7CWendy%20Simms%7C%C3%89tats-Unis"
976 ),
977 ),
978 array(
979 rawurldecode(
980 "Mod%C3%A8le%3AArrondissements%20homonymes%7CMod%C3%A8le%3ABandeau%20standard%20pour%20page%20d'homonymie%7C"
981 . "Mod%C3%A8le%3ABatailles%20homonymes%7CMod%C3%A8le%3ACantons%20homonymes%7C"
982 . "Mod%C3%A8le%3ACommunes%20fran%C3%A7aises%20homonymes%7CMod%C3%A8le%3AFilms%20homonymes%7C"
983 . "Mod%C3%A8le%3AGouvernements%20homonymes%7CMod%C3%A8le%3AGuerres%20homonymes%7CMod%C3%A8le%3AHomonymie%7C"
984 . "Mod%C3%A8le%3AHomonymie%20bateau%7CMod%C3%A8le%3AHomonymie%20d'%C3%A9tablissements%20scolaires%20ou"
985 . "%20universitaires%7CMod%C3%A8le%3AHomonymie%20d'%C3%AEles%7CMod%C3%A8le%3AHomonymie%20de%20clubs%20sportifs%7C"
986 . "Mod%C3%A8le%3AHomonymie%20de%20comt%C3%A9s%7CMod%C3%A8le%3AHomonymie%20de%20monument%7C"
987 . "Mod%C3%A8le%3AHomonymie%20de%20nom%20romain%7CMod%C3%A8le%3AHomonymie%20de%20parti%20politique%7C"
988 . "Mod%C3%A8le%3AHomonymie%20de%20route%7CMod%C3%A8le%3AHomonymie%20dynastique%7C"
989 . "Mod%C3%A8le%3AHomonymie%20vid%C3%A9oludique%7CMod%C3%A8le%3AHomonymie%20%C3%A9difice%20religieux%7C"
990 . "Mod%C3%A8le%3AInternationalisation%7CMod%C3%A8le%3AIsom%C3%A9rie%7CMod%C3%A8le%3AParonymie%7C"
991 . "Mod%C3%A8le%3APatronyme%7CMod%C3%A8le%3APatronyme%20basque%7CMod%C3%A8le%3APatronyme%20italien%7C"
992 . "Mod%C3%A8le%3APatronymie%7CMod%C3%A8le%3APersonnes%20homonymes%7CMod%C3%A8le%3ASaints%20homonymes%7C"
993 . "Mod%C3%A8le%3ATitres%20homonymes%7CMod%C3%A8le%3AToponymie%7CMod%C3%A8le%3AUnit%C3%A9s%20homonymes%7C"
994 . "Mod%C3%A8le%3AVilles%20homonymes%7CMod%C3%A8le%3A%C3%89difices%20religieux%20homonymes"
995 )
996 )
997 );
998 }
999
1000 /**
1001 * @dataProvider provideRomanNumeralsData
1002 */
1003 function testRomanNumerals( $num, $numerals ) {
1004 $this->assertEquals(
1005 $numerals,
1006 Language::romanNumeral( $num ),
1007 "romanNumeral('$num')"
1008 );
1009 }
1010
1011 function provideRomanNumeralsData() {
1012 return array(
1013 array( 1, 'I' ),
1014 array( 2, 'II' ),
1015 array( 3, 'III' ),
1016 array( 4, 'IV' ),
1017 array( 5, 'V' ),
1018 array( 6, 'VI' ),
1019 array( 7, 'VII' ),
1020 array( 8, 'VIII' ),
1021 array( 9, 'IX' ),
1022 array( 10, 'X' ),
1023 array( 20, 'XX' ),
1024 array( 30, 'XXX' ),
1025 array( 40, 'XL' ),
1026 array( 49, 'XLIX' ),
1027 array( 50, 'L' ),
1028 array( 60, 'LX' ),
1029 array( 70, 'LXX' ),
1030 array( 80, 'LXXX' ),
1031 array( 90, 'XC' ),
1032 array( 99, 'XCIX' ),
1033 array( 100, 'C' ),
1034 array( 200, 'CC' ),
1035 array( 300, 'CCC' ),
1036 array( 400, 'CD' ),
1037 array( 500, 'D' ),
1038 array( 600, 'DC' ),
1039 array( 700, 'DCC' ),
1040 array( 800, 'DCCC' ),
1041 array( 900, 'CM' ),
1042 array( 999, 'CMXCIX' ),
1043 array( 1000, 'M' ),
1044 array( 1989, 'MCMLXXXIX' ),
1045 array( 2000, 'MM' ),
1046 array( 3000, 'MMM' ),
1047 array( 4000, 'MMMM' ),
1048 array( 5000, 'MMMMM' ),
1049 array( 6000, 'MMMMMM' ),
1050 array( 7000, 'MMMMMMM' ),
1051 array( 8000, 'MMMMMMMM' ),
1052 array( 9000, 'MMMMMMMMM' ),
1053 array( 9999, 'MMMMMMMMMCMXCIX'),
1054 array( 10000, 'MMMMMMMMMM' ),
1055 );
1056 }
1057
1058 /**
1059 * @dataProvider providePluralData
1060 */
1061 function testConvertPlural( $expected, $number, $forms ) {
1062 $chosen = $this->getLang()->convertPlural( $number, $forms );
1063 $this->assertEquals( $expected, $chosen );
1064 }
1065
1066 function providePluralData() {
1067 return array(
1068 array( 'explicit zero', 0, array(
1069 '0=explicit zero', 'singular', 'plural'
1070 ) ),
1071 array( 'explicit one', 1, array(
1072 'singular', 'plural', '1=explicit one',
1073 ) ),
1074 array( 'singular', 1, array(
1075 'singular', 'plural', '0=explicit zero',
1076 ) ),
1077 array( 'plural', 3, array(
1078 '0=explicit zero', '1=explicit one', 'singular', 'plural'
1079 ) ),
1080 );
1081 }
1082
1083 /**
1084 * @covers Language::translateBlockExpiry()
1085 * @dataProvider provideTranslateBlockExpiry
1086 */
1087 function testTranslateBlockExpiry( $expectedData, $str, $desc ) {
1088 $lang = $this->getLang();
1089 if ( is_array( $expectedData ) ) {
1090 list( $func, $arg ) = $expectedData;
1091 $expected = $lang->$func( $arg );
1092 } else {
1093 $expected = $expectedData;
1094 }
1095 $this->assertEquals( $expected, $lang->translateBlockExpiry( $str ), $desc );
1096 }
1097
1098 function provideTranslateBlockExpiry() {
1099 return array(
1100 array( '2 hours', '2 hours', 'simple data from ipboptions' ),
1101 array( 'indefinite', 'infinite', 'infinite from ipboptions' ),
1102 array( 'indefinite', 'infinity', 'alternative infinite from ipboptions' ),
1103 array( 'indefinite', 'indefinite', 'another alternative infinite from ipboptions' ),
1104 array( array( 'formatDuration', 1023 * 60 * 60 ), '1023 hours', 'relative' ),
1105 array( array( 'formatDuration', -1023 ), '-1023 seconds', 'negative relative' ),
1106 array( array( 'formatDuration', 0 ), 'now', 'now' ),
1107 array( array( 'timeanddate', '20120102070000' ), '2012-1-1 7:00 +1 day', 'mixed, handled as absolute' ),
1108 array( array( 'timeanddate', '19910203040506' ), '1991-2-3 4:05:06', 'absolute' ),
1109 array( array( 'timeanddate', '19700101000000' ), '1970-1-1 0:00:00', 'absolute at epoch' ),
1110 array( array( 'timeanddate', '19691231235959' ), '1969-12-31 23:59:59', 'time before epoch' ),
1111 array( 'dummy', 'dummy', 'return garbage as is' ),
1112 );
1113 }
1114
1115 /**
1116 * @covers Language::commafy()
1117 * @dataProvider provideCommafyData
1118 */
1119 function testCommafy( $number, $numbersWithCommas ) {
1120 $this->assertEquals(
1121 $numbersWithCommas,
1122 $this->getLang()->commafy( $number ),
1123 "commafy('$number')"
1124 );
1125 }
1126
1127 function provideCommafyData() {
1128 return array(
1129 array( 1, '1' ),
1130 array( 10, '10' ),
1131 array( 100, '100' ),
1132 array( 1000, '1,000' ),
1133 array( 10000, '10,000' ),
1134 array( 100000, '100,000' ),
1135 array( 1000000, '1,000,000' ),
1136 array( 1.0001, '1.0001' ),
1137 array( 10.0001, '10.0001' ),
1138 array( 100.0001, '100.0001' ),
1139 array( 1000.0001, '1,000.0001' ),
1140 array( 10000.0001, '10,000.0001' ),
1141 array( 100000.0001, '100,000.0001' ),
1142 array( 1000000.0001, '1,000,000.0001' ),
1143 );
1144 }
1145
1146 function testListToText() {
1147 $lang = $this->getLang();
1148 $and = $lang->getMessageFromDB( 'and' );
1149 $s = $lang->getMessageFromDB( 'word-separator' );
1150 $c = $lang->getMessageFromDB( 'comma-separator' );
1151
1152 $this->assertEquals( '', $lang->listToText( array( ) ) );
1153 $this->assertEquals( 'a', $lang->listToText( array( 'a' ) ) );
1154 $this->assertEquals( "a{$and}{$s}b", $lang->listToText( array( 'a', 'b' ) ) );
1155 $this->assertEquals( "a{$c}b{$and}{$s}c", $lang->listToText( array( 'a', 'b', 'c' ) ) );
1156 $this->assertEquals( "a{$c}b{$c}c{$and}{$s}d", $lang->listToText( array( 'a', 'b', 'c', 'd' ) ) );
1157 }
1158 }
1159