1 // Copyright 2015 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.
15 "golang.org/x/text/internal/gen"
16 "golang.org/x/text/internal/testtext"
17 "golang.org/x/text/internal/ucd"
18 "golang.org/x/text/unicode/norm"
21 var testLevels = flag.Bool("levels", false, "enable testing of levels")
23 // TestBidiCore performs the tests in BidiTest.txt.
24 // See http://www.unicode.org/Public/UCD/latest/ucd/BidiTest.txt.
25 func TestBidiCore(t *testing.T) {
26 testtext.SkipIfNotLong(t)
28 r := gen.OpenUCDFile("BidiTest.txt")
31 var wantLevels, wantOrder []string
32 p := ucd.New(r, ucd.Part(func(p *ucd.Parser) {
33 s := strings.Split(p.String(0), ":")
36 wantLevels = strings.Fields(s[1])
38 wantOrder = strings.Fields(s[1])
40 log.Fatalf("Unknown part %q.", s[0])
46 for _, s := range p.Strings(0) {
47 types = append(types, bidiClass[s])
49 // We ignore the bracketing part of the algorithm.
50 pairTypes := make([]bracketType, len(types))
51 pairValues := make([]rune, len(types))
53 for i := uint(0); i < 3; i++ {
54 if p.Uint(1)&(1<<i) == 0 {
57 lev := level(int(i) - 1)
58 par := newParagraph(types, pairTypes, pairValues, lev)
61 levels := par.getLevels([]int{len(types)})
62 for i, s := range wantLevels {
66 l, _ := strconv.ParseUint(s, 10, 8)
67 if level(l)&1 != levels[i]&1 {
68 t.Errorf("%s:%d:levels: got %v; want %v", p.String(0), lev, levels, wantLevels)
74 order := par.getReordering([]int{len(types)})
75 gotOrder := filterOrder(types, order)
76 if got, want := fmt.Sprint(gotOrder), fmt.Sprint(wantOrder); got != want {
77 t.Errorf("%s:%d:order: got %v; want %v\noriginal %v", p.String(0), lev, got, want, order)
81 if err := p.Err(); err != nil {
86 var removeClasses = map[Class]bool{
95 // TestBidiCharacters performs the tests in BidiCharacterTest.txt.
96 // See http://www.unicode.org/Public/UCD/latest/ucd/BidiCharacterTest.txt
97 func TestBidiCharacters(t *testing.T) {
98 testtext.SkipIfNotLong(t)
100 ucd.Parse(gen.OpenUCDFile("BidiCharacterTest.txt"), func(p *ucd.Parser) {
103 pairTypes []bracketType
107 wantLevel = level(p.Int(2))
108 wantLevels = p.Strings(3)
109 wantVisualOrder = p.Strings(4)
112 switch l := p.Int(1); l {
116 parLevel = implicitLevel
118 // Spec says to ignore unknown parts.
123 for _, r := range runes {
124 // Assign the bracket type.
125 if d := norm.NFKD.PropertiesString(string(r)).Decomposition(); d != nil {
126 r = []rune(string(d))[0]
128 p, _ := LookupRune(r)
130 // Assign the class for this rune.
131 types = append(types, p.Class())
135 pairTypes = append(pairTypes, bpNone)
136 pairValues = append(pairValues, 0)
137 case p.IsOpeningBracket():
138 pairTypes = append(pairTypes, bpOpen)
139 pairValues = append(pairValues, r)
141 pairTypes = append(pairTypes, bpClose)
142 pairValues = append(pairValues, p.reverseBracket(r))
145 par := newParagraph(types, pairTypes, pairValues, parLevel)
148 if got := par.embeddingLevel; got != wantLevel {
149 t.Errorf("%v:level: got %d; want %d", string(runes), got, wantLevel)
153 gotLevels := getLevelStrings(types, par.getLevels([]int{len(types)}))
154 if got, want := fmt.Sprint(gotLevels), fmt.Sprint(wantLevels); got != want {
155 t.Errorf("%04X %q:%d: got %v; want %v\nval: %x\npair: %v", runes, string(runes), parLevel, got, want, pairValues, pairTypes)
159 order := par.getReordering([]int{len(types)})
160 order = filterOrder(types, order)
161 if got, want := fmt.Sprint(order), fmt.Sprint(wantVisualOrder); got != want {
162 t.Errorf("%04X %q:%d: got %v; want %v\ngot order: %s", runes, string(runes), parLevel, got, want, reorder(runes, order))
167 func getLevelStrings(cl []Class, levels []level) []string {
169 for i, l := range levels {
170 if !removeClasses[cl[i]] {
171 results = append(results, fmt.Sprint(l))
173 results = append(results, "x")
179 func filterOrder(cl []Class, order []int) []int {
181 for _, o := range order {
182 if !removeClasses[cl[o]] {
189 func reorder(r []rune, order []int) string {
190 nr := make([]rune, len(order))
191 for i, o := range order {
197 // bidiClass names and codes taken from class "bc" in
198 // http://www.unicode.org/Public/8.0.0/ucd/PropertyValueAliases.txt
199 var bidiClass = map[string]Class{
200 "AL": AL, // classArabicLetter,
201 "AN": AN, // classArabicNumber,
202 "B": B, // classParagraphSeparator,
203 "BN": BN, // classBoundaryNeutral,
204 "CS": CS, // classCommonSeparator,
205 "EN": EN, // classEuropeanNumber,
206 "ES": ES, // classEuropeanSeparator,
207 "ET": ET, // classEuropeanTerminator,
208 "L": L, // classLeftToRight,
209 "NSM": NSM, // classNonspacingMark,
210 "ON": ON, // classOtherNeutral,
211 "R": R, // classRightToLeft,
212 "S": S, // classSegmentSeparator,
213 "WS": WS, // classWhiteSpace,
215 "LRO": LRO, // classLeftToRightOverride,
216 "RLO": RLO, // classRightToLeftOverride,
217 "LRE": LRE, // classLeftToRightEmbedding,
218 "RLE": RLE, // classRightToLeftEmbedding,
219 "PDF": PDF, // classPopDirectionalFormat,
220 "LRI": LRI, // classLeftToRightIsolate,
221 "RLI": RLI, // classRightToLeftIsolate,
222 "FSI": FSI, // classFirstStrongIsolate,
223 "PDI": PDI, // classPopDirectionalIsolate,