github.com/go-xe2/third@v1.0.3/golang.org/x/text/internal/cldrtree/cldrtree_test.go (about) 1 // Copyright 2017 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 cldrtree 6 7 import ( 8 "bytes" 9 "flag" 10 "io/ioutil" 11 "log" 12 "math/rand" 13 "path/filepath" 14 "reflect" 15 "regexp" 16 "strconv" 17 "strings" 18 "testing" 19 20 "github.com/go-xe2/third/golang.org/x/text/internal/gen" 21 "github.com/go-xe2/third/golang.org/x/text/language" 22 "github.com/go-xe2/third/golang.org/x/text/unicode/cldr" 23 ) 24 25 var genOutput = flag.Bool("gen", false, "generate output files") 26 27 func TestAliasRegexp(t *testing.T) { 28 testCases := []struct { 29 alias string 30 want []string 31 }{{ 32 alias: "miscPatterns[@numberSystem='latn']", 33 want: []string{ 34 "miscPatterns[@numberSystem='latn']", 35 "miscPatterns", 36 "[@numberSystem='latn']", 37 "numberSystem", 38 "latn", 39 }, 40 }, { 41 alias: `calendar[@type='greg-foo']/days/`, 42 want: []string{ 43 "calendar[@type='greg-foo']", 44 "calendar", 45 "[@type='greg-foo']", 46 "type", 47 "greg-foo", 48 }, 49 }, { 50 alias: "eraAbbr", 51 want: []string{ 52 "eraAbbr", 53 "eraAbbr", 54 "", 55 "", 56 "", 57 }, 58 }, { 59 // match must be anchored at beginning. 60 alias: `../calendar[@type='gregorian']/days/`, 61 }} 62 for _, tc := range testCases { 63 t.Run(tc.alias, func(t *testing.T) { 64 got := aliasRe.FindStringSubmatch(tc.alias) 65 if !reflect.DeepEqual(got, tc.want) { 66 t.Errorf("got %v; want %v", got, tc.want) 67 } 68 }) 69 } 70 } 71 72 func TestBuild(t *testing.T) { 73 tree1, _ := loadTestdata(t, "test1") 74 tree2, _ := loadTestdata(t, "test2") 75 76 // Constants for second test test 77 const ( 78 calendar = iota 79 field 80 ) 81 const ( 82 month = iota 83 era 84 filler 85 cyclicNameSet 86 ) 87 const ( 88 abbreviated = iota 89 narrow 90 wide 91 ) 92 93 testCases := []struct { 94 desc string 95 tree *Tree 96 locale string 97 path []uint16 98 isFeature bool 99 result string 100 }{{ 101 desc: "und/chinese month format wide m1", 102 tree: tree1, 103 locale: "und", 104 path: path(calendar, 0, month, 0, wide, 1), 105 result: "cM01", 106 }, { 107 desc: "und/chinese month format wide m12", 108 tree: tree1, 109 locale: "und", 110 path: path(calendar, 0, month, 0, wide, 12), 111 result: "cM12", 112 }, { 113 desc: "und/non-existing value", 114 tree: tree1, 115 locale: "und", 116 path: path(calendar, 0, month, 0, wide, 13), 117 result: "", 118 }, { 119 desc: "und/dangi:chinese month format wide", 120 tree: tree1, 121 locale: "und", 122 path: path(calendar, 1, month, 0, wide, 1), 123 result: "cM01", 124 }, { 125 desc: "und/chinese month format abbreviated:wide", 126 tree: tree1, 127 locale: "und", 128 path: path(calendar, 0, month, 0, abbreviated, 1), 129 result: "cM01", 130 }, { 131 desc: "und/chinese month format narrow:wide", 132 tree: tree1, 133 locale: "und", 134 path: path(calendar, 0, month, 0, narrow, 1), 135 result: "cM01", 136 }, { 137 desc: "und/gregorian month format wide", 138 tree: tree1, 139 locale: "und", 140 path: path(calendar, 2, month, 0, wide, 2), 141 result: "gM02", 142 }, { 143 desc: "und/gregorian month format:stand-alone narrow", 144 tree: tree1, 145 locale: "und", 146 path: path(calendar, 2, month, 0, narrow, 1), 147 result: "1", 148 }, { 149 desc: "und/gregorian month stand-alone:format abbreviated", 150 tree: tree1, 151 locale: "und", 152 path: path(calendar, 2, month, 1, abbreviated, 1), 153 result: "gM01", 154 }, { 155 desc: "und/gregorian month stand-alone:format wide ", 156 tree: tree1, 157 locale: "und", 158 path: path(calendar, 2, month, 1, abbreviated, 1), 159 result: "gM01", 160 }, { 161 desc: "und/dangi:chinese month format narrow:wide ", 162 tree: tree1, 163 locale: "und", 164 path: path(calendar, 1, month, 0, narrow, 4), 165 result: "cM04", 166 }, { 167 desc: "und/field era displayname 0", 168 tree: tree2, 169 locale: "und", 170 path: path(field, 0, 0, 0), 171 result: "Era", 172 }, { 173 desc: "en/field era displayname 0", 174 tree: tree2, 175 locale: "en", 176 path: path(field, 0, 0, 0), 177 result: "era", 178 }, { 179 desc: "und/calendar hebrew format wide 7-leap", 180 tree: tree2, 181 locale: "und", 182 path: path(calendar, 7, month, 0, wide, 0), 183 result: "Adar II", 184 }, { 185 desc: "en-GB:en-001:en:und/calendar hebrew format wide 7-leap", 186 tree: tree2, 187 locale: "en-GB", 188 path: path(calendar, 7, month, 0, wide, 0), 189 result: "Adar II", 190 }, { 191 desc: "und/buddhist month format wide 11", 192 tree: tree2, 193 locale: "und", 194 path: path(calendar, 0, month, 0, wide, 12), 195 result: "genWideM12", 196 }, { 197 desc: "en-GB/gregorian month stand-alone narrow 2", 198 tree: tree2, 199 locale: "en-GB", 200 path: path(calendar, 6, month, 1, narrow, 3), 201 result: "gbNarrowM3", 202 }, { 203 desc: "en-GB/gregorian month format narrow 3/missing in en-GB", 204 tree: tree2, 205 locale: "en-GB", 206 path: path(calendar, 6, month, 0, narrow, 4), 207 result: "enNarrowM4", 208 }, { 209 desc: "en-GB/gregorian month format narrow 3/missing in en and en-GB", 210 tree: tree2, 211 locale: "en-GB", 212 path: path(calendar, 6, month, 0, narrow, 7), 213 result: "gregNarrowM7", 214 }, { 215 desc: "en-GB/gregorian month format narrow 3/missing in en and en-GB", 216 tree: tree2, 217 locale: "en-GB", 218 path: path(calendar, 6, month, 0, narrow, 7), 219 result: "gregNarrowM7", 220 }, { 221 desc: "en-GB/gregorian era narrow", 222 tree: tree2, 223 locale: "en-GB", 224 path: path(calendar, 6, era, abbreviated, 0, 1), 225 isFeature: true, 226 result: "AD", 227 }, { 228 desc: "en-GB/gregorian era narrow", 229 tree: tree2, 230 locale: "en-GB", 231 path: path(calendar, 6, era, narrow, 0, 0), 232 isFeature: true, 233 result: "BC", 234 }, { 235 desc: "en-GB/gregorian era narrow", 236 tree: tree2, 237 locale: "en-GB", 238 path: path(calendar, 6, era, wide, 1, 0), 239 isFeature: true, 240 result: "Before Common Era", 241 }, { 242 desc: "en-GB/dangi:chinese cyclicName, months, format, narrow:abbreviated 2", 243 tree: tree2, 244 locale: "en-GB", 245 path: path(calendar, 1, cyclicNameSet, 3, 0, 1, 2), 246 isFeature: true, 247 result: "year2", 248 }, { 249 desc: "en-GB/field era-narrow ", 250 tree: tree2, 251 locale: "en-GB", 252 path: path(field, 2, 0, 0), 253 result: "era", 254 }, { 255 desc: "en-GB/field month-narrow relativeTime future one", 256 tree: tree2, 257 locale: "en-GB", 258 path: path(field, 5, 2, 0, 1), 259 isFeature: true, 260 result: "001NarrowFutMOne", 261 }, { 262 // Don't fall back to the one of "en". 263 desc: "en-GB/field month-short relativeTime past one:other", 264 tree: tree2, 265 locale: "en-GB", 266 path: path(field, 4, 2, 1, 1), 267 isFeature: true, 268 result: "001ShortPastMOther", 269 }, { 270 desc: "en-GB/field month relativeTime future two:other", 271 tree: tree2, 272 locale: "en-GB", 273 path: path(field, 3, 2, 0, 2), 274 isFeature: true, 275 result: "enFutMOther", 276 }} 277 278 for _, tc := range testCases { 279 t.Run(tc.desc, func(t *testing.T) { 280 tag, _ := language.CompactIndex(language.MustParse(tc.locale)) 281 s := tc.tree.lookup(tag, tc.isFeature, tc.path...) 282 if s != tc.result { 283 t.Errorf("got %q; want %q", s, tc.result) 284 } 285 }) 286 } 287 } 288 289 func path(e ...uint16) []uint16 { return e } 290 291 func TestGen(t *testing.T) { 292 testCases := []string{"test1", "test2"} 293 for _, tc := range testCases { 294 t.Run(tc, func(t *testing.T) { 295 _, got := loadTestdata(t, tc) 296 297 // Remove sizes that may vary per architecture. 298 re := regexp.MustCompile("// Size: [0-9]*") 299 got = re.ReplaceAllLiteral(got, []byte("// Size: xxxx")) 300 re = regexp.MustCompile("// Total table size [0-9]*") 301 got = re.ReplaceAllLiteral(got, []byte("// Total table size: xxxx")) 302 303 file := filepath.Join("testdata", tc, "output.go") 304 if *genOutput { 305 ioutil.WriteFile(file, got, 0700) 306 t.SkipNow() 307 } 308 309 b, err := ioutil.ReadFile(file) 310 if err != nil { 311 t.Fatalf("failed to open file: %v", err) 312 } 313 if want := string(b); string(got) != want { 314 t.Log(string(got)) 315 t.Errorf("files differ") 316 } 317 }) 318 } 319 } 320 321 func loadTestdata(t *testing.T, test string) (tree *Tree, file []byte) { 322 b := New("test") 323 324 var d cldr.Decoder 325 326 data, err := d.DecodePath(filepath.Join("testdata", test)) 327 if err != nil { 328 t.Fatalf("error decoding testdata: %v", err) 329 } 330 331 context := Enum("context") 332 widthMap := func(s string) string { 333 // Align era with width values. 334 if r, ok := map[string]string{ 335 "eraAbbr": "abbreviated", 336 "eraNarrow": "narrow", 337 "eraNames": "wide", 338 }[s]; ok { 339 s = r 340 } 341 return "w" + strings.Title(s) 342 } 343 width := EnumFunc("width", widthMap, "abbreviated", "narrow", "wide") 344 month := Enum("month", "leap7") 345 relative := EnumFunc("relative", func(s string) string { 346 x, err := strconv.ParseInt(s, 10, 8) 347 if err != nil { 348 log.Fatal("Invalid number:", err) 349 } 350 return []string{ 351 "before1", 352 "current", 353 "after1", 354 }[x+1] 355 }) 356 cycleType := EnumFunc("cycleType", func(s string) string { 357 return "cyc" + strings.Title(s) 358 }) 359 r := rand.New(rand.NewSource(0)) 360 361 for _, loc := range data.Locales() { 362 ldml := data.RawLDML(loc) 363 x := b.Locale(language.Make(loc)) 364 365 if x := x.Index(ldml.Dates.Calendars); x != nil { 366 for _, cal := range ldml.Dates.Calendars.Calendar { 367 x := x.IndexFromType(cal) 368 if x := x.Index(cal.Months); x != nil { 369 for _, mc := range cal.Months.MonthContext { 370 x := x.IndexFromType(mc, context) 371 for _, mw := range mc.MonthWidth { 372 x := x.IndexFromType(mw, width) 373 for _, m := range mw.Month { 374 x.SetValue(m.Yeartype+m.Type, m, month) 375 } 376 } 377 } 378 } 379 if x := x.Index(cal.CyclicNameSets); x != nil { 380 for _, cns := range cal.CyclicNameSets.CyclicNameSet { 381 x := x.IndexFromType(cns, cycleType) 382 for _, cc := range cns.CyclicNameContext { 383 x := x.IndexFromType(cc, context) 384 for _, cw := range cc.CyclicNameWidth { 385 x := x.IndexFromType(cw, width) 386 for _, c := range cw.CyclicName { 387 x.SetValue(c.Type, c) 388 } 389 } 390 } 391 } 392 } 393 if x := x.Index(cal.Eras); x != nil { 394 opts := []Option{width, SharedType()} 395 if x := x.Index(cal.Eras.EraNames, opts...); x != nil { 396 for _, e := range cal.Eras.EraNames.Era { 397 x.IndexFromAlt(e).SetValue(e.Type, e) 398 } 399 } 400 if x := x.Index(cal.Eras.EraAbbr, opts...); x != nil { 401 for _, e := range cal.Eras.EraAbbr.Era { 402 x.IndexFromAlt(e).SetValue(e.Type, e) 403 } 404 } 405 if x := x.Index(cal.Eras.EraNarrow, opts...); x != nil { 406 for _, e := range cal.Eras.EraNarrow.Era { 407 x.IndexFromAlt(e).SetValue(e.Type, e) 408 } 409 } 410 } 411 { 412 // Ensure having more than 2 buckets. 413 f := x.IndexWithName("filler") 414 b := make([]byte, maxStrlen) 415 opt := &options{parent: x} 416 r.Read(b) 417 f.setValue("0", string(b), opt) 418 } 419 } 420 } 421 if x := x.Index(ldml.Dates.Fields); x != nil { 422 for _, f := range ldml.Dates.Fields.Field { 423 x := x.IndexFromType(f) 424 for _, d := range f.DisplayName { 425 x.Index(d).SetValue("", d) 426 } 427 for _, r := range f.Relative { 428 x.Index(r).SetValue(r.Type, r, relative) 429 } 430 for _, rt := range f.RelativeTime { 431 x := x.Index(rt).IndexFromType(rt) 432 for _, p := range rt.RelativeTimePattern { 433 x.SetValue(p.Count, p) 434 } 435 } 436 for _, rp := range f.RelativePeriod { 437 x.Index(rp).SetValue("", rp) 438 } 439 } 440 } 441 } 442 443 tree, err = build(b) 444 if err != nil { 445 t.Fatal("error building tree:", err) 446 } 447 w := gen.NewCodeWriter() 448 generate(b, tree, w) 449 generateTestData(b, w) 450 buf := &bytes.Buffer{} 451 if _, err = w.WriteGo(buf, "test"); err != nil { 452 t.Log(buf.String()) 453 t.Fatal("error generating code:", err) 454 } 455 return tree, buf.Bytes() 456 }