1
2
3
4
5 package build
6
7 import "testing"
8
9
10 func cjk(r rune) []rawCE {
11
12
13
14
15 const base = 0xFB40
16 return []rawCE{
17 {w: []int{base + int(r>>15), defaultSecondary, defaultTertiary, int(r)}},
18 {w: []int{int(r&0x7FFF) | 0x8000, 0, 0, int(r)}},
19 }
20 }
21
22 func pCE(p int) []rawCE {
23 return mkCE([]int{p, defaultSecondary, defaultTertiary, 0}, 0)
24 }
25
26 func pqCE(p, q int) []rawCE {
27 return mkCE([]int{p, defaultSecondary, defaultTertiary, q}, 0)
28 }
29
30 func ptCE(p, t int) []rawCE {
31 return mkCE([]int{p, defaultSecondary, t, 0}, 0)
32 }
33
34 func ptcCE(p, t int, ccc uint8) []rawCE {
35 return mkCE([]int{p, defaultSecondary, t, 0}, ccc)
36 }
37
38 func sCE(s int) []rawCE {
39 return mkCE([]int{0, s, defaultTertiary, 0}, 0)
40 }
41
42 func stCE(s, t int) []rawCE {
43 return mkCE([]int{0, s, t, 0}, 0)
44 }
45
46 func scCE(s int, ccc uint8) []rawCE {
47 return mkCE([]int{0, s, defaultTertiary, 0}, ccc)
48 }
49
50 func mkCE(w []int, ccc uint8) []rawCE {
51 return []rawCE{rawCE{w, ccc}}
52 }
53
54
55 type ducetElem struct {
56 str string
57 ces []rawCE
58 }
59
60 func newBuilder(t *testing.T, ducet []ducetElem) *Builder {
61 b := NewBuilder()
62 for _, e := range ducet {
63 ces := [][]int{}
64 for _, ce := range e.ces {
65 ces = append(ces, ce.w)
66 }
67 if err := b.Add([]rune(e.str), ces, nil); err != nil {
68 t.Errorf(err.Error())
69 }
70 }
71 b.t = &table{}
72 b.root.sort()
73 return b
74 }
75
76 type convertTest struct {
77 in, out []rawCE
78 err bool
79 }
80
81 var convLargeTests = []convertTest{
82 {pCE(0xFB39), pCE(0xFB39), false},
83 {cjk(0x2F9B2), pqCE(0x3F9B2, 0x2F9B2), false},
84 {pCE(0xFB40), pCE(0), true},
85 {append(pCE(0xFB40), pCE(0)[0]), pCE(0), true},
86 {pCE(0xFFFE), pCE(illegalOffset), false},
87 {pCE(0xFFFF), pCE(illegalOffset + 1), false},
88 }
89
90 func TestConvertLarge(t *testing.T) {
91 for i, tt := range convLargeTests {
92 e := new(entry)
93 for _, ce := range tt.in {
94 e.elems = append(e.elems, makeRawCE(ce.w, ce.ccc))
95 }
96 elems, err := convertLargeWeights(e.elems)
97 if tt.err {
98 if err == nil {
99 t.Errorf("%d: expected error; none found", i)
100 }
101 continue
102 } else if err != nil {
103 t.Errorf("%d: unexpected error: %v", i, err)
104 }
105 if !equalCEArrays(elems, tt.out) {
106 t.Errorf("%d: conversion was %x; want %x", i, elems, tt.out)
107 }
108 }
109 }
110
111
112 var simplifyTest = []ducetElem{
113 {"\u0300", sCE(30)},
114 {"\u030C", sCE(40)},
115 {"A", ptCE(100, 8)},
116 {"D", ptCE(104, 8)},
117 {"E", ptCE(105, 8)},
118 {"I", ptCE(110, 8)},
119 {"z", ptCE(130, 8)},
120 {"\u05F2", append(ptCE(200, 4), ptCE(200, 4)[0])},
121 {"\u05B7", sCE(80)},
122 {"\u00C0", append(ptCE(100, 8), sCE(30)...)},
123 {"\u00C8", append(ptCE(105, 8), sCE(30)...)},
124 {"\uFB1F", append(ptCE(200, 4), ptCE(200, 4)[0], sCE(80)[0])},
125 {"\u00C8\u0302", ptCE(106, 8)},
126 {"\u01C5", append(ptCE(104, 9), ptCE(130, 4)[0], stCE(40, maxTertiary)[0])},
127
128 {"\u2162", append(ptCE(110, 9), ptCE(110, 4)[0], ptCE(110, 8)[0])},
129 }
130
131 var genColTests = []ducetElem{
132 {"\uFA70", pqCE(0x1FA70, 0xFA70)},
133 {"A\u0300", append(ptCE(100, 8), sCE(30)...)},
134 {"A\u0300\uFA70", append(ptCE(100, 8), sCE(30)[0], pqCE(0x1FA70, 0xFA70)[0])},
135 {"A\u0300A\u0300", append(ptCE(100, 8), sCE(30)[0], ptCE(100, 8)[0], sCE(30)[0])},
136 }
137
138 func TestGenColElems(t *testing.T) {
139 b := newBuilder(t, simplifyTest[:5])
140
141 for i, tt := range genColTests {
142 res := b.root.genColElems(tt.str)
143 if !equalCEArrays(tt.ces, res) {
144 t.Errorf("%d: result %X; want %X", i, res, tt.ces)
145 }
146 }
147 }
148
149 type strArray []string
150
151 func (sa strArray) contains(s string) bool {
152 for _, e := range sa {
153 if e == s {
154 return true
155 }
156 }
157 return false
158 }
159
160 var simplifyRemoved = strArray{"\u00C0", "\uFB1F"}
161 var simplifyMarked = strArray{"\u01C5"}
162
163 func TestSimplify(t *testing.T) {
164 b := newBuilder(t, simplifyTest)
165 o := &b.root
166 simplify(o)
167
168 for i, tt := range simplifyTest {
169 if simplifyRemoved.contains(tt.str) {
170 continue
171 }
172 e := o.find(tt.str)
173 if e.str != tt.str || !equalCEArrays(e.elems, tt.ces) {
174 t.Errorf("%d: found element %s -> %X; want %s -> %X", i, e.str, e.elems, tt.str, tt.ces)
175 break
176 }
177 }
178 var i, k int
179 for e := o.front(); e != nil; e, _ = e.nextIndexed() {
180 gold := simplifyMarked.contains(e.str)
181 if gold {
182 k++
183 }
184 if gold != e.decompose {
185 t.Errorf("%d: %s has decompose %v; want %v", i, e.str, e.decompose, gold)
186 }
187 i++
188 }
189 if k != len(simplifyMarked) {
190 t.Errorf(" an entry that should be marked as decompose was deleted")
191 }
192 }
193
194 var expandTest = []ducetElem{
195 {"\u0300", append(scCE(29, 230), scCE(30, 230)...)},
196 {"\u00C0", append(ptCE(100, 8), scCE(30, 230)...)},
197 {"\u00C8", append(ptCE(105, 8), scCE(30, 230)...)},
198 {"\u00C9", append(ptCE(105, 8), scCE(30, 230)...)},
199 {"\u05F2", append(ptCE(200, 4), ptCE(200, 4)[0], ptCE(200, 4)[0])},
200 {"\u01FF", append(ptCE(200, 4), ptcCE(201, 4, 0)[0], scCE(30, 230)[0])},
201 }
202
203 func TestExpand(t *testing.T) {
204 const (
205 totalExpansions = 5
206 totalElements = 2 + 2 + 2 + 3 + 3 + totalExpansions
207 )
208 b := newBuilder(t, expandTest)
209 o := &b.root
210 b.processExpansions(o)
211
212 e := o.front()
213 for _, tt := range expandTest {
214 exp := b.t.ExpandElem[e.expansionIndex:]
215 if int(exp[0]) != len(tt.ces) {
216 t.Errorf("%U: len(expansion)==%d; want %d", []rune(tt.str)[0], exp[0], len(tt.ces))
217 }
218 exp = exp[1:]
219 for j, w := range tt.ces {
220 if ce, _ := makeCE(w); exp[j] != ce {
221 t.Errorf("%U: element %d is %X; want %X", []rune(tt.str)[0], j, exp[j], ce)
222 }
223 }
224 e, _ = e.nextIndexed()
225 }
226
227 if len(b.t.ExpandElem) != totalElements {
228 t.Errorf("len(expandElem)==%d; want %d", len(b.t.ExpandElem), totalElements)
229 }
230 }
231
232 var contractTest = []ducetElem{
233 {"abc", pCE(102)},
234 {"abd", pCE(103)},
235 {"a", pCE(100)},
236 {"ab", pCE(101)},
237 {"ac", pCE(104)},
238 {"bcd", pCE(202)},
239 {"b", pCE(200)},
240 {"bc", pCE(201)},
241 {"bd", pCE(203)},
242
243 {"Ab", pCE(301)},
244 {"A", pCE(300)},
245 {"Ac", pCE(304)},
246 {"Abc", pCE(302)},
247 {"Abd", pCE(303)},
248
249 {"z", pCE(1000)},
250 }
251
252 func TestContract(t *testing.T) {
253 const (
254 totalElements = 5 + 5 + 4
255 )
256 b := newBuilder(t, contractTest)
257 o := &b.root
258 b.processContractions(o)
259
260 indexMap := make(map[int]bool)
261 handleMap := make(map[rune]*entry)
262 for e := o.front(); e != nil; e, _ = e.nextIndexed() {
263 if e.contractionHandle.n > 0 {
264 handleMap[e.runes[0]] = e
265 indexMap[e.contractionHandle.index] = true
266 }
267 }
268
269 if len(indexMap) != 2 {
270 t.Errorf("number of tries is %d; want %d", len(indexMap), 2)
271 }
272 for _, tt := range contractTest {
273 e, ok := handleMap[[]rune(tt.str)[0]]
274 if !ok {
275 continue
276 }
277 str := tt.str[1:]
278 offset, n := lookup(&b.t.ContractTries, e.contractionHandle, []byte(str))
279 if len(str) != n {
280 t.Errorf("%s: bytes consumed==%d; want %d", tt.str, n, len(str))
281 }
282 ce := b.t.ContractElem[offset+e.contractionIndex]
283 if want, _ := makeCE(tt.ces[0]); want != ce {
284 t.Errorf("%s: element %X; want %X", tt.str, ce, want)
285 }
286 }
287 if len(b.t.ContractElem) != totalElements {
288 t.Errorf("len(expandElem)==%d; want %d", len(b.t.ContractElem), totalElements)
289 }
290 }
291
View as plain text