github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/text/width/transform_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 width 6 7 import ( 8 "bytes" 9 "testing" 10 11 "golang.org/x/text/internal/testtext" 12 "golang.org/x/text/transform" 13 ) 14 15 func foldRune(r rune) (folded rune, ok bool) { 16 alt, ok := mapRunes[r] 17 if ok && alt.e&tagNeedsFold != 0 { 18 return alt.r, true 19 } 20 return r, false 21 } 22 23 func widenRune(r rune) (wide rune, ok bool) { 24 alt, ok := mapRunes[r] 25 if k := alt.e.kind(); k == EastAsianHalfwidth || k == EastAsianNarrow { 26 return alt.r, true 27 } 28 return r, false 29 } 30 31 func narrowRune(r rune) (narrow rune, ok bool) { 32 alt, ok := mapRunes[r] 33 if k := alt.e.kind(); k == EastAsianFullwidth || k == EastAsianWide || k == EastAsianAmbiguous { 34 return alt.r, true 35 } 36 return r, false 37 } 38 39 func TestFoldSingleRunes(t *testing.T) { 40 for r := rune(0); r < 0x1FFFF; r++ { 41 if loSurrogate <= r && r <= hiSurrogate { 42 continue 43 } 44 x, _ := foldRune(r) 45 want := string(x) 46 got := Fold.String(string(r)) 47 if got != want { 48 t.Errorf("Fold().String(%U) = %+q; want %+q", r, got, want) 49 } 50 } 51 } 52 53 func TestFold(t *testing.T) { 54 for _, tc := range []struct { 55 desc string 56 src string 57 nDst int 58 atEOF bool 59 dst string 60 nSrc int 61 err error 62 }{{ 63 desc: "empty", 64 src: "", 65 dst: "", 66 nDst: 10, 67 nSrc: 0, 68 atEOF: false, 69 err: nil, 70 }, { 71 desc: "short source 1", 72 src: "a\xc2", 73 dst: "a", 74 nDst: 10, 75 nSrc: 1, 76 atEOF: false, 77 err: transform.ErrShortSrc, 78 }, { 79 desc: "short source 2", 80 src: "a\xe0\x80", 81 dst: "a", 82 nDst: 10, 83 nSrc: 1, 84 atEOF: false, 85 err: transform.ErrShortSrc, 86 }, { 87 desc: "incomplete but terminated source 1", 88 src: "a\xc2", 89 dst: "a\xc2", 90 nDst: 10, 91 nSrc: 2, 92 atEOF: true, 93 err: nil, 94 }, { 95 desc: "incomplete but terminated source 2", 96 src: "a\xe0\x80", 97 dst: "a\xe0\x80", 98 nDst: 10, 99 nSrc: 3, 100 atEOF: true, 101 err: nil, 102 }, { 103 desc: "exact fit dst", 104 src: "a\uff01", 105 dst: "a!", 106 nDst: 2, 107 nSrc: 4, 108 atEOF: false, 109 err: nil, 110 }, { 111 desc: "short dst 1", 112 src: "a\uffe0", 113 dst: "a", 114 nDst: 2, 115 nSrc: 1, 116 atEOF: false, 117 err: transform.ErrShortDst, 118 }, { 119 desc: "short dst 2", 120 src: "不夠", 121 dst: "不", 122 nDst: 3, 123 nSrc: 3, 124 atEOF: true, 125 err: transform.ErrShortDst, 126 }, { 127 desc: "short dst fast path", 128 src: "fast", 129 dst: "fas", 130 nDst: 3, 131 nSrc: 3, 132 atEOF: true, 133 err: transform.ErrShortDst, 134 }, { 135 desc: "fast path alternation", 136 src: "fast路徑fast路徑", 137 dst: "fast路徑fast路徑", 138 nDst: 20, 139 nSrc: 20, 140 atEOF: true, 141 err: nil, 142 }} { 143 b := make([]byte, tc.nDst) 144 nDst, nSrc, err := Fold.Transform(b, []byte(tc.src), tc.atEOF) 145 if got := string(b[:nDst]); got != tc.dst { 146 t.Errorf("%s: dst was %+q; want %+q", tc.desc, got, tc.dst) 147 } 148 if nSrc != tc.nSrc { 149 t.Errorf("%s: nSrc was %d; want %d", tc.desc, nSrc, tc.nSrc) 150 } 151 if err != tc.err { 152 t.Errorf("%s: error was %v; want %v", tc.desc, err, tc.err) 153 } 154 } 155 } 156 157 func TestWidenSingleRunes(t *testing.T) { 158 for r := rune(0); r < 0x1FFFF; r++ { 159 if loSurrogate <= r && r <= hiSurrogate { 160 continue 161 } 162 alt, _ := widenRune(r) 163 want := string(alt) 164 got := Widen.String(string(r)) 165 if got != want { 166 t.Errorf("Widen().String(%U) = %+q; want %+q", r, got, want) 167 } 168 } 169 } 170 171 func TestWiden(t *testing.T) { 172 for _, tc := range []struct { 173 desc string 174 src string 175 nDst int 176 atEOF bool 177 dst string 178 nSrc int 179 err error 180 }{{ 181 desc: "empty", 182 src: "", 183 dst: "", 184 nDst: 10, 185 nSrc: 0, 186 atEOF: false, 187 err: nil, 188 }, { 189 desc: "short source 1", 190 src: "a\xc2", 191 dst: "a", 192 nDst: 10, 193 nSrc: 1, 194 atEOF: false, 195 err: transform.ErrShortSrc, 196 }, { 197 desc: "short source 2", 198 src: "a\xe0\x80", 199 dst: "a", 200 nDst: 10, 201 nSrc: 1, 202 atEOF: false, 203 err: transform.ErrShortSrc, 204 }, { 205 desc: "incomplete but terminated source 1", 206 src: "a\xc2", 207 dst: "a\xc2", 208 nDst: 10, 209 nSrc: 2, 210 atEOF: true, 211 err: nil, 212 }, { 213 desc: "incomplete but terminated source 2", 214 src: "a\xe0\x80", 215 dst: "a\xe0\x80", 216 nDst: 10, 217 nSrc: 3, 218 atEOF: true, 219 err: nil, 220 }, { 221 desc: "exact fit dst", 222 src: "a!", 223 dst: "a\uff01", 224 nDst: 6, 225 nSrc: 2, 226 atEOF: false, 227 err: nil, 228 }, { 229 desc: "short dst 1", 230 src: "a\uffe0", 231 dst: "a", 232 nDst: 4, 233 nSrc: 1, 234 atEOF: false, 235 err: transform.ErrShortDst, 236 }, { 237 desc: "short dst 2", 238 src: "不夠", 239 dst: "不", 240 nDst: 3, 241 nSrc: 3, 242 atEOF: true, 243 err: transform.ErrShortDst, 244 }, { 245 desc: "short dst ascii", 246 src: "ascii", 247 dst: "\uff41", 248 nDst: 3, 249 nSrc: 1, 250 atEOF: true, 251 err: transform.ErrShortDst, 252 }, { 253 desc: "ambiguous", 254 src: "\uffe9", 255 dst: "\u2190", 256 nDst: 4, 257 nSrc: 3, 258 atEOF: false, 259 err: nil, 260 }} { 261 b := make([]byte, tc.nDst) 262 nDst, nSrc, err := Widen.Transform(b, []byte(tc.src), tc.atEOF) 263 if got := string(b[:nDst]); got != tc.dst { 264 t.Errorf("%s: dst was %+q; want %+q", tc.desc, got, tc.dst) 265 } 266 if nSrc != tc.nSrc { 267 t.Errorf("%s: nSrc was %d; want %d", tc.desc, nSrc, tc.nSrc) 268 } 269 if err != tc.err { 270 t.Errorf("%s: error was %v; want %v", tc.desc, err, tc.err) 271 } 272 } 273 } 274 275 func TestNarrowSingleRunes(t *testing.T) { 276 for r := rune(0); r < 0x1FFFF; r++ { 277 if loSurrogate <= r && r <= hiSurrogate { 278 continue 279 } 280 alt, _ := narrowRune(r) 281 want := string(alt) 282 got := Narrow.String(string(r)) 283 if got != want { 284 t.Errorf("Narrow().String(%U) = %+q; want %+q", r, got, want) 285 } 286 } 287 } 288 289 func TestNarrow(t *testing.T) { 290 for _, tc := range []struct { 291 desc string 292 src string 293 nDst int 294 atEOF bool 295 dst string 296 nSrc int 297 err error 298 }{{ 299 desc: "empty", 300 src: "", 301 dst: "", 302 nDst: 10, 303 nSrc: 0, 304 atEOF: false, 305 err: nil, 306 }, { 307 desc: "short source 1", 308 src: "a\xc2", 309 dst: "a", 310 nDst: 10, 311 nSrc: 1, 312 atEOF: false, 313 err: transform.ErrShortSrc, 314 }, { 315 desc: "short source 2", 316 src: "a\xe0\x80", 317 dst: "a", 318 nDst: 10, 319 nSrc: 3, 320 atEOF: false, 321 err: transform.ErrShortSrc, 322 }, { 323 desc: "incomplete but terminated source 1", 324 src: "a\xc2", 325 dst: "a\xc2", 326 nDst: 10, 327 nSrc: 4, 328 atEOF: true, 329 err: nil, 330 }, { 331 desc: "incomplete but terminated source 2", 332 src: "a\xe0\x80", 333 dst: "a\xe0\x80", 334 nDst: 10, 335 nSrc: 5, 336 atEOF: true, 337 err: nil, 338 }, { 339 desc: "exact fit dst", 340 src: "a\uff01", 341 dst: "a!", 342 nDst: 2, 343 nSrc: 6, 344 atEOF: false, 345 err: nil, 346 }, { 347 desc: "short dst 1", 348 src: "a\uffe0", 349 dst: "a", 350 nDst: 2, 351 nSrc: 3, 352 atEOF: false, 353 err: transform.ErrShortDst, 354 }, { 355 desc: "short dst 2", 356 src: "不夠", 357 dst: "不", 358 nDst: 3, 359 nSrc: 3, 360 atEOF: true, 361 err: transform.ErrShortDst, 362 }, { 363 // Create a narrow variant of ambiguous runes, if they exist. 364 desc: "ambiguous", 365 src: "\u2190", 366 dst: "\uffe9", 367 nDst: 4, 368 nSrc: 3, 369 atEOF: false, 370 err: nil, 371 }, { 372 desc: "short dst fast path", 373 src: "fast", 374 dst: "fas", 375 nDst: 3, 376 nSrc: 3, 377 atEOF: true, 378 err: transform.ErrShortDst, 379 }, { 380 desc: "fast path alternation", 381 src: "fast路徑fast路徑", 382 dst: "fast路徑fast路徑", 383 nDst: 20, 384 nSrc: 20, 385 atEOF: true, 386 err: nil, 387 }} { 388 b := make([]byte, tc.nDst) 389 nDst, nSrc, err := Narrow.Transform(b, []byte(tc.src), tc.atEOF) 390 if got := string(b[:nDst]); got != tc.dst { 391 t.Errorf("%s: dst was %+q; want %+q", tc.desc, got, tc.dst) 392 } 393 if nSrc != tc.nSrc { 394 t.Errorf("%s: nSrc was %d; want %d", tc.desc, nSrc, tc.nSrc) 395 } 396 if err != tc.err { 397 t.Errorf("%s: error was %v; want %v", tc.desc, err, tc.err) 398 } 399 } 400 } 401 func bench(b *testing.B, t Transformer, s string) { 402 dst := make([]byte, 1024) 403 src := []byte(s) 404 b.SetBytes(int64(len(src))) 405 b.ResetTimer() 406 for i := 0; i < b.N; i++ { 407 t.Transform(dst, src, true) 408 } 409 } 410 411 func changingRunes(f func(r rune) (rune, bool)) string { 412 buf := &bytes.Buffer{} 413 for r := rune(0); r <= 0xFFFF; r++ { 414 if _, ok := foldRune(r); ok { 415 buf.WriteRune(r) 416 } 417 } 418 return buf.String() 419 } 420 421 func BenchmarkFoldASCII(b *testing.B) { 422 bench(b, Fold, testtext.ASCII) 423 } 424 425 func BenchmarkFoldCJK(b *testing.B) { 426 bench(b, Fold, testtext.CJK) 427 } 428 429 func BenchmarkFoldNonCanonical(b *testing.B) { 430 bench(b, Fold, changingRunes(foldRune)) 431 } 432 433 func BenchmarkFoldOther(b *testing.B) { 434 bench(b, Fold, testtext.TwoByteUTF8+testtext.ThreeByteUTF8) 435 } 436 437 func BenchmarkWideASCII(b *testing.B) { 438 bench(b, Widen, testtext.ASCII) 439 } 440 441 func BenchmarkWideCJK(b *testing.B) { 442 bench(b, Widen, testtext.CJK) 443 } 444 445 func BenchmarkWideNonCanonical(b *testing.B) { 446 bench(b, Widen, changingRunes(widenRune)) 447 } 448 449 func BenchmarkWideOther(b *testing.B) { 450 bench(b, Widen, testtext.TwoByteUTF8+testtext.ThreeByteUTF8) 451 } 452 453 func BenchmarkNarrowASCII(b *testing.B) { 454 bench(b, Narrow, testtext.ASCII) 455 } 456 457 func BenchmarkNarrowCJK(b *testing.B) { 458 bench(b, Narrow, testtext.CJK) 459 } 460 461 func BenchmarkNarrowNonCanonical(b *testing.B) { 462 bench(b, Narrow, changingRunes(narrowRune)) 463 } 464 465 func BenchmarkNarrowOther(b *testing.B) { 466 bench(b, Narrow, testtext.TwoByteUTF8+testtext.ThreeByteUTF8) 467 }