resolve_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. package cldr
  2. import (
  3. "fmt"
  4. "log"
  5. "reflect"
  6. "testing"
  7. )
  8. func failOnError(err error) {
  9. if err != nil {
  10. log.Panic(err)
  11. }
  12. }
  13. func data() *CLDR {
  14. d := Decoder{}
  15. data, err := d.Decode(testLoader{})
  16. failOnError(err)
  17. return data
  18. }
  19. type h struct {
  20. A string `xml:"ha,attr"`
  21. E string `xml:"he"`
  22. D string `xml:",chardata"`
  23. X string
  24. }
  25. type fieldTest struct {
  26. Common
  27. To string `xml:"to,attr"`
  28. Key string `xml:"key,attr"`
  29. E string `xml:"e"`
  30. D string `xml:",chardata"`
  31. X string
  32. h
  33. }
  34. var testStruct = fieldTest{
  35. Common: Common{
  36. name: "mapping", // exclude "type" as distinguishing attribute
  37. Type: "foo",
  38. Alt: "foo",
  39. },
  40. To: "nyc",
  41. Key: "k",
  42. E: "E",
  43. D: "D",
  44. h: h{
  45. A: "A",
  46. E: "E",
  47. D: "D",
  48. },
  49. }
  50. func TestIter(t *testing.T) {
  51. tests := map[string]string{
  52. "Type": "foo",
  53. "Alt": "foo",
  54. "To": "nyc",
  55. "A": "A",
  56. "Alias": "<nil>",
  57. }
  58. k := 0
  59. for i := iter(reflect.ValueOf(testStruct)); !i.done(); i.next() {
  60. v := i.value()
  61. if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.String {
  62. v = v.Elem()
  63. }
  64. name := i.field().Name
  65. if w, ok := tests[name]; ok {
  66. s := fmt.Sprint(v.Interface())
  67. if w != s {
  68. t.Errorf("value: found %q; want %q", w, s)
  69. }
  70. delete(tests, name)
  71. }
  72. k++
  73. }
  74. if len(tests) != 0 {
  75. t.Errorf("missing fields: %v", tests)
  76. }
  77. }
  78. func TestFindField(t *testing.T) {
  79. tests := []struct {
  80. name, val string
  81. exist bool
  82. }{
  83. {"type", "foo", true},
  84. {"alt", "foo", true},
  85. {"to", "nyc", true},
  86. {"he", "E", true},
  87. {"q", "", false},
  88. }
  89. vf := reflect.ValueOf(testStruct)
  90. for i, tt := range tests {
  91. v, err := findField(vf, tt.name)
  92. if (err == nil) != tt.exist {
  93. t.Errorf("%d: field %q present is %v; want %v", i, tt.name, err == nil, tt.exist)
  94. } else if tt.exist {
  95. if v.Kind() == reflect.Ptr {
  96. if v.IsNil() {
  97. continue
  98. }
  99. v = v.Elem()
  100. }
  101. if v.String() != tt.val {
  102. t.Errorf("%d: found value %q; want %q", i, v.String(), tt.val)
  103. }
  104. }
  105. }
  106. }
  107. var keyTests = []struct {
  108. exclude []string
  109. key string
  110. }{
  111. {[]string{}, "alt=foo;key=k;to=nyc"},
  112. {[]string{"type"}, "alt=foo;key=k;to=nyc"},
  113. {[]string{"choice"}, "alt=foo;key=k;to=nyc"},
  114. {[]string{"alt"}, "key=k;to=nyc"},
  115. {[]string{"a"}, "alt=foo;key=k;to=nyc"},
  116. {[]string{"to"}, "alt=foo;key=k"},
  117. {[]string{"alt", "to"}, "key=k"},
  118. {[]string{"alt", "to", "key"}, ""},
  119. }
  120. func TestAttrKey(t *testing.T) {
  121. v := reflect.ValueOf(&testStruct)
  122. for i, tt := range keyTests {
  123. key := attrKey(v, tt.exclude...)
  124. if key != tt.key {
  125. t.Errorf("%d: found %q, want %q", i, key, tt.key)
  126. }
  127. }
  128. }
  129. func TestKey(t *testing.T) {
  130. for i, tt := range keyTests {
  131. key := Key(&testStruct, tt.exclude...)
  132. if key != tt.key {
  133. t.Errorf("%d: found %q, want %q", i, key, tt.key)
  134. }
  135. }
  136. }
  137. func testEnclosing(t *testing.T, x *LDML, name string) {
  138. eq := func(a, b Elem, i int) {
  139. for ; i > 0; i-- {
  140. b = b.enclosing()
  141. }
  142. if a != b {
  143. t.Errorf("%s: found path %q, want %q", name, getPath(a), getPath(b))
  144. }
  145. }
  146. eq(x, x, 0)
  147. eq(x, x.Identity, 1)
  148. eq(x, x.Dates.Calendars, 2)
  149. eq(x, x.Dates.Calendars.Calendar[0], 3)
  150. eq(x, x.Dates.Calendars.Calendar[1], 3)
  151. //eq(x, x.Dates.Calendars.Calendar[0].Months, 4)
  152. eq(x, x.Dates.Calendars.Calendar[1].Months, 4)
  153. }
  154. func TestEnclosing(t *testing.T) {
  155. testEnclosing(t, data().RawLDML("de"), "enclosing-raw")
  156. de, _ := data().LDML("de")
  157. testEnclosing(t, de, "enclosing")
  158. }
  159. func TestDeepCopy(t *testing.T) {
  160. eq := func(have, want string) {
  161. if have != want {
  162. t.Errorf("found %q; want %q", have, want)
  163. }
  164. }
  165. x, _ := data().LDML("de")
  166. vc := deepCopy(reflect.ValueOf(x))
  167. c := vc.Interface().(*LDML)
  168. linkEnclosing(nil, c)
  169. if x == c {
  170. t.Errorf("did not copy")
  171. }
  172. eq(c.name, "ldml")
  173. eq(c.Dates.name, "dates")
  174. testEnclosing(t, c, "deepCopy")
  175. }
  176. type getTest struct {
  177. loc string
  178. path string
  179. field string // used in combination with length
  180. data string
  181. altData string // used for buddhist calendar if value != ""
  182. typ string
  183. length int
  184. missing bool
  185. }
  186. const (
  187. budMon = "dates/calendars/calendar[@type='buddhist']/months/"
  188. chnMon = "dates/calendars/calendar[@type='chinese']/months/"
  189. greMon = "dates/calendars/calendar[@type='gregorian']/months/"
  190. )
  191. func monthVal(path, context, width string, month int) string {
  192. const format = "%s/monthContext[@type='%s']/monthWidth[@type='%s']/month[@type='%d']"
  193. return fmt.Sprintf(format, path, context, width, month)
  194. }
  195. var rootGetTests = []getTest{
  196. {loc: "root", path: "identity/language", typ: "root"},
  197. {loc: "root", path: "characters/moreInformation", data: "?"},
  198. {loc: "root", path: "characters", field: "exemplarCharacters", length: 3},
  199. {loc: "root", path: greMon, field: "monthContext", length: 2},
  200. {loc: "root", path: greMon + "monthContext[@type='format']/monthWidth[@type='narrow']", field: "month", length: 4},
  201. {loc: "root", path: greMon + "monthContext[@type='stand-alone']/monthWidth[@type='wide']", field: "month", length: 4},
  202. // unescaping character data
  203. {loc: "root", path: "characters/exemplarCharacters[@type='punctuation']", data: `[\- ‐ – — … ' ‘ ‚ " “ „ \& #]`},
  204. // default resolution
  205. {loc: "root", path: "dates/calendars/calendar", typ: "gregorian"},
  206. // alias resolution
  207. {loc: "root", path: budMon, field: "monthContext", length: 2},
  208. // crossing but non-circular alias resolution
  209. {loc: "root", path: budMon + "monthContext[@type='format']/monthWidth[@type='narrow']", field: "month", length: 4},
  210. {loc: "root", path: budMon + "monthContext[@type='stand-alone']/monthWidth[@type='wide']", field: "month", length: 4},
  211. {loc: "root", path: monthVal(greMon, "format", "wide", 1), data: "11"},
  212. {loc: "root", path: monthVal(greMon, "format", "narrow", 2), data: "2"},
  213. {loc: "root", path: monthVal(greMon, "stand-alone", "wide", 3), data: "33"},
  214. {loc: "root", path: monthVal(greMon, "stand-alone", "narrow", 4), data: "4"},
  215. {loc: "root", path: monthVal(budMon, "format", "wide", 1), data: "11"},
  216. {loc: "root", path: monthVal(budMon, "format", "narrow", 2), data: "2"},
  217. {loc: "root", path: monthVal(budMon, "stand-alone", "wide", 3), data: "33"},
  218. {loc: "root", path: monthVal(budMon, "stand-alone", "narrow", 4), data: "4"},
  219. }
  220. // 19
  221. var deGetTests = []getTest{
  222. {loc: "de", path: "identity/language", typ: "de"},
  223. {loc: "de", path: "posix", length: 2},
  224. {loc: "de", path: "characters", field: "exemplarCharacters", length: 4},
  225. {loc: "de", path: "characters/exemplarCharacters[@type='auxiliary']", data: `[á à ă]`},
  226. // identity is a blocking element, so de should not inherit generation from root.
  227. {loc: "de", path: "identity/generation", missing: true},
  228. // default resolution
  229. {loc: "root", path: "dates/calendars/calendar", typ: "gregorian"},
  230. // absolute path alias resolution
  231. {loc: "gsw", path: "posix", field: "messages", length: 1},
  232. {loc: "gsw", path: "posix/messages/yesstr", data: "yes:y"},
  233. }
  234. // 27(greMon) - 52(budMon) - 77(chnMon)
  235. func calGetTests(s string) []getTest {
  236. tests := []getTest{
  237. {loc: "de", path: s, length: 2},
  238. {loc: "de", path: s + "monthContext[@type='format']/monthWidth[@type='wide']", field: "month", length: 5},
  239. {loc: "de", path: monthVal(s, "format", "wide", 1), data: "11"},
  240. {loc: "de", path: monthVal(s, "format", "wide", 2), data: "22"},
  241. {loc: "de", path: monthVal(s, "format", "wide", 3), data: "Maerz", altData: "bbb"},
  242. {loc: "de", path: monthVal(s, "format", "wide", 4), data: "April"},
  243. {loc: "de", path: monthVal(s, "format", "wide", 5), data: "Mai"},
  244. {loc: "de", path: s + "monthContext[@type='format']/monthWidth[@type='narrow']", field: "month", length: 5},
  245. {loc: "de", path: monthVal(s, "format", "narrow", 1), data: "1"},
  246. {loc: "de", path: monthVal(s, "format", "narrow", 2), data: "2"},
  247. {loc: "de", path: monthVal(s, "format", "narrow", 3), data: "M", altData: "BBB"},
  248. {loc: "de", path: monthVal(s, "format", "narrow", 4), data: "A"},
  249. {loc: "de", path: monthVal(s, "format", "narrow", 5), data: "m"},
  250. {loc: "de", path: s + "monthContext[@type='stand-alone']/monthWidth[@type='wide']", field: "month", length: 5},
  251. {loc: "de", path: monthVal(s, "stand-alone", "wide", 1), data: "11"},
  252. {loc: "de", path: monthVal(s, "stand-alone", "wide", 2), data: "22"},
  253. {loc: "de", path: monthVal(s, "stand-alone", "wide", 3), data: "Maerz", altData: "bbb"},
  254. {loc: "de", path: monthVal(s, "stand-alone", "wide", 4), data: "april"},
  255. {loc: "de", path: monthVal(s, "stand-alone", "wide", 5), data: "mai"},
  256. {loc: "de", path: s + "monthContext[@type='stand-alone']/monthWidth[@type='narrow']", field: "month", length: 5},
  257. {loc: "de", path: monthVal(s, "stand-alone", "narrow", 1), data: "1"},
  258. {loc: "de", path: monthVal(s, "stand-alone", "narrow", 2), data: "2"},
  259. {loc: "de", path: monthVal(s, "stand-alone", "narrow", 3), data: "m"},
  260. {loc: "de", path: monthVal(s, "stand-alone", "narrow", 4), data: "4"},
  261. {loc: "de", path: monthVal(s, "stand-alone", "narrow", 5), data: "m"},
  262. }
  263. if s == budMon {
  264. for i, t := range tests {
  265. if t.altData != "" {
  266. tests[i].data = t.altData
  267. }
  268. }
  269. }
  270. return tests
  271. }
  272. var getTests = append(rootGetTests,
  273. append(deGetTests,
  274. append(calGetTests(greMon),
  275. append(calGetTests(budMon),
  276. calGetTests(chnMon)...)...)...)...)
  277. func TestPath(t *testing.T) {
  278. d := data()
  279. for i, tt := range getTests {
  280. x, _ := d.LDML(tt.loc)
  281. e, err := walkXPath(x, tt.path)
  282. if err != nil {
  283. if !tt.missing {
  284. t.Errorf("%d:error: %v %v", i, err, tt.missing)
  285. }
  286. continue
  287. }
  288. if tt.missing {
  289. t.Errorf("%d: missing is %v; want %v", i, e == nil, tt.missing)
  290. continue
  291. }
  292. if tt.data != "" && e.GetCommon().Data() != tt.data {
  293. t.Errorf("%d: data is %v; want %v", i, e.GetCommon().Data(), tt.data)
  294. continue
  295. }
  296. if tt.typ != "" && e.GetCommon().Type != tt.typ {
  297. t.Errorf("%d: type is %v; want %v", i, e.GetCommon().Type, tt.typ)
  298. continue
  299. }
  300. if tt.field != "" {
  301. slice, _ := findField(reflect.ValueOf(e), tt.field)
  302. if slice.Len() != tt.length {
  303. t.Errorf("%d: length is %v; want %v", i, slice.Len(), tt.length)
  304. continue
  305. }
  306. }
  307. }
  308. }
  309. func TestGet(t *testing.T) {
  310. d := data()
  311. for i, tt := range getTests {
  312. x, _ := d.LDML(tt.loc)
  313. e, err := Get(x, tt.path)
  314. if err != nil {
  315. if !tt.missing {
  316. t.Errorf("%d:error: %v %v", i, err, tt.missing)
  317. }
  318. continue
  319. }
  320. if tt.missing {
  321. t.Errorf("%d: missing is %v; want %v", i, e == nil, tt.missing)
  322. continue
  323. }
  324. if tt.data != "" && e.GetCommon().Data() != tt.data {
  325. t.Errorf("%d: data is %v; want %v", i, e.GetCommon().Data(), tt.data)
  326. continue
  327. }
  328. if tt.typ != "" && e.GetCommon().Type != tt.typ {
  329. t.Errorf("%d: type is %v; want %v", i, e.GetCommon().Type, tt.typ)
  330. continue
  331. }
  332. if tt.field != "" {
  333. slice, _ := findField(reflect.ValueOf(e), tt.field)
  334. if slice.Len() != tt.length {
  335. t.Errorf("%d: length is %v; want %v", i, slice.Len(), tt.length)
  336. continue
  337. }
  338. }
  339. }
  340. }