You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

276 lines
4.6 KiB

  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. package cldr
  5. import (
  6. "fmt"
  7. "strings"
  8. "testing"
  9. )
  10. // A recorder implements the RuleProcessor interface, whereby its methods
  11. // simply record the invocations.
  12. type recorder struct {
  13. calls []string
  14. }
  15. func (r *recorder) Reset(anchor string, before int) error {
  16. if before > 5 {
  17. return fmt.Errorf("before %d > 5", before)
  18. }
  19. r.calls = append(r.calls, fmt.Sprintf("R:%s-%d", anchor, before))
  20. return nil
  21. }
  22. func (r *recorder) Insert(level int, str, context, extend string) error {
  23. s := fmt.Sprintf("O:%d:%s", level, str)
  24. if context != "" {
  25. s += "|" + context
  26. }
  27. if extend != "" {
  28. s += "/" + extend
  29. }
  30. r.calls = append(r.calls, s)
  31. return nil
  32. }
  33. func (r *recorder) Index(id string) {
  34. r.calls = append(r.calls, fmt.Sprintf("I:%s", id))
  35. }
  36. func (r *recorder) Error(err error) {
  37. r.calls = append(r.calls, fmt.Sprintf("E:%v", err))
  38. }
  39. func TestRuleProcessor(t *testing.T) {
  40. for _, tt := range []struct {
  41. desc string
  42. in string
  43. out string
  44. }{
  45. {desc: "empty"},
  46. {desc: "whitespace and comments only",
  47. in: `
  48. # adsfads
  49. # adfadf
  50. `,
  51. },
  52. {
  53. desc: "reset anchor",
  54. in: `
  55. & a
  56. &b #
  57. & [ before 3 ] c
  58. & [before 4] d & ee
  59. & [first tertiary ignorable]
  60. &'g'
  61. & 'h''h'h'h'
  62. &'\u0069' # LATIN SMALL LETTER I
  63. `,
  64. out: `
  65. R:a-0
  66. R:b-0
  67. R:c-3
  68. R:d-4
  69. R:ee-0
  70. R:<first tertiary ignorable/>-0
  71. R:g-0
  72. R:hhhh-0
  73. R:i-0
  74. `,
  75. },
  76. {
  77. desc: "ordering",
  78. in: `
  79. & 0
  80. < 1 <<''2#
  81. <<< 3'3''33'3#
  82. <<<<4
  83. = 5 << 6 | s
  84. <<<< 7 / z
  85. << 8'' | s / ch
  86. `,
  87. out: `
  88. R:0-0
  89. O:1:1
  90. O:2:'2
  91. O:3:33333
  92. O:4:4
  93. O:5:5
  94. O:2:6|s
  95. O:4:7/z
  96. O:2:8'|s/ch
  97. `,
  98. },
  99. {
  100. desc: "index",
  101. in: "< '\ufdd0'A",
  102. out: "I:A",
  103. },
  104. {
  105. desc: "sequence",
  106. in: `
  107. & 0
  108. <<* 1234
  109. <* a-cde-f
  110. =* q-q
  111. `,
  112. out: `
  113. R:0-0
  114. O:2:1
  115. O:2:2
  116. O:2:3
  117. O:2:4
  118. O:1:a
  119. O:1:b
  120. O:1:c
  121. O:1:d
  122. O:1:e
  123. O:1:f
  124. O:5:q
  125. `,
  126. },
  127. {
  128. desc: "compact",
  129. in: "&B<t<<<T<s<<<S<e<<<E",
  130. out: `
  131. R:B-0
  132. O:1:t
  133. O:3:T
  134. O:1:s
  135. O:3:S
  136. O:1:e
  137. O:3:E
  138. `,
  139. },
  140. {
  141. desc: "err operator",
  142. in: "a",
  143. out: "E:1: illegal operator 'a'",
  144. },
  145. {
  146. desc: "err line number",
  147. in: `& a
  148. << b
  149. a`,
  150. out: `
  151. R:a-0
  152. O:2:b
  153. E:3: illegal operator 'a'`,
  154. },
  155. {
  156. desc: "err empty anchor",
  157. in: " & ",
  158. out: "E:1: missing string",
  159. },
  160. {
  161. desc: "err anchor invalid special 1",
  162. in: " & [ foo ",
  163. out: "E:1: unmatched bracket",
  164. },
  165. {
  166. desc: "err anchor invalid special 2",
  167. in: "&[",
  168. out: "E:1: unmatched bracket",
  169. },
  170. {
  171. desc: "err anchor invalid before 1",
  172. in: "&[before a]",
  173. out: `E:1: strconv.ParseUint: parsing "a": invalid syntax`,
  174. },
  175. {
  176. desc: "err anchor invalid before 2",
  177. in: "&[before 12]",
  178. out: `E:1: strconv.ParseUint: parsing "12": value out of range`,
  179. },
  180. {
  181. desc: "err anchor invalid before 3",
  182. in: "&[before 2]",
  183. out: "E:1: missing string",
  184. },
  185. {
  186. desc: "err anchor invalid before 4",
  187. in: "&[before 6] a",
  188. out: "E:1: before 6 > 5",
  189. },
  190. {
  191. desc: "err empty order",
  192. in: " < ",
  193. out: "E:1: missing string",
  194. },
  195. {
  196. desc: "err empty identity",
  197. in: " = ",
  198. out: "E:1: missing string",
  199. },
  200. {
  201. desc: "err empty context",
  202. in: " < a | ",
  203. out: "E:1: missing string after context",
  204. },
  205. {
  206. desc: "err empty extend",
  207. in: " < a / ",
  208. out: "E:1: missing string after extension",
  209. },
  210. {
  211. desc: "err empty sequence",
  212. in: " <* ",
  213. out: "E:1: empty sequence",
  214. },
  215. {
  216. desc: "err sequence 1",
  217. in: " <* -a",
  218. out: "E:1: range without starter value",
  219. },
  220. {
  221. desc: "err sequence 3",
  222. in: " <* a-a-b",
  223. out: `O:1:a
  224. E:1: range without starter value
  225. `,
  226. },
  227. {
  228. desc: "err sequence 3",
  229. in: " <* b-a",
  230. out: `O:1:b
  231. E:1: invalid range 'b'-'a'
  232. `,
  233. },
  234. {
  235. desc: "err unmatched quote",
  236. in: " < 'b",
  237. out: ` E:1: unmatched single quote
  238. `,
  239. },
  240. } {
  241. rec := &recorder{}
  242. err := Collation{
  243. Cr: []*Common{
  244. {hidden: hidden{CharData: tt.in}},
  245. },
  246. }.Process(rec)
  247. if err != nil {
  248. rec.Error(err)
  249. }
  250. got := rec.calls
  251. want := strings.Split(strings.TrimSpace(tt.out), "\n")
  252. if tt.out == "" {
  253. want = nil
  254. }
  255. if len(got) != len(want) {
  256. t.Errorf("%s: nResults: got %d; want %d", tt.desc, len(got), len(want))
  257. continue
  258. }
  259. for i, g := range got {
  260. if want := strings.TrimSpace(want[i]); g != want {
  261. t.Errorf("%s:%d: got %q; want %q", tt.desc, i, g, want)
  262. }
  263. }
  264. }
  265. }