1// Copyright 2012 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
5package build
6
7import (
8	"testing"
9
10	"golang.org/x/text/internal/colltab"
11)
12
13type ceTest struct {
14	f   func(in []int) (uint32, error)
15	arg []int
16	val uint32
17}
18
19func normalCE(in []int) (ce uint32, err error) {
20	return makeCE(rawCE{w: in[:3], ccc: uint8(in[3])})
21}
22
23func expandCE(in []int) (ce uint32, err error) {
24	return makeExpandIndex(in[0])
25}
26
27func contractCE(in []int) (ce uint32, err error) {
28	return makeContractIndex(ctHandle{in[0], in[1]}, in[2])
29}
30
31func decompCE(in []int) (ce uint32, err error) {
32	return makeDecompose(in[0], in[1])
33}
34
35var ceTests = []ceTest{
36	{normalCE, []int{0, 0, 0, 0}, 0xA0000000},
37	{normalCE, []int{0, 0x28, 3, 0}, 0xA0002803},
38	{normalCE, []int{0, 0x28, 3, 0xFF}, 0xAFF02803},
39	{normalCE, []int{100, defaultSecondary, 3, 0}, 0x0000C883},
40	// non-ignorable primary with non-default secondary
41	{normalCE, []int{100, 0x28, defaultTertiary, 0}, 0x4000C828},
42	{normalCE, []int{100, defaultSecondary + 8, 3, 0}, 0x0000C983},
43	{normalCE, []int{100, 0, 3, 0}, 0xFFFF}, // non-ignorable primary with non-supported secondary
44	{normalCE, []int{100, 1, 3, 0}, 0xFFFF},
45	{normalCE, []int{1 << maxPrimaryBits, defaultSecondary, 0, 0}, 0xFFFF},
46	{normalCE, []int{0, 1 << maxSecondaryBits, 0, 0}, 0xFFFF},
47	{normalCE, []int{100, defaultSecondary, 1 << maxTertiaryBits, 0}, 0xFFFF},
48	{normalCE, []int{0x123, defaultSecondary, 8, 0xFF}, 0x88FF0123},
49	{normalCE, []int{0x123, defaultSecondary + 1, 8, 0xFF}, 0xFFFF},
50
51	{contractCE, []int{0, 0, 0}, 0xC0000000},
52	{contractCE, []int{1, 1, 1}, 0xC0010011},
53	{contractCE, []int{1, (1 << maxNBits) - 1, 1}, 0xC001001F},
54	{contractCE, []int{(1 << maxTrieIndexBits) - 1, 1, 1}, 0xC001FFF1},
55	{contractCE, []int{1, 1, (1 << maxContractOffsetBits) - 1}, 0xDFFF0011},
56	{contractCE, []int{1, (1 << maxNBits), 1}, 0xFFFF},
57	{contractCE, []int{(1 << maxTrieIndexBits), 1, 1}, 0xFFFF},
58	{contractCE, []int{1, (1 << maxContractOffsetBits), 1}, 0xFFFF},
59
60	{expandCE, []int{0}, 0xE0000000},
61	{expandCE, []int{5}, 0xE0000005},
62	{expandCE, []int{(1 << maxExpandIndexBits) - 1}, 0xE000FFFF},
63	{expandCE, []int{1 << maxExpandIndexBits}, 0xFFFF},
64
65	{decompCE, []int{0, 0}, 0xF0000000},
66	{decompCE, []int{1, 1}, 0xF0000101},
67	{decompCE, []int{0x1F, 0x1F}, 0xF0001F1F},
68	{decompCE, []int{256, 0x1F}, 0xFFFF},
69	{decompCE, []int{0x1F, 256}, 0xFFFF},
70}
71
72func TestColElem(t *testing.T) {
73	for i, tt := range ceTests {
74		in := make([]int, len(tt.arg))
75		copy(in, tt.arg)
76		ce, err := tt.f(in)
77		if tt.val == 0xFFFF {
78			if err == nil {
79				t.Errorf("%d: expected error for args %x", i, tt.arg)
80			}
81			continue
82		}
83		if err != nil {
84			t.Errorf("%d: unexpected error: %v", i, err.Error())
85		}
86		if ce != tt.val {
87			t.Errorf("%d: colElem=%X; want %X", i, ce, tt.val)
88		}
89	}
90}
91
92func mkRawCES(in [][]int) []rawCE {
93	out := []rawCE{}
94	for _, w := range in {
95		out = append(out, rawCE{w: w})
96	}
97	return out
98}
99
100type weightsTest struct {
101	a, b   [][]int
102	level  colltab.Level
103	result int
104}
105
106var nextWeightTests = []weightsTest{
107	{
108		a:     [][]int{{100, 20, 5, 0}},
109		b:     [][]int{{101, defaultSecondary, defaultTertiary, 0}},
110		level: colltab.Primary,
111	},
112	{
113		a:     [][]int{{100, 20, 5, 0}},
114		b:     [][]int{{100, 21, defaultTertiary, 0}},
115		level: colltab.Secondary,
116	},
117	{
118		a:     [][]int{{100, 20, 5, 0}},
119		b:     [][]int{{100, 20, 6, 0}},
120		level: colltab.Tertiary,
121	},
122	{
123		a:     [][]int{{100, 20, 5, 0}},
124		b:     [][]int{{100, 20, 5, 0}},
125		level: colltab.Identity,
126	},
127}
128
129var extra = [][]int{{200, 32, 8, 0}, {0, 32, 8, 0}, {0, 0, 8, 0}, {0, 0, 0, 0}}
130
131func TestNextWeight(t *testing.T) {
132	for i, tt := range nextWeightTests {
133		test := func(l colltab.Level, tt weightsTest, a, gold [][]int) {
134			res := nextWeight(tt.level, mkRawCES(a))
135			if !equalCEArrays(mkRawCES(gold), res) {
136				t.Errorf("%d:%d: expected weights %d; found %d", i, l, gold, res)
137			}
138		}
139		test(-1, tt, tt.a, tt.b)
140		for l := colltab.Primary; l <= colltab.Tertiary; l++ {
141			if tt.level <= l {
142				test(l, tt, append(tt.a, extra[l]), tt.b)
143			} else {
144				test(l, tt, append(tt.a, extra[l]), append(tt.b, extra[l]))
145			}
146		}
147	}
148}
149
150var compareTests = []weightsTest{
151	{
152		[][]int{{100, 20, 5, 0}},
153		[][]int{{100, 20, 5, 0}},
154		colltab.Identity,
155		0,
156	},
157	{
158		[][]int{{100, 20, 5, 0}, extra[0]},
159		[][]int{{100, 20, 5, 1}},
160		colltab.Primary,
161		1,
162	},
163	{
164		[][]int{{100, 20, 5, 0}},
165		[][]int{{101, 20, 5, 0}},
166		colltab.Primary,
167		-1,
168	},
169	{
170		[][]int{{101, 20, 5, 0}},
171		[][]int{{100, 20, 5, 0}},
172		colltab.Primary,
173		1,
174	},
175	{
176		[][]int{{100, 0, 0, 0}, {0, 20, 5, 0}},
177		[][]int{{0, 20, 5, 0}, {100, 0, 0, 0}},
178		colltab.Identity,
179		0,
180	},
181	{
182		[][]int{{100, 20, 5, 0}},
183		[][]int{{100, 21, 5, 0}},
184		colltab.Secondary,
185		-1,
186	},
187	{
188		[][]int{{100, 20, 5, 0}},
189		[][]int{{100, 20, 2, 0}},
190		colltab.Tertiary,
191		1,
192	},
193	{
194		[][]int{{100, 20, 5, 1}},
195		[][]int{{100, 20, 5, 2}},
196		colltab.Quaternary,
197		-1,
198	},
199}
200
201func TestCompareWeights(t *testing.T) {
202	for i, tt := range compareTests {
203		test := func(tt weightsTest, a, b [][]int) {
204			res, level := compareWeights(mkRawCES(a), mkRawCES(b))
205			if res != tt.result {
206				t.Errorf("%d: expected comparison result %d; found %d", i, tt.result, res)
207			}
208			if level != tt.level {
209				t.Errorf("%d: expected level %d; found %d", i, tt.level, level)
210			}
211		}
212		test(tt, tt.a, tt.b)
213		test(tt, append(tt.a, extra[0]), append(tt.b, extra[0]))
214	}
215}
216