| // 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 colltab |
| |
| import ( |
| "fmt" |
| "testing" |
| "unicode" |
| ) |
| |
| func (e Elem) String() string { |
| q := "" |
| if v := e.Quaternary(); v == MaxQuaternary { |
| q = "max" |
| } else { |
| q = fmt.Sprint(v) |
| } |
| return fmt.Sprintf("[%d, %d, %d, %s]", |
| e.Primary(), |
| e.Secondary(), |
| e.Tertiary(), |
| q) |
| } |
| |
| type ceTest struct { |
| f func(inout []int) (Elem, ceType) |
| arg []int |
| } |
| |
| func makeCE(weights []int) Elem { |
| ce, _ := MakeElem(weights[0], weights[1], weights[2], uint8(weights[3])) |
| return ce |
| } |
| |
| var defaultValues = []int{0, defaultSecondary, defaultTertiary, 0} |
| |
| func e(w ...int) Elem { |
| return makeCE(append(w, defaultValues[len(w):]...)) |
| } |
| |
| func makeContractIndex(index, n, offset int) Elem { |
| const ( |
| contractID = 0xC0000000 |
| maxNBits = 4 |
| maxTrieIndexBits = 12 |
| maxContractOffsetBits = 13 |
| ) |
| ce := Elem(contractID) |
| ce += Elem(offset << (maxNBits + maxTrieIndexBits)) |
| ce += Elem(index << maxNBits) |
| ce += Elem(n) |
| return ce |
| } |
| |
| func makeExpandIndex(index int) Elem { |
| const expandID = 0xE0000000 |
| return expandID + Elem(index) |
| } |
| |
| func makeDecompose(t1, t2 int) Elem { |
| const decompID = 0xF0000000 |
| return Elem(t2<<8+t1) + decompID |
| } |
| |
| func normalCE(inout []int) (ce Elem, t ceType) { |
| ce = makeCE(inout) |
| inout[0] = ce.Primary() |
| inout[1] = ce.Secondary() |
| inout[2] = int(ce.Tertiary()) |
| inout[3] = int(ce.CCC()) |
| return ce, ceNormal |
| } |
| |
| func expandCE(inout []int) (ce Elem, t ceType) { |
| ce = makeExpandIndex(inout[0]) |
| inout[0] = splitExpandIndex(ce) |
| return ce, ceExpansionIndex |
| } |
| |
| func contractCE(inout []int) (ce Elem, t ceType) { |
| ce = makeContractIndex(inout[0], inout[1], inout[2]) |
| i, n, o := splitContractIndex(ce) |
| inout[0], inout[1], inout[2] = i, n, o |
| return ce, ceContractionIndex |
| } |
| |
| func decompCE(inout []int) (ce Elem, t ceType) { |
| ce = makeDecompose(inout[0], inout[1]) |
| t1, t2 := splitDecompose(ce) |
| inout[0], inout[1] = int(t1), int(t2) |
| return ce, ceDecompose |
| } |
| |
| var ceTests = []ceTest{ |
| {normalCE, []int{0, 0, 0, 0}}, |
| {normalCE, []int{0, 30, 3, 0}}, |
| {normalCE, []int{0, 30, 3, 0xFF}}, |
| {normalCE, []int{100, defaultSecondary, defaultTertiary, 0}}, |
| {normalCE, []int{100, defaultSecondary, defaultTertiary, 0xFF}}, |
| {normalCE, []int{100, defaultSecondary, 3, 0}}, |
| {normalCE, []int{0x123, defaultSecondary, 8, 0xFF}}, |
| |
| {contractCE, []int{0, 0, 0}}, |
| {contractCE, []int{1, 1, 1}}, |
| {contractCE, []int{1, (1 << maxNBits) - 1, 1}}, |
| {contractCE, []int{(1 << maxTrieIndexBits) - 1, 1, 1}}, |
| {contractCE, []int{1, 1, (1 << maxContractOffsetBits) - 1}}, |
| |
| {expandCE, []int{0}}, |
| {expandCE, []int{5}}, |
| {expandCE, []int{(1 << maxExpandIndexBits) - 1}}, |
| |
| {decompCE, []int{0, 0}}, |
| {decompCE, []int{1, 1}}, |
| {decompCE, []int{0x1F, 0x1F}}, |
| } |
| |
| func TestColElem(t *testing.T) { |
| for i, tt := range ceTests { |
| inout := make([]int, len(tt.arg)) |
| copy(inout, tt.arg) |
| ce, typ := tt.f(inout) |
| if ce.ctype() != typ { |
| t.Errorf("%d: type is %d; want %d (ColElem: %X)", i, ce.ctype(), typ, ce) |
| } |
| for j, a := range tt.arg { |
| if inout[j] != a { |
| t.Errorf("%d: argument %d is %X; want %X (ColElem: %X)", i, j, inout[j], a, ce) |
| } |
| } |
| } |
| } |
| |
| type implicitTest struct { |
| r rune |
| p int |
| } |
| |
| var implicitTests = []implicitTest{ |
| {0x33FF, 0x533FF}, |
| {0x3400, 0x23400}, |
| {0x4DC0, 0x54DC0}, |
| {0x4DFF, 0x54DFF}, |
| {0x4E00, 0x14E00}, |
| {0x9FCB, 0x19FCB}, |
| {0xA000, 0x5A000}, |
| {0xF8FF, 0x5F8FF}, |
| {0xF900, 0x1F900}, |
| {0xFA23, 0x1FA23}, |
| {0xFAD9, 0x1FAD9}, |
| {0xFB00, 0x5FB00}, |
| {0x20000, 0x40000}, |
| {0x2B81C, 0x4B81C}, |
| {unicode.MaxRune, 0x15FFFF}, // maximum primary value |
| } |
| |
| func TestImplicit(t *testing.T) { |
| for _, tt := range implicitTests { |
| if p := implicitPrimary(tt.r); p != tt.p { |
| t.Errorf("%U: was %X; want %X", tt.r, p, tt.p) |
| } |
| } |
| } |
| |
| func TestUpdateTertiary(t *testing.T) { |
| tests := []struct { |
| in, out Elem |
| t uint8 |
| }{ |
| {0x4000FE20, 0x0000FE8A, 0x0A}, |
| {0x4000FE21, 0x0000FEAA, 0x0A}, |
| {0x0000FE8B, 0x0000FE83, 0x03}, |
| {0x82FF0188, 0x9BFF0188, 0x1B}, |
| {0xAFF0CC02, 0xAFF0CC1B, 0x1B}, |
| } |
| for i, tt := range tests { |
| if out := tt.in.updateTertiary(tt.t); out != tt.out { |
| t.Errorf("%d: was %X; want %X", i, out, tt.out) |
| } |
| } |
| } |