github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/text/display/display_test.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package display 6 7 import ( 8 "reflect" 9 "testing" 10 "unicode" 11 12 "golang.org/x/text/language" 13 ) 14 15 // TODO: test that tables are properly dropped by the linker for various use 16 // cases. 17 18 var ( 19 firstLang2aa = language.MustParseBase("aa") 20 lastLang2zu = language.MustParseBase("zu") 21 firstLang3ace = language.MustParseBase("ace") 22 lastLang3zza = language.MustParseBase("zza") 23 firstTagAr001 = language.MustParse("ar-001") 24 lastTagZhHant = language.MustParse("zh-Hant") 25 ) 26 27 func TestSupported(t *testing.T) { 28 supportedTags := Supported.Tags() 29 if len(supportedTags) != numSupported { 30 t.Errorf("number of supported was %d; want %d", len(supportedTags), numSupported) 31 } 32 33 tags := make(map[language.Tag]bool) 34 namers := make(map[Namer]bool) 35 // isNil verifies that the namer is unique and returns whether it is nil. 36 isNil := func(n Namer) bool { 37 if n != nil { 38 if namers[n] { 39 t.Errorf("%s: duplicate namer", n) 40 } 41 namers[n] = true 42 } 43 return n == nil 44 } 45 46 for _, tag := range supportedTags { 47 if isNil(Languages(tag)) && isNil(Regions(tag)) && isNil(Scripts(tag)) { 48 t.Errorf("%s: supported, but no data available", tag) 49 } 50 if tags[tag] { 51 t.Errorf("%s: included in Supported.Tags more than once", tag) 52 } 53 tags[tag] = true 54 } 55 } 56 57 func TestCoverage(t *testing.T) { 58 en := language.English 59 tests := []struct { 60 n Namer 61 x interface{} 62 }{ 63 {Languages(en), Values.Tags()}, 64 {Scripts(en), Values.Scripts()}, 65 {Regions(en), Values.Regions()}, 66 } 67 for i, tt := range tests { 68 uniq := make(map[string]interface{}) 69 70 v := reflect.ValueOf(tt.x) 71 for j := 0; j < v.Len(); j++ { 72 x := v.Index(j).Interface() 73 s := tt.n.Name(x) 74 if s == "" { 75 t.Errorf("%d:%d:%s: missing content", i, j, x) 76 } else if uniq[s] != nil { 77 t.Errorf("%d:%d:%s: identical return value %q for %v and %v", i, j, x, s, x, uniq[s]) 78 } 79 uniq[s] = x 80 } 81 } 82 } 83 84 // TestUpdate tests whether dictionary entries for certain languages need to be 85 // updated. For some languages, some of the headers may be empty or they may be 86 // identical to the parent. This code detects if such entries need to be updated 87 // after a table update. 88 func TestUpdate(t *testing.T) { 89 tests := []struct { 90 d *Dictionary 91 tag string 92 }{ 93 {ModernStandardArabic, "ar-001"}, 94 {AmericanEnglish, "en-US"}, 95 {EuropeanSpanish, "es-ES"}, 96 {BrazilianPortuguese, "pt-BR"}, 97 {SimplifiedChinese, "zh-Hans"}, 98 } 99 100 for _, tt := range tests { 101 _, i, _ := matcher.Match(language.MustParse(tt.tag)) 102 if !reflect.DeepEqual(tt.d.lang, langHeaders[i]) { 103 t.Errorf("%s: lang table update needed", tt.tag) 104 } 105 if !reflect.DeepEqual(tt.d.script, scriptHeaders[i]) { 106 t.Errorf("%s: script table update needed", tt.tag) 107 } 108 if !reflect.DeepEqual(tt.d.region, regionHeaders[i]) { 109 t.Errorf("%s: region table update needed", tt.tag) 110 } 111 } 112 } 113 114 func TestIndex(t *testing.T) { 115 notIn := []string{"aa", "xx", "zz", "aaa", "xxx", "zzz", "Aaaa", "Xxxx", "Zzzz"} 116 tests := []tagIndex{ 117 { 118 "", 119 "", 120 "", 121 }, 122 { 123 "bb", 124 "", 125 "", 126 }, 127 { 128 "", 129 "bbb", 130 "", 131 }, 132 { 133 "", 134 "", 135 "Bbbb", 136 }, 137 { 138 "bb", 139 "bbb", 140 "Bbbb", 141 }, 142 { 143 "bbccddyy", 144 "bbbcccdddyyy", 145 "BbbbCcccDdddYyyy", 146 }, 147 } 148 for i, tt := range tests { 149 // Create the test set from the tagIndex. 150 cnt := 0 151 for sz := 2; sz <= 4; sz++ { 152 a := tt[sz-2] 153 for j := 0; j < len(a); j += sz { 154 s := a[j : j+sz] 155 if idx := tt.index(s); idx != cnt { 156 t.Errorf("%d:%s: index was %d; want %d", i, s, idx, cnt) 157 } 158 cnt++ 159 } 160 } 161 if n := tt.len(); n != cnt { 162 t.Errorf("%d: len was %d; want %d", i, n, cnt) 163 } 164 for _, x := range notIn { 165 if idx := tt.index(x); idx != -1 { 166 t.Errorf("%d:%s: index was %d; want -1", i, x, idx) 167 } 168 } 169 } 170 } 171 172 func TestTag(t *testing.T) { 173 tests := []struct { 174 dict string 175 tag string 176 name string 177 }{ 178 {"nl", "nl", "Nederlands"}, 179 {"nl", "nl-BE", "Vlaams"}, 180 {"en", "en", "English"}, 181 {"en", "en-GB", "British English"}, 182 {"en", "en-US", "American English"}, // American English in CLDR 24+ 183 {"ru", "ru", "русский"}, 184 {"ru", "ru-RU", "русский (Россия)"}, 185 // TODO: Script capitalization changed in CLDR 26, but the change seems 186 // aribitrary as for most scripts it did not. 187 {"ru", "ru-Cyrl", "русский (Кириллица)"}, 188 {"en", lastLang2zu.String(), "Zulu"}, 189 {"en", firstLang2aa.String(), "Afar"}, 190 {"en", lastLang3zza.String(), "Zaza"}, 191 {"en", firstLang3ace.String(), "Achinese"}, 192 {"en", firstTagAr001.String(), "Modern Standard Arabic"}, 193 {"en", lastTagZhHant.String(), "Traditional Chinese"}, 194 {"en", "aaa", ""}, 195 {"en", "zzj", ""}, 196 // If full tag doesn't match, try without script or retion. 197 {"en", "aa-Hans", "Afar (Simplified Han)"}, 198 {"en", "af-Arab", "Afrikaans (Arabic)"}, 199 {"en", "zu-Cyrl", "Zulu (Cyrillic)"}, 200 {"en", "aa-GB", "Afar (United Kingdom)"}, 201 {"en", "af-NA", "Afrikaans (Namibia)"}, 202 {"en", "zu-BR", "Zulu (Brazil)"}, 203 // Correct inheritance and language selection. 204 {"zh", "zh-TW", "中文 (台湾)"}, 205 {"zh", "zh-Hant-TW", "繁体中文 (台湾)"}, 206 {"zh-Hant", "zh-TW", "中文 (台灣)"}, 207 {"zh-Hant", "zh-Hant-TW", "繁體中文 (台灣)"}, 208 // Some rather arbitrary interpretations for Serbian. This is arguably 209 // correct and consistent with the way zh-[Hant-]TW is handled. It will 210 // also give results more in line with the expectations if users 211 // explicitly use "sh". 212 {"sr-Latn", "sr-ME", "Srpski (Crna Gora)"}, 213 {"sr-Latn", "sr-Latn-ME", "Srpskohrvatski (Crna Gora)"}, 214 // Double script and region 215 {"nl", "en-Cyrl-BE", "Engels (Cyrillisch, België)"}, 216 // Canonical equivalents. 217 {"ro", "ro-MD", "moldovenească"}, 218 {"ro", "mo", "moldovenească"}, 219 } 220 for i, tt := range tests { 221 d := Tags(language.MustParse(tt.dict)) 222 if n := d.Name(language.Raw.MustParse(tt.tag)); n != tt.name { 223 // Change back to Errorf when CLDR ticker 224 // http://unicode.org/cldr/trac/ticket/8051 is resolved. 225 t.Skipf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.tag, n, tt.name) 226 } 227 } 228 } 229 230 func TestLanguage(t *testing.T) { 231 tests := []struct { 232 dict string 233 tag string 234 name string 235 }{ 236 {"nl", "nl", "Nederlands"}, 237 {"nl", "nl-BE", "Vlaams"}, 238 {"en", "pt", "Portuguese"}, 239 {"en", "pt-PT", "European Portuguese"}, 240 {"en", "pt-BR", "Brazilian Portuguese"}, 241 {"en", "en", "English"}, 242 {"en", "en-GB", "British English"}, 243 {"en", "en-US", "American English"}, // American English in CLDR 24+ 244 {"en", lastLang2zu.String(), "Zulu"}, 245 {"en", firstLang2aa.String(), "Afar"}, 246 {"en", lastLang3zza.String(), "Zaza"}, 247 {"en", firstLang3ace.String(), "Achinese"}, 248 {"en", firstTagAr001.String(), "Modern Standard Arabic"}, 249 {"en", lastTagZhHant.String(), "Traditional Chinese"}, 250 {"en", "aaa", ""}, 251 {"en", "zzj", ""}, 252 // If full tag doesn't match, try without script or region. 253 {"en", "aa-Hans", "Afar"}, 254 {"en", "af-Arab", "Afrikaans"}, 255 {"en", "zu-Cyrl", "Zulu"}, 256 {"en", "aa-GB", "Afar"}, 257 {"en", "af-NA", "Afrikaans"}, 258 {"en", "zu-BR", "Zulu"}, 259 {"agq", "zh-Hant", ""}, 260 // Canonical equivalents. 261 {"ro", "ro-MD", "moldovenească"}, 262 {"ro", "mo", "moldovenească"}, 263 {"en", "sh", "Serbo-Croatian"}, 264 {"en", "sr-Latn", "Serbo-Croatian"}, 265 {"en", "sr", "Serbian"}, 266 {"en", "sr-ME", "Serbian"}, 267 {"en", "sr-Latn-ME", "Serbo-Croatian"}, // See comments in TestTag. 268 } 269 for i, tt := range tests { 270 d := Languages(language.Raw.MustParse(tt.dict)) 271 if n := d.Name(language.Raw.MustParse(tt.tag)); n != tt.name { 272 t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.tag, n, tt.name) 273 } 274 if len(tt.tag) <= 3 { 275 if n := d.Name(language.MustParseBase(tt.tag)); n != tt.name { 276 t.Errorf("%d:%s:base(%s): was %q; want %q", i, tt.dict, tt.tag, n, tt.name) 277 } 278 } 279 } 280 } 281 282 func TestScript(t *testing.T) { 283 tests := []struct { 284 dict string 285 scr string 286 name string 287 }{ 288 {"nl", "Arab", "Arabisch"}, 289 {"en", "Arab", "Arabic"}, 290 {"en", "Zzzz", "Unknown Script"}, 291 {"zh-Hant", "Hang", "韓文字"}, 292 {"zh-Hant-HK", "Hang", "韓文字母"}, 293 {"zh", "Arab", "阿拉伯文"}, 294 {"zh-Hans-HK", "Arab", "阿拉伯文"}, // same as zh 295 {"zh-Hant", "Arab", "阿拉伯文"}, 296 {"zh-Hant-HK", "Arab", "阿拉伯文"}, // same as zh 297 // Canonicalized form 298 {"en", "Qaai", "Inherited"}, // deprecated script, now is Zinh 299 {"en", "sh", "Unknown Script"}, // sh canonicalizes to sr-Latn 300 {"en", "en", "Unknown Script"}, 301 // Don't introduce scripts with canonicalization. 302 {"en", "sh", "Unknown Script"}, // sh canonicalizes to sr-Latn 303 } 304 for i, tt := range tests { 305 d := Scripts(language.MustParse(tt.dict)) 306 var x interface{} 307 if unicode.IsUpper(rune(tt.scr[0])) { 308 x = language.MustParseScript(tt.scr) 309 tag, _ := language.Raw.Compose(x) 310 if n := d.Name(tag); n != tt.name { 311 t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.scr, n, tt.name) 312 } 313 } else { 314 x = language.Raw.MustParse(tt.scr) 315 } 316 if n := d.Name(x); n != tt.name { 317 t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.scr, n, tt.name) 318 } 319 } 320 } 321 322 func TestRegion(t *testing.T) { 323 tests := []struct { 324 dict string 325 reg string 326 name string 327 }{ 328 {"nl", "NL", "Nederland"}, 329 {"en", "US", "United States"}, 330 {"en", "ZZ", "Unknown Region"}, 331 {"en", "UM", "U.S. Outlying Islands"}, 332 {"en-GB", "UM", "U.S. Outlying Islands"}, 333 {"en-GB", "NL", "Netherlands"}, 334 // Canonical equivalents 335 {"en", "UK", "United Kingdom"}, 336 // No region 337 {"en", "pt", "Unknown Region"}, 338 {"en", "und", "Unknown Region"}, 339 // Don't introduce regions with canonicalization. 340 {"en", "mo", "Unknown Region"}, 341 } 342 for i, tt := range tests { 343 d := Regions(language.MustParse(tt.dict)) 344 var x interface{} 345 if unicode.IsUpper(rune(tt.reg[0])) { 346 // Region 347 x = language.MustParseRegion(tt.reg) 348 tag, _ := language.Raw.Compose(x) 349 if n := d.Name(tag); n != tt.name { 350 t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.reg, n, tt.name) 351 } 352 } else { 353 // Tag 354 x = language.Raw.MustParse(tt.reg) 355 } 356 if n := d.Name(x); n != tt.name { 357 t.Errorf("%d:%s:%s: was %q; want %q", i, tt.dict, tt.reg, n, tt.name) 358 } 359 } 360 } 361 362 func TestSelf(t *testing.T) { 363 tests := []struct { 364 tag string 365 name string 366 }{ 367 {"nl", "Nederlands"}, 368 {"nl-BE", "Vlaams"}, 369 {"en-GB", "British English"}, 370 {lastLang2zu.String(), "isiZulu"}, 371 {firstLang2aa.String(), ""}, // not defined 372 {lastLang3zza.String(), ""}, // not defined 373 {firstLang3ace.String(), ""}, // not defined 374 {firstTagAr001.String(), "العربية الرسمية الحديثة"}, 375 {"ar", "العربية"}, 376 {lastTagZhHant.String(), "繁體中文"}, 377 {"aaa", ""}, 378 {"zzj", ""}, 379 // Drop entries that are not in the requested script, even if there is 380 // an entry for the language. 381 {"aa-Hans", ""}, 382 {"af-Arab", ""}, 383 {"zu-Cyrl", ""}, 384 // Append the country name in the language of the matching language. 385 {"af-NA", "Afrikaans"}, 386 {"zh", "中文"}, 387 // zh-TW should match zh-Hant instead of zh! 388 {"zh-TW", "繁體中文"}, 389 {"zh-Hant", "繁體中文"}, 390 {"zh-Hans", "简体中文"}, 391 {"zh-Hant-TW", "繁體中文"}, 392 {"zh-Hans-TW", "简体中文"}, 393 // Take the entry for sr which has the matching script. 394 // TODO: Capitalization changed as of CLDR 26, but change seems 395 // arbitrary. Revisit capitalization with revision 27. See 396 // http://unicode.org/cldr/trac/ticket/8051. 397 {"sr", "српски"}, 398 // TODO: sr-ME should show up as Serbian or Montenegrin, not Serbo- 399 // Croatian. This is an artifact of the current algorithm, which is the 400 // way it is to have the preferred behavior for other languages such as 401 // Chinese. We can hardwire this case in the table generator or package 402 // code, but we first check if CLDR can be updated. 403 // {"sr-ME", "Srpski"}, // Is Srpskohrvatski 404 {"sr-Latn-ME", "Srpskohrvatski"}, 405 {"sr-Cyrl-ME", "српски"}, 406 {"sr-NL", "српски"}, 407 // Canonical equivalents. 408 {"ro-MD", "moldovenească"}, 409 {"mo", "moldovenească"}, 410 // NOTE: kk is defined, but in Cyrillic script. For China, Arab is the 411 // dominant script. We do not have data for kk-Arab and we chose to not 412 // fall back in such cases. 413 {"kk-CN", ""}, 414 } 415 for i, tt := range tests { 416 d := Self 417 if n := d.Name(language.Raw.MustParse(tt.tag)); n != tt.name { 418 t.Errorf("%d:%s: was %q; want %q", i, tt.tag, n, tt.name) 419 } 420 } 421 }