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