language_test.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // Copyright 2013 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. package compact
  5. import (
  6. "reflect"
  7. "testing"
  8. "golang.org/x/text/internal/language"
  9. )
  10. func mustParse(s string) Tag {
  11. t, err := language.Parse(s)
  12. if err != nil {
  13. panic(err)
  14. }
  15. return Make(t)
  16. }
  17. func TestTagSize(t *testing.T) {
  18. id := Tag{}
  19. typ := reflect.TypeOf(id)
  20. if typ.Size() > 24 {
  21. t.Errorf("size of Tag was %d; want 24", typ.Size())
  22. }
  23. }
  24. func TestNoPublic(t *testing.T) {
  25. noExportedField(t, reflect.TypeOf(Tag{}))
  26. }
  27. func noExportedField(t *testing.T, typ reflect.Type) {
  28. for i := 0; i < typ.NumField(); i++ {
  29. f := typ.Field(i)
  30. if f.PkgPath == "" {
  31. t.Errorf("Tag may not have exported fields, but has field %q", f.Name)
  32. }
  33. if f.Anonymous {
  34. noExportedField(t, f.Type)
  35. }
  36. }
  37. }
  38. func TestEquality(t *testing.T) {
  39. for i, tt := range parseTests() {
  40. s := tt.in
  41. tag := mk(s)
  42. t1 := mustParse(tag.Tag().String())
  43. if tag != t1 {
  44. t.Errorf("%d:%s: equality test 1 failed\n got: %#v\nwant: %#v)", i, s, t1, tag)
  45. }
  46. }
  47. }
  48. type compactTest struct {
  49. tag string
  50. index ID
  51. ok bool
  52. }
  53. var compactTests = []compactTest{
  54. // TODO: these values will change with each CLDR update. This issue
  55. // will be solved if we decide to fix the indexes.
  56. {"und", undIndex, true},
  57. {"ca-ES-valencia", caESvalenciaIndex, true},
  58. {"ca-ES-valencia-u-va-posix", caESvalenciaIndex, false},
  59. {"ca-ES-valencia-u-co-phonebk", caESvalenciaIndex, false},
  60. {"ca-ES-valencia-u-co-phonebk-va-posix", caESvalenciaIndex, false},
  61. {"x-klingon", 0, false},
  62. {"en-US", enUSIndex, true},
  63. {"en-US-u-va-posix", enUSuvaposixIndex, true},
  64. {"en", enIndex, true},
  65. {"en-u-co-phonebk", enIndex, false},
  66. {"en-001", en001Index, true},
  67. {"zh-Hant-HK", zhHantHKIndex, true},
  68. {"zh-HK", zhHantHKIndex, false}, // maximized to zh-Hant-HK
  69. {"nl-Beng", 0, false}, // parent skips script
  70. {"nl-NO", nlIndex, false}, // region is ignored
  71. {"nl-Latn-NO", nlIndex, false},
  72. {"nl-Latn-NO-u-co-phonebk", nlIndex, false},
  73. {"nl-Latn-NO-valencia", nlIndex, false},
  74. {"nl-Latn-NO-oxendict", nlIndex, false},
  75. {"sh", shIndex, true}, // From plural rules.
  76. }
  77. func TestLanguageID(t *testing.T) {
  78. tests := append(compactTests, []compactTest{
  79. {"en-GB", enGBIndex, true},
  80. {"en-GB-u-rg-uszzzz", enGBIndex, true},
  81. {"en-GB-u-rg-USZZZZ", enGBIndex, true},
  82. {"en-GB-u-rg-uszzzz-va-posix", enGBIndex, false},
  83. {"en-GB-u-co-phonebk-rg-uszzzz", enGBIndex, false},
  84. // Invalid region specifications are ignored.
  85. {"en-GB-u-rg-usz-va-posix", enGBIndex, false},
  86. {"en-GB-u-co-phonebk-rg-usz", enGBIndex, false},
  87. }...)
  88. for _, tt := range tests {
  89. x, ok := LanguageID(mustParse(tt.tag))
  90. if ID(x) != tt.index || ok != tt.ok {
  91. t.Errorf("%s: got %d, %v; want %d %v", tt.tag, x, ok, tt.index, tt.ok)
  92. }
  93. }
  94. }
  95. func TestRegionalID(t *testing.T) {
  96. tests := append(compactTests, []compactTest{
  97. {"en-GB", enGBIndex, true},
  98. {"en-GB-u-rg-uszzzz", enUSIndex, true},
  99. {"en-GB-u-rg-USZZZZ", enUSIndex, true},
  100. // TODO: use different exact values for language and regional tag?
  101. {"en-GB-u-rg-uszzzz-va-posix", enUSuvaposixIndex, false},
  102. {"en-GB-u-co-phonebk-rg-uszzzz-va-posix", enUSuvaposixIndex, false},
  103. {"en-GB-u-co-phonebk-rg-uszzzz", enUSIndex, false},
  104. // Invalid region specifications are ignored.
  105. {"en-GB-u-rg-usz-va-posix", enGBIndex, false},
  106. {"en-GB-u-co-phonebk-rg-usz", enGBIndex, false},
  107. }...)
  108. for _, tt := range tests {
  109. x, ok := RegionalID(mustParse(tt.tag))
  110. if ID(x) != tt.index || ok != tt.ok {
  111. t.Errorf("%s: got %d, %v; want %d %v", tt.tag, x, ok, tt.index, tt.ok)
  112. }
  113. }
  114. }
  115. func TestParent(t *testing.T) {
  116. tests := []struct{ in, out string }{
  117. // Strip variants and extensions first
  118. {"de-u-co-phonebk", "de"},
  119. {"de-1994", "de"},
  120. {"de-Latn-1994", "de"}, // remove superfluous script.
  121. // Ensure the canonical Tag for an entry is in the chain for base-script
  122. // pairs.
  123. {"zh-Hans", "zh"},
  124. // Skip the script if it is the maximized version. CLDR files for the
  125. // skipped tag are always empty.
  126. {"zh-Hans-TW", "zh"},
  127. {"zh-Hans-CN", "zh"},
  128. // Insert the script if the maximized script is not the same as the
  129. // maximized script of the base language.
  130. {"zh-TW", "zh-Hant"},
  131. {"zh-HK", "zh-Hant"},
  132. {"zh-Hant-TW", "zh-Hant"},
  133. {"zh-Hant-HK", "zh-Hant"},
  134. // Non-default script skips to und.
  135. // CLDR
  136. {"az-Cyrl", "und"},
  137. {"bs-Cyrl", "und"},
  138. {"en-Dsrt", "und"},
  139. {"ha-Arab", "und"},
  140. {"mn-Mong", "und"},
  141. {"pa-Arab", "und"},
  142. {"shi-Latn", "und"},
  143. {"sr-Latn", "und"},
  144. {"uz-Arab", "und"},
  145. {"uz-Cyrl", "und"},
  146. {"vai-Latn", "und"},
  147. {"zh-Hant", "und"},
  148. // extra
  149. {"nl-Cyrl", "und"},
  150. // World english inherits from en-001.
  151. {"en-150", "en-001"},
  152. {"en-AU", "en-001"},
  153. {"en-BE", "en-001"},
  154. {"en-GG", "en-001"},
  155. {"en-GI", "en-001"},
  156. {"en-HK", "en-001"},
  157. {"en-IE", "en-001"},
  158. {"en-IM", "en-001"},
  159. {"en-IN", "en-001"},
  160. {"en-JE", "en-001"},
  161. {"en-MT", "en-001"},
  162. {"en-NZ", "en-001"},
  163. {"en-PK", "en-001"},
  164. {"en-SG", "en-001"},
  165. // Spanish in Latin-American countries have es-419 as parent.
  166. {"es-AR", "es-419"},
  167. {"es-BO", "es-419"},
  168. {"es-CL", "es-419"},
  169. {"es-CO", "es-419"},
  170. {"es-CR", "es-419"},
  171. {"es-CU", "es-419"},
  172. {"es-DO", "es-419"},
  173. {"es-EC", "es-419"},
  174. {"es-GT", "es-419"},
  175. {"es-HN", "es-419"},
  176. {"es-MX", "es-419"},
  177. {"es-NI", "es-419"},
  178. {"es-PA", "es-419"},
  179. {"es-PE", "es-419"},
  180. {"es-PR", "es-419"},
  181. {"es-PY", "es-419"},
  182. {"es-SV", "es-419"},
  183. {"es-US", "es-419"},
  184. {"es-UY", "es-419"},
  185. {"es-VE", "es-419"},
  186. // exceptions (according to CLDR)
  187. {"es-CW", "es"},
  188. // Inherit from pt-PT, instead of pt for these countries.
  189. {"pt-AO", "pt-PT"},
  190. {"pt-CV", "pt-PT"},
  191. {"pt-GW", "pt-PT"},
  192. {"pt-MO", "pt-PT"},
  193. {"pt-MZ", "pt-PT"},
  194. {"pt-ST", "pt-PT"},
  195. {"pt-TL", "pt-PT"},
  196. {"en-GB-u-co-phonebk-rg-uszzzz", "en-GB"},
  197. {"en-GB-u-rg-uszzzz", "en-GB"},
  198. {"en-US-u-va-posix", "en-US"},
  199. // Difference between language and regional tag.
  200. {"ca-ES-valencia", "ca-ES"},
  201. {"ca-ES-valencia-u-rg-ptzzzz", "ca-ES"}, // t.full != nil
  202. {"en-US-u-va-variant", "en-US"},
  203. {"en-u-va-variant", "en"}, // t.full != nil
  204. {"en-u-rg-gbzzzz", "en"},
  205. {"en-US-u-rg-gbzzzz", "en-US"},
  206. {"nl-US-u-rg-gbzzzz", "nl-US"}, // t.full != nil
  207. }
  208. for _, tt := range tests {
  209. tag := mustParse(tt.in)
  210. if p := mustParse(tt.out); p != tag.Parent() {
  211. t.Errorf("%s: was %v; want %v", tt.in, tag.Parent(), p)
  212. }
  213. }
  214. }