1
2
3
4
5 package display
6
7 import (
8 "fmt"
9 "reflect"
10 "strings"
11 "testing"
12 "unicode"
13
14 "golang.org/x/text/language"
15 "golang.org/x/text/message"
16 )
17
18
19
20
21 var (
22 firstLang2aa = language.MustParseBase("aa")
23 lastLang2zu = language.MustParseBase("zu")
24 firstLang3ace = language.MustParseBase("ace")
25 lastLang3zza = language.MustParseBase("zza")
26 firstTagAr001 = language.MustParse("ar-001")
27 lastTagZhHant = language.MustParse("zh-Hant")
28 )
29
30
31
32
33
34 func TestValues(t *testing.T) {
35 type testcase struct {
36 kind string
37 n Namer
38 }
39
40 checkDefined := func(x interface{}, namers []testcase) {
41 for _, n := range namers {
42 t.Run(fmt.Sprintf("%s.Name(%s)", n.kind, x), func(t *testing.T) {
43 if n.n.Name(x) == "" {
44
45
46 if x.(fmt.Stringer).String() == "az-Arab" {
47 return
48 }
49 t.Errorf("supported but no result")
50 }
51 })
52 }
53 }
54
55 checkUnsupported := func(x interface{}, namers []testcase) {
56 for _, n := range namers {
57 if got := n.n.Name(x); got != "" {
58 t.Fatalf("%s.Name(%s): unsupported tag gave non-empty result: %q", n.kind, x, got)
59 }
60 }
61 }
62
63 tags := map[language.Tag]bool{}
64 namers := []testcase{
65 {"Languages(en)", Languages(language.English)},
66 {"Tags(en)", Tags(language.English)},
67 {"English.Languages()", English.Languages()},
68 {"English.Tags()", English.Tags()},
69 }
70 for _, tag := range Values.Tags() {
71 checkDefined(tag, namers)
72 tags[tag] = true
73 }
74 for _, base := range language.Supported.BaseLanguages() {
75 tag, _ := language.All.Compose(base)
76 if !tags[tag] {
77 checkUnsupported(tag, namers)
78 }
79 }
80
81 regions := map[language.Region]bool{}
82 namers = []testcase{
83 {"Regions(en)", Regions(language.English)},
84 {"English.Regions()", English.Regions()},
85 }
86 for _, r := range Values.Regions() {
87 checkDefined(r, namers)
88 regions[r] = true
89 }
90 for _, r := range language.Supported.Regions() {
91 if r = r.Canonicalize(); !regions[r] {
92 checkUnsupported(r, namers)
93 }
94 }
95
96 scripts := map[language.Script]bool{}
97 namers = []testcase{
98 {"Scripts(en)", Scripts(language.English)},
99 {"English.Scripts()", English.Scripts()},
100 }
101 for _, s := range Values.Scripts() {
102 checkDefined(s, namers)
103 scripts[s] = true
104 }
105 for _, s := range language.Supported.Scripts() {
106
107 tag, _ := language.DeprecatedScript.Compose(s)
108 if _, s, _ = tag.Raw(); !scripts[s] {
109 checkUnsupported(s, namers)
110 }
111 }
112 }
113
114
115
116
117 func TestSupported(t *testing.T) {
118 supportedTags := Supported.Tags()
119 if len(supportedTags) != numSupported {
120 t.Errorf("number of supported was %d; want %d", len(supportedTags), numSupported)
121 }
122
123 namerFuncs := []struct {
124 kind string
125 fn func(language.Tag) Namer
126 }{
127 {"Tags", Tags},
128 {"Languages", Languages},
129 {"Regions", Regions},
130 {"Scripts", Scripts},
131 }
132
133
134 tags := make(map[language.Tag]bool)
135 for _, tag := range supportedTags {
136
137 found := false
138 for _, kind := range namerFuncs {
139 if defined(t, kind.kind, kind.fn(tag), tag) {
140 found = true
141 }
142 }
143 if !found {
144 t.Errorf("%s: supported, but no data available", tag)
145 }
146 if tags[tag] {
147 t.Errorf("%s: included in Supported.Tags more than once", tag)
148 }
149 tags[tag] = true
150 }
151
152
153 for _, base := range language.Supported.BaseLanguages() {
154 tag, _ := language.All.Compose(base)
155
156 if _, _, conf := matcher.Match(tag); conf != language.No {
157 continue
158 }
159
160 for _, kind := range namerFuncs {
161 if defined(t, kind.kind, kind.fn(tag), tag) {
162 t.Errorf("%[1]s(%[2]s) returns a Namer, but %[2]s is not in the set of supported Tags.", kind.kind, tag)
163 }
164 }
165 }
166 }
167
168
169
170 func defined(t *testing.T, kind string, n Namer, tag language.Tag) bool {
171 if n == nil {
172 return false
173 }
174 switch kind {
175 case "Tags":
176 for _, t := range Values.Tags() {
177 if n.Name(t) != "" {
178 return true
179 }
180 }
181 case "Languages":
182 for _, t := range Values.BaseLanguages() {
183 if n.Name(t) != "" {
184 return true
185 }
186 }
187 case "Regions":
188 for _, t := range Values.Regions() {
189 if n.Name(t) != "" {
190 return true
191 }
192 }
193 case "Scripts":
194 for _, t := range Values.Scripts() {
195 if n.Name(t) != "" {
196 return true
197 }
198 }
199 }
200 t.Errorf("%s(%s) returns non-nil Namer without content", kind, tag)
201 return false
202 }
203
204 func TestCoverage(t *testing.T) {
205 en := language.English
206 tests := []struct {
207 n Namer
208 x interface{}
209 }{
210 {Languages(en), Values.Tags()},
211 {Scripts(en), Values.Scripts()},
212 {Regions(en), Values.Regions()},
213 }
214 for i, tt := range tests {
215 uniq := make(map[string]interface{})
216
217 v := reflect.ValueOf(tt.x)
218 for j := 0; j < v.Len(); j++ {
219 x := v.Index(j).Interface()
220
221
222 if x.(fmt.Stringer).String() == "az-Arab" {
223 continue
224 }
225 s := tt.n.Name(x)
226 if s == "" {
227 t.Errorf("%d:%d:%s: missing content", i, j, x)
228 } else if uniq[s] != nil {
229 t.Errorf("%d:%d:%s: identical return value %q for %v and %v", i, j, x, s, x, uniq[s])
230 }
231 uniq[s] = x
232 }
233 }
234 }
235
236
237
238
239
240 func TestUpdate(t *testing.T) {
241 tests := []struct {
242 d *Dictionary
243 tag string
244 }{
245 {ModernStandardArabic, "ar-001"},
246 {AmericanEnglish, "en-US"},
247 {EuropeanSpanish, "es-ES"},
248 {BrazilianPortuguese, "pt-BR"},
249 {SimplifiedChinese, "zh-Hans"},
250 }
251
252 for _, tt := range tests {
253 _, i, _ := matcher.Match(language.MustParse(tt.tag))
254 if !reflect.DeepEqual(tt.d.lang, langHeaders[i]) {
255 t.Errorf("%s: lang table update needed", tt.tag)
256 }
257 if !reflect.DeepEqual(tt.d.script, scriptHeaders[i]) {
258 t.Errorf("%s: script table update needed", tt.tag)
259 }
260 if !reflect.DeepEqual(tt.d.region, regionHeaders[i]) {
261 t.Errorf("%s: region table update needed", tt.tag)
262 }
263 }
264 }
265
266 func TestIndex(t *testing.T) {
267 notIn := []string{"aa", "xx", "zz", "aaa", "xxx", "zzz", "Aaaa", "Xxxx", "Zzzz"}
268 tests := []tagIndex{
269 {
270 "",
271 "",
272 "",
273 },
274 {
275 "bb",
276 "",
277 "",
278 },
279 {
280 "",
281 "bbb",
282 "",
283 },
284 {
285 "",
286 "",
287 "Bbbb",
288 },
289 {
290 "bb",
291 "bbb",
292 "Bbbb",
293 },
294 {
295 "bbccddyy",
296 "bbbcccdddyyy",
297 "BbbbCcccDdddYyyy",
298 },
299 }
300 for i, tt := range tests {
301
302 cnt := 0
303 for sz := 2; sz <= 4; sz++ {
304 a := tt[sz-2]
305 for j := 0; j < len(a); j += sz {
306 s := a[j : j+sz]
307 if idx := tt.index(s); idx != cnt {
308 t.Errorf("%d:%s: index was %d; want %d", i, s, idx, cnt)
309 }
310 cnt++
311 }
312 }
313 if n := tt.len(); n != cnt {
314 t.Errorf("%d: len was %d; want %d", i, n, cnt)
315 }
316 for _, x := range notIn {
317 if idx := tt.index(x); idx != -1 {
318 t.Errorf("%d:%s: index was %d; want -1", i, x, idx)
319 }
320 }
321 }
322 }
323
324 func TestTag(t *testing.T) {
325 tests := []struct {
326 dict string
327 tag string
328 name string
329 }{
330
331 {"agq", "sr", "|[language: sr]"},
332 {"nl", "nl", "Nederlands"},
333
334
335
336 {"nl", "nl-BE", "Nederlands (België)"},
337 {"nl", "vls", "West-Vlaams"},
338 {"en", "nl-BE", "Flemish"},
339 {"en", "en", "English"},
340 {"en", "en-GB", "British English"},
341 {"en", "en-US", "American English"},
342 {"ru", "ru", "русский"},
343 {"ru", "ru-RU", "русский (Россия)"},
344 {"ru", "ru-Cyrl", "русский (кириллица)"},
345 {"en", lastLang2zu.String(), "Zulu"},
346 {"en", firstLang2aa.String(), "Afar"},
347 {"en", lastLang3zza.String(), "Zaza"},
348 {"en", firstLang3ace.String(), "Achinese"},
349 {"en", firstTagAr001.String(), "Modern Standard Arabic"},
350 {"en", lastTagZhHant.String(), "Traditional Chinese"},
351 {"en", "aaa", "|Unknown language (aaa)"},
352 {"en", "zzj", "|Unknown language (zzj)"},
353
354 {"en", "aa-Hans", "Afar (Simplified Han)"},
355 {"en", "af-Arab", "Afrikaans (Arabic)"},
356 {"en", "zu-Cyrl", "Zulu (Cyrillic)"},
357 {"en", "aa-GB", "Afar (United Kingdom)"},
358 {"en", "af-NA", "Afrikaans (Namibia)"},
359 {"en", "zu-BR", "Zulu (Brazil)"},
360
361 {"zh", "zh-TW", "中文 (台湾)"},
362 {"zh", "zh-Hant-TW", "繁体中文 (台湾)"},
363 {"zh-Hant", "zh-TW", "中文 (台灣)"},
364 {"zh-Hant", "zh-Hant-TW", "繁體中文 (台灣)"},
365
366
367
368
369 {"sr-Latn", "sr-ME", "srpski (Crna Gora)"},
370 {"sr-Latn", "sr-Latn-ME", "srpskohrvatski (Crna Gora)"},
371
372 {"nl", "en-Cyrl-BE", "Engels (Cyrillisch, België)"},
373 }
374 for _, tt := range tests {
375 t.Run(tt.dict+"/"+tt.tag, func(t *testing.T) {
376 name, fmtName := splitName(tt.name)
377 dict := language.MustParse(tt.dict)
378 tag := language.Raw.MustParse(tt.tag)
379 d := Tags(dict)
380 if n := d.Name(tag); n != name {
381
382
383
384
385
386 t.Errorf("Name(%s) = %q; want %q", tag, n, name)
387 }
388
389 p := message.NewPrinter(dict)
390 if n := p.Sprint(Tag(tag)); n != fmtName {
391 t.Errorf("Tag(%s) = %q; want %q", tag, n, fmtName)
392 }
393 })
394 }
395 }
396
397 func splitName(names string) (name, formatName string) {
398 split := strings.Split(names, "|")
399 name, formatName = split[0], split[0]
400 if len(split) > 1 {
401 formatName = split[1]
402 }
403 return name, formatName
404 }
405
406 func TestLanguage(t *testing.T) {
407 tests := []struct {
408 dict string
409 tag string
410 name string
411 }{
412
413 {"agq", "sr", "|[language: sr]"},
414
415
416
417
418
419 {"nl", "nl", "Nederlands"},
420 {"nl", "vls", "West-Vlaams"},
421 {"nl", "nl-BE", "Nederlands"},
422 {"en", "pt", "Portuguese"},
423 {"en", "pt-PT", "European Portuguese"},
424 {"en", "pt-BR", "Brazilian Portuguese"},
425 {"en", "en", "English"},
426 {"en", "en-GB", "British English"},
427 {"en", "en-US", "American English"},
428 {"en", lastLang2zu.String(), "Zulu"},
429 {"en", firstLang2aa.String(), "Afar"},
430 {"en", lastLang3zza.String(), "Zaza"},
431 {"en", firstLang3ace.String(), "Achinese"},
432 {"en", firstTagAr001.String(), "Modern Standard Arabic"},
433 {"en", lastTagZhHant.String(), "Traditional Chinese"},
434 {"en", "aaa", "|Unknown language (aaa)"},
435 {"en", "zzj", "|Unknown language (zzj)"},
436
437 {"en", "aa-Hans", "Afar"},
438 {"en", "af-Arab", "Afrikaans"},
439 {"en", "zu-Cyrl", "Zulu"},
440 {"en", "aa-GB", "Afar"},
441 {"en", "af-NA", "Afrikaans"},
442 {"en", "zu-BR", "Zulu"},
443 {"agq", "zh-Hant", "|[language: zh-Hant]"},
444 {"en", "sh", "Serbo-Croatian"},
445 {"en", "sr-Latn", "Serbo-Croatian"},
446 {"en", "sr", "Serbian"},
447 {"en", "sr-ME", "Serbian"},
448 {"en", "sr-Latn-ME", "Serbo-Croatian"},
449 }
450 for _, tt := range tests {
451 t.Run(tt.dict+"/"+tt.tag, func(t *testing.T) {
452 name, fmtName := splitName(tt.name)
453 dict := language.MustParse(tt.dict)
454 tag := language.Raw.MustParse(tt.tag)
455 p := message.NewPrinter(dict)
456 d := Languages(dict)
457 if n := d.Name(tag); n != name {
458 t.Errorf("Name(%v) = %q; want %q", tag, n, name)
459 }
460 if n := p.Sprint(Language(tag)); n != fmtName {
461 t.Errorf("Language(%v) = %q; want %q", tag, n, fmtName)
462 }
463 if len(tt.tag) <= 3 {
464 base := language.MustParseBase(tt.tag)
465 if n := d.Name(base); n != name {
466 t.Errorf("Name(%v) = %q; want %q", base, n, name)
467 }
468 if n := p.Sprint(Language(base)); n != fmtName {
469 t.Errorf("Language(%v) = %q; want %q", base, n, fmtName)
470 }
471 }
472 })
473 }
474 }
475
476 func TestScript(t *testing.T) {
477 tests := []struct {
478 dict string
479 scr string
480 name string
481 }{
482 {"nl", "Arab", "Arabisch"},
483 {"en", "Arab", "Arabic"},
484 {"en", "Zzzz", "Unknown Script"},
485 {"zh-Hant", "Hang", "韓文字"},
486 {"zh-Hant-HK", "Hang", "韓文字"},
487 {"zh", "Arab", "阿拉伯文"},
488 {"zh-Hans-HK", "Arab", "阿拉伯文"},
489 {"zh-Hant", "Arab", "阿拉伯文"},
490 {"zh-Hant-HK", "Arab", "阿拉伯文"},
491
492 {"en", "Qaai", "Inherited"},
493 {"en", "sh", "Unknown Script"},
494 {"en", "en", "Unknown Script"},
495
496 {"en", "sh", "Unknown Script"},
497 }
498 for _, tt := range tests {
499 t.Run(tt.dict+"/"+tt.scr, func(t *testing.T) {
500 name, fmtName := splitName(tt.name)
501 dict := language.MustParse(tt.dict)
502 p := message.NewPrinter(dict)
503 d := Scripts(dict)
504 var tag language.Tag
505 if unicode.IsUpper(rune(tt.scr[0])) {
506 x := language.MustParseScript(tt.scr)
507 if n := d.Name(x); n != name {
508 t.Errorf("Name(%v) = %q; want %q", x, n, name)
509 }
510 if n := p.Sprint(Script(x)); n != fmtName {
511 t.Errorf("Script(%v) = %q; want %q", x, n, fmtName)
512 }
513 tag, _ = language.Raw.Compose(x)
514 } else {
515 tag = language.Raw.MustParse(tt.scr)
516 }
517 if n := d.Name(tag); n != name {
518 t.Errorf("Name(%v) = %q; want %q", tag, n, name)
519 }
520 if n := p.Sprint(Script(tag)); n != fmtName {
521 t.Errorf("Script(%v) = %q; want %q", tag, n, fmtName)
522 }
523 })
524 }
525 }
526
527 func TestRegion(t *testing.T) {
528 tests := []struct {
529 dict string
530 reg string
531 name string
532 }{
533 {"nl", "NL", "Nederland"},
534 {"en", "US", "United States"},
535 {"en", "ZZ", "Unknown Region"},
536 {"en-GB", "NL", "Netherlands"},
537
538 {"en", "UK", "United Kingdom"},
539
540 {"en", "pt", "Unknown Region"},
541 {"en", "und", "Unknown Region"},
542
543 {"en", "mo", "Unknown Region"},
544 }
545 for _, tt := range tests {
546 t.Run(tt.dict+"/"+tt.reg, func(t *testing.T) {
547 dict := language.MustParse(tt.dict)
548 p := message.NewPrinter(dict)
549 d := Regions(dict)
550 var tag language.Tag
551 if unicode.IsUpper(rune(tt.reg[0])) {
552
553 x := language.MustParseRegion(tt.reg)
554 if n := d.Name(x); n != tt.name {
555 t.Errorf("Name(%v) = %q; want %q", x, n, tt.name)
556 }
557 if n := p.Sprint(Region(x)); n != tt.name {
558 t.Errorf("Region(%v) = %q; want %q", x, n, tt.name)
559 }
560 tag, _ = language.Raw.Compose(x)
561 } else {
562 tag = language.Raw.MustParse(tt.reg)
563 }
564 if n := d.Name(tag); n != tt.name {
565 t.Errorf("Name(%v) = %q; want %q", tag, n, tt.name)
566 }
567 if n := p.Sprint(Region(tag)); n != tt.name {
568 t.Errorf("Region(%v) = %q; want %q", tag, n, tt.name)
569 }
570 })
571 }
572 }
573
574 func TestSelf(t *testing.T) {
575 tests := []struct {
576 tag string
577 name string
578 }{
579 {"nl", "Nederlands"},
580
581
582
583 {"nl-BE", "Nederlands"},
584 {"en-GB", "British English"},
585 {lastLang2zu.String(), "isiZulu"},
586 {firstLang2aa.String(), ""},
587 {lastLang3zza.String(), ""},
588 {firstLang3ace.String(), ""},
589 {firstTagAr001.String(), "العربية الرسمية الحديثة"},
590 {"ar", "العربية"},
591 {lastTagZhHant.String(), "繁體中文"},
592 {"aaa", ""},
593 {"zzj", ""},
594
595
596 {"aa-Hans", ""},
597 {"af-Arab", ""},
598 {"zu-Cyrl", ""},
599
600 {"af-NA", "Afrikaans"},
601 {"zh", "中文"},
602
603 {"zh-TW", "繁體中文"},
604 {"zh-Hant", "繁體中文"},
605 {"zh-Hans", "简体中文"},
606 {"zh-Hant-TW", "繁體中文"},
607 {"zh-Hans-TW", "简体中文"},
608
609
610
611
612 {"sr", "српски"},
613
614
615
616
617
618
619 {"sr-Latn-ME", "srpskohrvatski"},
620 {"sr-Cyrl-ME", "српски"},
621 {"sr-NL", "српски"},
622
623
624
625 {"kk-CN", ""},
626 }
627 for i, tt := range tests {
628 d := Self
629 if n := d.Name(language.Raw.MustParse(tt.tag)); n != tt.name {
630 t.Errorf("%d:%s: was %q; want %q", i, tt.tag, n, tt.name)
631 }
632 }
633 }
634
635 func TestEquivalence(t *testing.T) {
636 testCases := []struct {
637 desc string
638 namer Namer
639 }{
640 {"Self", Self},
641 {"Tags", Tags(language.Romanian)},
642 {"Languages", Languages(language.Romanian)},
643 {"Scripts", Scripts(language.Romanian)},
644 }
645 for _, tc := range testCases {
646 t.Run(tc.desc, func(t *testing.T) {
647 ro := tc.namer.Name(language.Raw.MustParse("ro-MD"))
648 mo := tc.namer.Name(language.Raw.MustParse("mo"))
649 if ro != mo {
650 t.Errorf("%q != %q", ro, mo)
651 }
652 })
653 }
654 }
655
656 func TestDictionaryLang(t *testing.T) {
657 tests := []struct {
658 d *Dictionary
659 tag string
660 name string
661 }{
662 {English, "en", "English"},
663 {Portuguese, "af", "africâner"},
664 {EuropeanPortuguese, "af", "africanês"},
665 {English, "nl-BE", "Flemish"},
666 }
667 for i, test := range tests {
668 tag := language.MustParse(test.tag)
669 if got := test.d.Tags().Name(tag); got != test.name {
670 t.Errorf("%d:%v: got %s; want %s", i, tag, got, test.name)
671 }
672 if base, _ := language.Compose(tag.Base()); base == tag {
673 if got := test.d.Languages().Name(base); got != test.name {
674 t.Errorf("%d:%v: got %s; want %s", i, tag, got, test.name)
675 }
676 }
677 }
678 }
679
680 func TestDictionaryRegion(t *testing.T) {
681 tests := []struct {
682 d *Dictionary
683 region string
684 name string
685 }{
686 {English, "FR", "France"},
687 {Portuguese, "009", "Oceania"},
688 {EuropeanPortuguese, "009", "Oceânia"},
689 }
690 for i, test := range tests {
691 tag := language.MustParseRegion(test.region)
692 if got := test.d.Regions().Name(tag); got != test.name {
693 t.Errorf("%d:%v: got %s; want %s", i, tag, got, test.name)
694 }
695 }
696 }
697
698 func TestDictionaryScript(t *testing.T) {
699 tests := []struct {
700 d *Dictionary
701 script string
702 name string
703 }{
704 {English, "Cyrl", "Cyrillic"},
705 {EuropeanPortuguese, "Gujr", "guzerate"},
706 }
707 for i, test := range tests {
708 tag := language.MustParseScript(test.script)
709 if got := test.d.Scripts().Name(tag); got != test.name {
710 t.Errorf("%d:%v: got %s; want %s", i, tag, got, test.name)
711 }
712 }
713 }
714
View as plain text