230 lines
4.7 KiB
Go
230 lines
4.7 KiB
Go
// Copyright 2012 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package build
|
|
|
|
import (
|
|
"strconv"
|
|
"testing"
|
|
|
|
"golang.org/x/text/internal/colltab"
|
|
)
|
|
|
|
type entryTest struct {
|
|
f func(in []int) (uint32, error)
|
|
arg []int
|
|
val uint32
|
|
}
|
|
|
|
// makeList returns a list of entries of length n+2, with n normal
|
|
// entries plus a leading and trailing anchor.
|
|
func makeList(n int) []*entry {
|
|
es := make([]*entry, n+2)
|
|
weights := []rawCE{{w: []int{100, 20, 5, 0}}}
|
|
for i := range es {
|
|
runes := []rune{rune(i)}
|
|
es[i] = &entry{
|
|
runes: runes,
|
|
elems: weights,
|
|
}
|
|
weights = nextWeight(colltab.Primary, weights)
|
|
}
|
|
for i := 1; i < len(es); i++ {
|
|
es[i-1].next = es[i]
|
|
es[i].prev = es[i-1]
|
|
_, es[i-1].level = compareWeights(es[i-1].elems, es[i].elems)
|
|
}
|
|
es[0].exclude = true
|
|
es[0].logical = firstAnchor
|
|
es[len(es)-1].exclude = true
|
|
es[len(es)-1].logical = lastAnchor
|
|
return es
|
|
}
|
|
|
|
func TestNextIndexed(t *testing.T) {
|
|
const n = 5
|
|
es := makeList(n)
|
|
for i := int64(0); i < 1<<n; i++ {
|
|
mask := strconv.FormatInt(i+(1<<n), 2)
|
|
for i, c := range mask {
|
|
es[i].exclude = c == '1'
|
|
}
|
|
e := es[0]
|
|
for i, c := range mask {
|
|
if c == '0' {
|
|
e, _ = e.nextIndexed()
|
|
if e != es[i] {
|
|
t.Errorf("%d: expected entry %d; found %d", i, es[i].elems, e.elems)
|
|
}
|
|
}
|
|
}
|
|
if e, _ = e.nextIndexed(); e != nil {
|
|
t.Errorf("%d: expected nil entry; found %d", i, e.elems)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRemove(t *testing.T) {
|
|
const n = 5
|
|
for i := int64(0); i < 1<<n; i++ {
|
|
es := makeList(n)
|
|
mask := strconv.FormatInt(i+(1<<n), 2)
|
|
for i, c := range mask {
|
|
if c == '0' {
|
|
es[i].remove()
|
|
}
|
|
}
|
|
e := es[0]
|
|
for i, c := range mask {
|
|
if c == '1' {
|
|
if e != es[i] {
|
|
t.Errorf("%d: expected entry %d; found %d", i, es[i].elems, e.elems)
|
|
}
|
|
e, _ = e.nextIndexed()
|
|
}
|
|
}
|
|
if e != nil {
|
|
t.Errorf("%d: expected nil entry; found %d", i, e.elems)
|
|
}
|
|
}
|
|
}
|
|
|
|
// nextPerm generates the next permutation of the array. The starting
|
|
// permutation is assumed to be a list of integers sorted in increasing order.
|
|
// It returns false if there are no more permuations left.
|
|
func nextPerm(a []int) bool {
|
|
i := len(a) - 2
|
|
for ; i >= 0; i-- {
|
|
if a[i] < a[i+1] {
|
|
break
|
|
}
|
|
}
|
|
if i < 0 {
|
|
return false
|
|
}
|
|
for j := len(a) - 1; j >= i; j-- {
|
|
if a[j] > a[i] {
|
|
a[i], a[j] = a[j], a[i]
|
|
break
|
|
}
|
|
}
|
|
for j := i + 1; j < (len(a)+i+1)/2; j++ {
|
|
a[j], a[len(a)+i-j] = a[len(a)+i-j], a[j]
|
|
}
|
|
return true
|
|
}
|
|
|
|
func TestInsertAfter(t *testing.T) {
|
|
const n = 5
|
|
orig := makeList(n)
|
|
perm := make([]int, n)
|
|
for i := range perm {
|
|
perm[i] = i + 1
|
|
}
|
|
for ok := true; ok; ok = nextPerm(perm) {
|
|
es := makeList(n)
|
|
last := es[0]
|
|
for _, i := range perm {
|
|
last.insertAfter(es[i])
|
|
last = es[i]
|
|
}
|
|
for _, e := range es {
|
|
e.elems = es[0].elems
|
|
}
|
|
e := es[0]
|
|
for _, i := range perm {
|
|
e, _ = e.nextIndexed()
|
|
if e.runes[0] != orig[i].runes[0] {
|
|
t.Errorf("%d:%d: expected entry %X; found %X", perm, i, orig[i].runes, e.runes)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestInsertBefore(t *testing.T) {
|
|
const n = 5
|
|
orig := makeList(n)
|
|
perm := make([]int, n)
|
|
for i := range perm {
|
|
perm[i] = i + 1
|
|
}
|
|
for ok := true; ok; ok = nextPerm(perm) {
|
|
es := makeList(n)
|
|
last := es[len(es)-1]
|
|
for _, i := range perm {
|
|
last.insertBefore(es[i])
|
|
last = es[i]
|
|
}
|
|
for _, e := range es {
|
|
e.elems = es[0].elems
|
|
}
|
|
e := es[0]
|
|
for i := n - 1; i >= 0; i-- {
|
|
e, _ = e.nextIndexed()
|
|
if e.runes[0] != rune(perm[i]) {
|
|
t.Errorf("%d:%d: expected entry %X; found %X", perm, i, orig[i].runes, e.runes)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
type entryLessTest struct {
|
|
a, b *entry
|
|
res bool
|
|
}
|
|
|
|
var (
|
|
w1 = []rawCE{{w: []int{100, 20, 5, 5}}}
|
|
w2 = []rawCE{{w: []int{101, 20, 5, 5}}}
|
|
)
|
|
|
|
var entryLessTests = []entryLessTest{
|
|
{&entry{str: "a", elems: w1},
|
|
&entry{str: "a", elems: w1},
|
|
false,
|
|
},
|
|
{&entry{str: "a", elems: w1},
|
|
&entry{str: "a", elems: w2},
|
|
true,
|
|
},
|
|
{&entry{str: "a", elems: w1},
|
|
&entry{str: "b", elems: w1},
|
|
true,
|
|
},
|
|
{&entry{str: "a", elems: w2},
|
|
&entry{str: "a", elems: w1},
|
|
false,
|
|
},
|
|
{&entry{str: "c", elems: w1},
|
|
&entry{str: "b", elems: w1},
|
|
false,
|
|
},
|
|
{&entry{str: "a", elems: w1, logical: firstAnchor},
|
|
&entry{str: "a", elems: w1},
|
|
true,
|
|
},
|
|
{&entry{str: "a", elems: w1},
|
|
&entry{str: "b", elems: w1, logical: firstAnchor},
|
|
false,
|
|
},
|
|
{&entry{str: "b", elems: w1},
|
|
&entry{str: "a", elems: w1, logical: lastAnchor},
|
|
true,
|
|
},
|
|
{&entry{str: "a", elems: w1, logical: lastAnchor},
|
|
&entry{str: "c", elems: w1},
|
|
false,
|
|
},
|
|
}
|
|
|
|
func TestEntryLess(t *testing.T) {
|
|
for i, tt := range entryLessTests {
|
|
if res := entryLess(tt.a, tt.b); res != tt.res {
|
|
t.Errorf("%d: was %v; want %v", i, res, tt.res)
|
|
}
|
|
}
|
|
}
|