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