OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / text / unicode / bidi / core_test.go
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.
4
5 package bidi
6
7 import (
8         "flag"
9         "fmt"
10         "log"
11         "strconv"
12         "strings"
13         "testing"
14
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"
19 )
20
21 var testLevels = flag.Bool("levels", false, "enable testing of levels")
22
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)
27
28         r := gen.OpenUCDFile("BidiTest.txt")
29         defer r.Close()
30
31         var wantLevels, wantOrder []string
32         p := ucd.New(r, ucd.Part(func(p *ucd.Parser) {
33                 s := strings.Split(p.String(0), ":")
34                 switch s[0] {
35                 case "Levels":
36                         wantLevels = strings.Fields(s[1])
37                 case "Reorder":
38                         wantOrder = strings.Fields(s[1])
39                 default:
40                         log.Fatalf("Unknown part %q.", s[0])
41                 }
42         }))
43
44         for p.Next() {
45                 types := []Class{}
46                 for _, s := range p.Strings(0) {
47                         types = append(types, bidiClass[s])
48                 }
49                 // We ignore the bracketing part of the algorithm.
50                 pairTypes := make([]bracketType, len(types))
51                 pairValues := make([]rune, len(types))
52
53                 for i := uint(0); i < 3; i++ {
54                         if p.Uint(1)&(1<<i) == 0 {
55                                 continue
56                         }
57                         lev := level(int(i) - 1)
58                         par := newParagraph(types, pairTypes, pairValues, lev)
59
60                         if *testLevels {
61                                 levels := par.getLevels([]int{len(types)})
62                                 for i, s := range wantLevels {
63                                         if s == "x" {
64                                                 continue
65                                         }
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)
69                                                 break
70                                         }
71                                 }
72                         }
73
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)
78                         }
79                 }
80         }
81         if err := p.Err(); err != nil {
82                 log.Fatal(err)
83         }
84 }
85
86 var removeClasses = map[Class]bool{
87         LRO: true,
88         RLO: true,
89         RLE: true,
90         LRE: true,
91         PDF: true,
92         BN:  true,
93 }
94
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)
99
100         ucd.Parse(gen.OpenUCDFile("BidiCharacterTest.txt"), func(p *ucd.Parser) {
101                 var (
102                         types      []Class
103                         pairTypes  []bracketType
104                         pairValues []rune
105                         parLevel   level
106
107                         wantLevel       = level(p.Int(2))
108                         wantLevels      = p.Strings(3)
109                         wantVisualOrder = p.Strings(4)
110                 )
111
112                 switch l := p.Int(1); l {
113                 case 0, 1:
114                         parLevel = level(l)
115                 case 2:
116                         parLevel = implicitLevel
117                 default:
118                         // Spec says to ignore unknown parts.
119                 }
120
121                 runes := p.Runes(0)
122
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]
127                         }
128                         p, _ := LookupRune(r)
129
130                         // Assign the class for this rune.
131                         types = append(types, p.Class())
132
133                         switch {
134                         case !p.IsBracket():
135                                 pairTypes = append(pairTypes, bpNone)
136                                 pairValues = append(pairValues, 0)
137                         case p.IsOpeningBracket():
138                                 pairTypes = append(pairTypes, bpOpen)
139                                 pairValues = append(pairValues, r)
140                         default:
141                                 pairTypes = append(pairTypes, bpClose)
142                                 pairValues = append(pairValues, p.reverseBracket(r))
143                         }
144                 }
145                 par := newParagraph(types, pairTypes, pairValues, parLevel)
146
147                 // Test results:
148                 if got := par.embeddingLevel; got != wantLevel {
149                         t.Errorf("%v:level: got %d; want %d", string(runes), got, wantLevel)
150                 }
151
152                 if *testLevels {
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)
156                         }
157                 }
158
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))
163                 }
164         })
165 }
166
167 func getLevelStrings(cl []Class, levels []level) []string {
168         var results []string
169         for i, l := range levels {
170                 if !removeClasses[cl[i]] {
171                         results = append(results, fmt.Sprint(l))
172                 } else {
173                         results = append(results, "x")
174                 }
175         }
176         return results
177 }
178
179 func filterOrder(cl []Class, order []int) []int {
180         no := []int{}
181         for _, o := range order {
182                 if !removeClasses[cl[o]] {
183                         no = append(no, o)
184                 }
185         }
186         return no
187 }
188
189 func reorder(r []rune, order []int) string {
190         nr := make([]rune, len(order))
191         for i, o := range order {
192                 nr[i] = r[o]
193         }
194         return string(nr)
195 }
196
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,
214
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,
224 }