package cldr import ( "fmt" "log" "reflect" "testing" ) func failOnError(err error) { if err != nil { log.Panic(err) } } func data() *CLDR { d := Decoder{} data, err := d.Decode(testLoader{}) failOnError(err) return data } type h struct { A string `xml:"ha,attr"` E string `xml:"he"` D string `xml:",chardata"` X string } type fieldTest struct { Common To string `xml:"to,attr"` Key string `xml:"key,attr"` E string `xml:"e"` D string `xml:",chardata"` X string h } var testStruct = fieldTest{ Common: Common{ name: "mapping", // exclude "type" as distinguishing attribute Type: "foo", Alt: "foo", }, To: "nyc", Key: "k", E: "E", D: "D", h: h{ A: "A", E: "E", D: "D", }, } func TestIter(t *testing.T) { tests := map[string]string{ "Type": "foo", "Alt": "foo", "To": "nyc", "A": "A", "Alias": "", } k := 0 for i := iter(reflect.ValueOf(testStruct)); !i.done(); i.next() { v := i.value() if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.String { v = v.Elem() } name := i.field().Name if w, ok := tests[name]; ok { s := fmt.Sprint(v.Interface()) if w != s { t.Errorf("value: found %q; want %q", w, s) } delete(tests, name) } k++ } if len(tests) != 0 { t.Errorf("missing fields: %v", tests) } } func TestFindField(t *testing.T) { tests := []struct { name, val string exist bool }{ {"type", "foo", true}, {"alt", "foo", true}, {"to", "nyc", true}, {"he", "E", true}, {"q", "", false}, } vf := reflect.ValueOf(testStruct) for i, tt := range tests { v, err := findField(vf, tt.name) if (err == nil) != tt.exist { t.Errorf("%d: field %q present is %v; want %v", i, tt.name, err == nil, tt.exist) } else if tt.exist { if v.Kind() == reflect.Ptr { if v.IsNil() { continue } v = v.Elem() } if v.String() != tt.val { t.Errorf("%d: found value %q; want %q", i, v.String(), tt.val) } } } } var keyTests = []struct { exclude []string key string }{ {[]string{}, "alt=foo;key=k;to=nyc"}, {[]string{"type"}, "alt=foo;key=k;to=nyc"}, {[]string{"choice"}, "alt=foo;key=k;to=nyc"}, {[]string{"alt"}, "key=k;to=nyc"}, {[]string{"a"}, "alt=foo;key=k;to=nyc"}, {[]string{"to"}, "alt=foo;key=k"}, {[]string{"alt", "to"}, "key=k"}, {[]string{"alt", "to", "key"}, ""}, } func TestAttrKey(t *testing.T) { v := reflect.ValueOf(&testStruct) for i, tt := range keyTests { key := attrKey(v, tt.exclude...) if key != tt.key { t.Errorf("%d: found %q, want %q", i, key, tt.key) } } } func TestKey(t *testing.T) { for i, tt := range keyTests { key := Key(&testStruct, tt.exclude...) if key != tt.key { t.Errorf("%d: found %q, want %q", i, key, tt.key) } } } func testEnclosing(t *testing.T, x *LDML, name string) { eq := func(a, b Elem, i int) { for ; i > 0; i-- { b = b.enclosing() } if a != b { t.Errorf("%s: found path %q, want %q", name, getPath(a), getPath(b)) } } eq(x, x, 0) eq(x, x.Identity, 1) eq(x, x.Dates.Calendars, 2) eq(x, x.Dates.Calendars.Calendar[0], 3) eq(x, x.Dates.Calendars.Calendar[1], 3) //eq(x, x.Dates.Calendars.Calendar[0].Months, 4) eq(x, x.Dates.Calendars.Calendar[1].Months, 4) } func TestEnclosing(t *testing.T) { testEnclosing(t, data().RawLDML("de"), "enclosing-raw") de, _ := data().LDML("de") testEnclosing(t, de, "enclosing") } func TestDeepCopy(t *testing.T) { eq := func(have, want string) { if have != want { t.Errorf("found %q; want %q", have, want) } } x, _ := data().LDML("de") vc := deepCopy(reflect.ValueOf(x)) c := vc.Interface().(*LDML) linkEnclosing(nil, c) if x == c { t.Errorf("did not copy") } eq(c.name, "ldml") eq(c.Dates.name, "dates") testEnclosing(t, c, "deepCopy") } type getTest struct { loc string path string field string // used in combination with length data string altData string // used for buddhist calendar if value != "" typ string length int missing bool } const ( budMon = "dates/calendars/calendar[@type='buddhist']/months/" chnMon = "dates/calendars/calendar[@type='chinese']/months/" greMon = "dates/calendars/calendar[@type='gregorian']/months/" ) func monthVal(path, context, width string, month int) string { const format = "%s/monthContext[@type='%s']/monthWidth[@type='%s']/month[@type='%d']" return fmt.Sprintf(format, path, context, width, month) } var rootGetTests = []getTest{ {loc: "root", path: "identity/language", typ: "root"}, {loc: "root", path: "characters/moreInformation", data: "?"}, {loc: "root", path: "characters", field: "exemplarCharacters", length: 3}, {loc: "root", path: greMon, field: "monthContext", length: 2}, {loc: "root", path: greMon + "monthContext[@type='format']/monthWidth[@type='narrow']", field: "month", length: 4}, {loc: "root", path: greMon + "monthContext[@type='stand-alone']/monthWidth[@type='wide']", field: "month", length: 4}, // unescaping character data {loc: "root", path: "characters/exemplarCharacters[@type='punctuation']", data: `[\- ‐ – — … ' ‘ ‚ " “ „ \& #]`}, // default resolution {loc: "root", path: "dates/calendars/calendar", typ: "gregorian"}, // alias resolution {loc: "root", path: budMon, field: "monthContext", length: 2}, // crossing but non-circular alias resolution {loc: "root", path: budMon + "monthContext[@type='format']/monthWidth[@type='narrow']", field: "month", length: 4}, {loc: "root", path: budMon + "monthContext[@type='stand-alone']/monthWidth[@type='wide']", field: "month", length: 4}, {loc: "root", path: monthVal(greMon, "format", "wide", 1), data: "11"}, {loc: "root", path: monthVal(greMon, "format", "narrow", 2), data: "2"}, {loc: "root", path: monthVal(greMon, "stand-alone", "wide", 3), data: "33"}, {loc: "root", path: monthVal(greMon, "stand-alone", "narrow", 4), data: "4"}, {loc: "root", path: monthVal(budMon, "format", "wide", 1), data: "11"}, {loc: "root", path: monthVal(budMon, "format", "narrow", 2), data: "2"}, {loc: "root", path: monthVal(budMon, "stand-alone", "wide", 3), data: "33"}, {loc: "root", path: monthVal(budMon, "stand-alone", "narrow", 4), data: "4"}, } // 19 var deGetTests = []getTest{ {loc: "de", path: "identity/language", typ: "de"}, {loc: "de", path: "posix", length: 2}, {loc: "de", path: "characters", field: "exemplarCharacters", length: 4}, {loc: "de", path: "characters/exemplarCharacters[@type='auxiliary']", data: `[á à ă]`}, // identity is a blocking element, so de should not inherit generation from root. {loc: "de", path: "identity/generation", missing: true}, // default resolution {loc: "root", path: "dates/calendars/calendar", typ: "gregorian"}, // absolute path alias resolution {loc: "gsw", path: "posix", field: "messages", length: 1}, {loc: "gsw", path: "posix/messages/yesstr", data: "yes:y"}, } // 27(greMon) - 52(budMon) - 77(chnMon) func calGetTests(s string) []getTest { tests := []getTest{ {loc: "de", path: s, length: 2}, {loc: "de", path: s + "monthContext[@type='format']/monthWidth[@type='wide']", field: "month", length: 5}, {loc: "de", path: monthVal(s, "format", "wide", 1), data: "11"}, {loc: "de", path: monthVal(s, "format", "wide", 2), data: "22"}, {loc: "de", path: monthVal(s, "format", "wide", 3), data: "Maerz", altData: "bbb"}, {loc: "de", path: monthVal(s, "format", "wide", 4), data: "April"}, {loc: "de", path: monthVal(s, "format", "wide", 5), data: "Mai"}, {loc: "de", path: s + "monthContext[@type='format']/monthWidth[@type='narrow']", field: "month", length: 5}, {loc: "de", path: monthVal(s, "format", "narrow", 1), data: "1"}, {loc: "de", path: monthVal(s, "format", "narrow", 2), data: "2"}, {loc: "de", path: monthVal(s, "format", "narrow", 3), data: "M", altData: "BBB"}, {loc: "de", path: monthVal(s, "format", "narrow", 4), data: "A"}, {loc: "de", path: monthVal(s, "format", "narrow", 5), data: "m"}, {loc: "de", path: s + "monthContext[@type='stand-alone']/monthWidth[@type='wide']", field: "month", length: 5}, {loc: "de", path: monthVal(s, "stand-alone", "wide", 1), data: "11"}, {loc: "de", path: monthVal(s, "stand-alone", "wide", 2), data: "22"}, {loc: "de", path: monthVal(s, "stand-alone", "wide", 3), data: "Maerz", altData: "bbb"}, {loc: "de", path: monthVal(s, "stand-alone", "wide", 4), data: "april"}, {loc: "de", path: monthVal(s, "stand-alone", "wide", 5), data: "mai"}, {loc: "de", path: s + "monthContext[@type='stand-alone']/monthWidth[@type='narrow']", field: "month", length: 5}, {loc: "de", path: monthVal(s, "stand-alone", "narrow", 1), data: "1"}, {loc: "de", path: monthVal(s, "stand-alone", "narrow", 2), data: "2"}, {loc: "de", path: monthVal(s, "stand-alone", "narrow", 3), data: "m"}, {loc: "de", path: monthVal(s, "stand-alone", "narrow", 4), data: "4"}, {loc: "de", path: monthVal(s, "stand-alone", "narrow", 5), data: "m"}, } if s == budMon { for i, t := range tests { if t.altData != "" { tests[i].data = t.altData } } } return tests } var getTests = append(rootGetTests, append(deGetTests, append(calGetTests(greMon), append(calGetTests(budMon), calGetTests(chnMon)...)...)...)...) func TestPath(t *testing.T) { d := data() for i, tt := range getTests { x, _ := d.LDML(tt.loc) e, err := walkXPath(x, tt.path) if err != nil { if !tt.missing { t.Errorf("%d:error: %v %v", i, err, tt.missing) } continue } if tt.missing { t.Errorf("%d: missing is %v; want %v", i, e == nil, tt.missing) continue } if tt.data != "" && e.GetCommon().Data() != tt.data { t.Errorf("%d: data is %v; want %v", i, e.GetCommon().Data(), tt.data) continue } if tt.typ != "" && e.GetCommon().Type != tt.typ { t.Errorf("%d: type is %v; want %v", i, e.GetCommon().Type, tt.typ) continue } if tt.field != "" { slice, _ := findField(reflect.ValueOf(e), tt.field) if slice.Len() != tt.length { t.Errorf("%d: length is %v; want %v", i, slice.Len(), tt.length) continue } } } } func TestGet(t *testing.T) { d := data() for i, tt := range getTests { x, _ := d.LDML(tt.loc) e, err := Get(x, tt.path) if err != nil { if !tt.missing { t.Errorf("%d:error: %v %v", i, err, tt.missing) } continue } if tt.missing { t.Errorf("%d: missing is %v; want %v", i, e == nil, tt.missing) continue } if tt.data != "" && e.GetCommon().Data() != tt.data { t.Errorf("%d: data is %v; want %v", i, e.GetCommon().Data(), tt.data) continue } if tt.typ != "" && e.GetCommon().Type != tt.typ { t.Errorf("%d: type is %v; want %v", i, e.GetCommon().Type, tt.typ) continue } if tt.field != "" { slice, _ := findField(reflect.ValueOf(e), tt.field) if slice.Len() != tt.length { t.Errorf("%d: length is %v; want %v", i, slice.Len(), tt.length) continue } } } }