github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/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 "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.resultLevels 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 trie := newBidiTrie(0) 122 runes := p.Runes(0) 123 124 for _, r := range runes { 125 // Assign the bracket type. 126 if d := norm.NFKD.PropertiesString(string(r)).Decomposition(); d != nil { 127 r = []rune(string(d))[0] 128 } 129 e, _ := trie.lookupString(string(r)) 130 entry := entry(e) 131 132 // Assign the class for this rune. 133 types = append(types, entry.class(r)) 134 135 switch { 136 case !entry.isBracket(): 137 pairTypes = append(pairTypes, bpNone) 138 pairValues = append(pairValues, 0) 139 case entry.isOpen(): 140 pairTypes = append(pairTypes, bpOpen) 141 pairValues = append(pairValues, r) 142 default: 143 pairTypes = append(pairTypes, bpClose) 144 pairValues = append(pairValues, entry.reverseBracket(r)) 145 } 146 } 147 par := newParagraph(types, pairTypes, pairValues, parLevel) 148 149 // Test results: 150 if got := par.embeddingLevel; got != wantLevel { 151 t.Errorf("%v:level: got %d; want %d", string(runes), got, wantLevel) 152 } 153 154 if *testLevels { 155 gotLevels := getLevelStrings(types, par.resultLevels) 156 if got, want := fmt.Sprint(gotLevels), fmt.Sprint(wantLevels); got != want { 157 t.Errorf("%04X %q:%d: got %v; want %v\nval: %x\npair: %v", runes, string(runes), parLevel, got, want, pairValues, pairTypes) 158 } 159 } 160 161 order := par.getReordering([]int{len(types)}) 162 order = filterOrder(types, order) 163 if got, want := fmt.Sprint(order), fmt.Sprint(wantVisualOrder); got != want { 164 t.Errorf("%04X %q:%d: got %v; want %v\ngot order: %s", runes, string(runes), parLevel, got, want, reorder(runes, order)) 165 } 166 }) 167 } 168 169 func getLevelStrings(cl []class, levels []level) []string { 170 var results []string 171 for i, l := range levels { 172 if !removeClasses[cl[i]] { 173 results = append(results, fmt.Sprint(l)) 174 } else { 175 results = append(results, "x") 176 } 177 } 178 return results 179 } 180 181 func filterOrder(cl []class, order []int) []int { 182 no := []int{} 183 for _, o := range order { 184 if !removeClasses[cl[o]] { 185 no = append(no, o) 186 } 187 } 188 return no 189 } 190 191 func reorder(r []rune, order []int) string { 192 nr := make([]rune, len(order)) 193 for i, o := range order { 194 nr[i] = r[o] 195 } 196 return string(nr) 197 } 198 199 // bidiClass names and codes taken from class "bc" in 200 // http://www.unicode.org/Public/8.0.0/ucd/PropertyValueAliases.txt 201 var bidiClass = map[string]class{ 202 "AL": _AL, // classArabicLetter, 203 "AN": _AN, // classArabicNumber, 204 "B": _B, // classParagraphSeparator, 205 "BN": _BN, // classBoundaryNeutral, 206 "CS": _CS, // classCommonSeparator, 207 "EN": _EN, // classEuropeanNumber, 208 "ES": _ES, // classEuropeanSeparator, 209 "ET": _ET, // classEuropeanTerminator, 210 "L": _L, // classLeftToRight, 211 "NSM": _NSM, // classNonspacingMark, 212 "ON": _ON, // classOtherNeutral, 213 "R": _R, // classRightToLeft, 214 "S": _S, // classSegmentSeparator, 215 "WS": _WS, // classWhiteSpace, 216 217 "LRO": _LRO, // classLeftToRightOverride, 218 "RLO": _RLO, // classRightToLeftOverride, 219 "LRE": _LRE, // classLeftToRightEmbedding, 220 "RLE": _RLE, // classRightToLeftEmbedding, 221 "PDF": _PDF, // classPopDirectionalFormat, 222 "LRI": _LRI, // classLeftToRightIsolate, 223 "RLI": _RLI, // classRightToLeftIsolate, 224 "FSI": _FSI, // classFirstStrongIsolate, 225 "PDI": _PDI, // classPopDirectionalIsolate, 226 }