github.com/go-xe2/third@v1.0.3/golang.org/x/text/unicode/bidi/core_test.go (about) 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 "github.com/go-xe2/third/golang.org/x/text/internal/gen" 16 "github.com/go-xe2/third/golang.org/x/text/internal/testtext" 17 "github.com/go-xe2/third/golang.org/x/text/internal/ucd" 18 "github.com/go-xe2/third/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 }