summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/text/width/transform_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/text/width/transform_test.go')
-rw-r--r--vendor/golang.org/x/text/width/transform_test.go701
1 files changed, 701 insertions, 0 deletions
diff --git a/vendor/golang.org/x/text/width/transform_test.go b/vendor/golang.org/x/text/width/transform_test.go
new file mode 100644
index 0000000..f9122d6
--- /dev/null
+++ b/vendor/golang.org/x/text/width/transform_test.go
@@ -0,0 +1,701 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package width
+
+import (
+ "bytes"
+ "strings"
+ "testing"
+
+ "golang.org/x/text/internal/testtext"
+ "golang.org/x/text/transform"
+)
+
+func foldRune(r rune) (folded rune, ok bool) {
+ alt, ok := mapRunes[r]
+ if ok && alt.e&tagNeedsFold != 0 {
+ return alt.r, true
+ }
+ return r, false
+}
+
+func widenRune(r rune) (wide rune, ok bool) {
+ alt, ok := mapRunes[r]
+ if k := alt.e.kind(); k == EastAsianHalfwidth || k == EastAsianNarrow {
+ return alt.r, true
+ }
+ return r, false
+}
+
+func narrowRune(r rune) (narrow rune, ok bool) {
+ alt, ok := mapRunes[r]
+ if k := alt.e.kind(); k == EastAsianFullwidth || k == EastAsianWide || k == EastAsianAmbiguous {
+ return alt.r, true
+ }
+ return r, false
+}
+
+func TestFoldSingleRunes(t *testing.T) {
+ for r := rune(0); r < 0x1FFFF; r++ {
+ if loSurrogate <= r && r <= hiSurrogate {
+ continue
+ }
+ x, _ := foldRune(r)
+ want := string(x)
+ got := Fold.String(string(r))
+ if got != want {
+ t.Errorf("Fold().String(%U) = %+q; want %+q", r, got, want)
+ }
+ }
+}
+
+type transformTest struct {
+ desc string
+ src string
+ nBuf int
+ nDst int
+ atEOF bool
+ dst string
+ nSrc int
+ err error
+ nSpan int
+ errSpan error
+}
+
+func (tc *transformTest) doTest(t *testing.T, tr Transformer) {
+ testtext.Run(t, tc.desc, func(t *testing.T) {
+ b := make([]byte, tc.nBuf)
+ nDst, nSrc, err := tr.Transform(b, []byte(tc.src), tc.atEOF)
+ if got := string(b[:nDst]); got != tc.dst[:nDst] {
+ t.Errorf("dst was %+q; want %+q", got, tc.dst)
+ }
+ if nDst != tc.nDst {
+ t.Errorf("nDst was %d; want %d", nDst, tc.nDst)
+ }
+ if nSrc != tc.nSrc {
+ t.Errorf("nSrc was %d; want %d", nSrc, tc.nSrc)
+ }
+ if err != tc.err {
+ t.Errorf("error was %v; want %v", err, tc.err)
+ }
+ if got := tr.String(tc.src); got != tc.dst {
+ t.Errorf("String(%q) = %q; want %q", tc.src, got, tc.dst)
+ }
+ n, err := tr.Span([]byte(tc.src), tc.atEOF)
+ if n != tc.nSpan || err != tc.errSpan {
+ t.Errorf("Span: got %d, %v; want %d, %v", n, err, tc.nSpan, tc.errSpan)
+ }
+ })
+}
+
+func TestFold(t *testing.T) {
+ for _, tc := range []transformTest{{
+ desc: "empty",
+ src: "",
+ nBuf: 10,
+ dst: "",
+ nDst: 0,
+ nSrc: 0,
+ atEOF: false,
+ err: nil,
+ nSpan: 0,
+ errSpan: nil,
+ }, {
+ desc: "short source 1",
+ src: "a\xc2",
+ nBuf: 10,
+ dst: "a\xc2",
+ nDst: 1,
+ nSrc: 1,
+ atEOF: false,
+ err: transform.ErrShortSrc,
+ nSpan: 1,
+ errSpan: transform.ErrShortSrc,
+ }, {
+ desc: "short source 2",
+ src: "a\xe0\x80",
+ nBuf: 10,
+ dst: "a\xe0\x80",
+ nDst: 1,
+ nSrc: 1,
+ atEOF: false,
+ err: transform.ErrShortSrc,
+ nSpan: 1,
+ errSpan: transform.ErrShortSrc,
+ }, {
+ desc: "incomplete but terminated source 1",
+ src: "a\xc2",
+ nBuf: 10,
+ dst: "a\xc2",
+ nDst: 2,
+ nSrc: 2,
+ atEOF: true,
+ err: nil,
+ nSpan: 2,
+ errSpan: nil,
+ }, {
+ desc: "incomplete but terminated source 2",
+ src: "a\xe0\x80",
+ nBuf: 10,
+ dst: "a\xe0\x80",
+ nDst: 3,
+ nSrc: 3,
+ atEOF: true,
+ err: nil,
+ nSpan: 3,
+ errSpan: nil,
+ }, {
+ desc: "exact fit dst",
+ src: "a\uff01",
+ nBuf: 2,
+ dst: "a!",
+ nDst: 2,
+ nSrc: 4,
+ atEOF: false,
+ err: nil,
+ nSpan: 1,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "exact fit dst and src ascii",
+ src: "ab",
+ nBuf: 2,
+ dst: "ab",
+ nDst: 2,
+ nSrc: 2,
+ atEOF: true,
+ err: nil,
+ nSpan: 2,
+ errSpan: nil,
+ }, {
+ desc: "empty dst",
+ src: "\u0300",
+ nBuf: 0,
+ dst: "\u0300",
+ nDst: 0,
+ nSrc: 0,
+ atEOF: true,
+ err: transform.ErrShortDst,
+ nSpan: 2,
+ errSpan: nil,
+ }, {
+ desc: "empty dst ascii",
+ src: "a",
+ nBuf: 0,
+ dst: "a",
+ nDst: 0,
+ nSrc: 0,
+ atEOF: true,
+ err: transform.ErrShortDst,
+ nSpan: 1,
+ errSpan: nil,
+ }, {
+ desc: "short dst 1",
+ src: "a\uffe0", // ¢
+ nBuf: 2,
+ dst: "a\u00a2", // ¢
+ nDst: 1,
+ nSrc: 1,
+ atEOF: false,
+ err: transform.ErrShortDst,
+ nSpan: 1,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "short dst 2",
+ src: "不夠",
+ nBuf: 3,
+ dst: "不夠",
+ nDst: 3,
+ nSrc: 3,
+ atEOF: true,
+ err: transform.ErrShortDst,
+ nSpan: 6,
+ errSpan: nil,
+ }, {
+ desc: "short dst fast path",
+ src: "fast",
+ nDst: 3,
+ dst: "fast",
+ nBuf: 3,
+ nSrc: 3,
+ atEOF: true,
+ err: transform.ErrShortDst,
+ nSpan: 4,
+ errSpan: nil,
+ }, {
+ desc: "short dst larger buffer",
+ src: "\uff21" + strings.Repeat("0", 127) + "B",
+ nBuf: 128,
+ dst: "A" + strings.Repeat("0", 127) + "B",
+ nDst: 128,
+ nSrc: 130,
+ atEOF: true,
+ err: transform.ErrShortDst,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "fast path alternation",
+ src: "fast路徑fast路徑",
+ nBuf: 20,
+ dst: "fast路徑fast路徑",
+ nDst: 20,
+ nSrc: 20,
+ atEOF: true,
+ err: nil,
+ nSpan: 20,
+ errSpan: nil,
+ }} {
+ tc.doTest(t, Fold)
+ }
+}
+
+func TestWidenSingleRunes(t *testing.T) {
+ for r := rune(0); r < 0x1FFFF; r++ {
+ if loSurrogate <= r && r <= hiSurrogate {
+ continue
+ }
+ alt, _ := widenRune(r)
+ want := string(alt)
+ got := Widen.String(string(r))
+ if got != want {
+ t.Errorf("Widen().String(%U) = %+q; want %+q", r, got, want)
+ }
+ }
+}
+
+func TestWiden(t *testing.T) {
+ for _, tc := range []transformTest{{
+ desc: "empty",
+ src: "",
+ nBuf: 10,
+ dst: "",
+ nDst: 0,
+ nSrc: 0,
+ atEOF: false,
+ err: nil,
+ nSpan: 0,
+ errSpan: nil,
+ }, {
+ desc: "short source 1",
+ src: "a\xc2",
+ nBuf: 10,
+ dst: "a\xc2",
+ nDst: 3,
+ nSrc: 1,
+ atEOF: false,
+ err: transform.ErrShortSrc,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "short source 2",
+ src: "a\xe0\x80",
+ nBuf: 10,
+ dst: "a\xe0\x80",
+ nDst: 3,
+ nSrc: 1,
+ atEOF: false,
+ err: transform.ErrShortSrc,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "incomplete but terminated source 1",
+ src: "a\xc2",
+ nBuf: 10,
+ dst: "a\xc2",
+ nDst: 4,
+ nSrc: 2,
+ atEOF: true,
+ err: nil,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "incomplete but terminated source 2",
+ src: "a\xe0\x80",
+ nBuf: 10,
+ dst: "a\xe0\x80",
+ nDst: 5,
+ nSrc: 3,
+ atEOF: true,
+ err: nil,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "short source 1 some span",
+ src: "a\xc2",
+ nBuf: 10,
+ dst: "a\xc2",
+ nDst: 3,
+ nSrc: 3,
+ atEOF: false,
+ err: transform.ErrShortSrc,
+ nSpan: 3,
+ errSpan: transform.ErrShortSrc,
+ }, {
+ desc: "short source 2 some span",
+ src: "a\xe0\x80",
+ nBuf: 10,
+ dst: "a\xe0\x80",
+ nDst: 3,
+ nSrc: 3,
+ atEOF: false,
+ err: transform.ErrShortSrc,
+ nSpan: 3,
+ errSpan: transform.ErrShortSrc,
+ }, {
+ desc: "incomplete but terminated source 1 some span",
+ src: "a\xc2",
+ nBuf: 10,
+ dst: "a\xc2",
+ nDst: 4,
+ nSrc: 4,
+ atEOF: true,
+ err: nil,
+ nSpan: 4,
+ errSpan: nil,
+ }, {
+ desc: "incomplete but terminated source 2 some span",
+ src: "a\xe0\x80",
+ nBuf: 10,
+ dst: "a\xe0\x80",
+ nDst: 5,
+ nSrc: 5,
+ atEOF: true,
+ err: nil,
+ nSpan: 5,
+ errSpan: nil,
+ }, {
+ desc: "exact fit dst",
+ src: "a!",
+ nBuf: 6,
+ dst: "a\uff01",
+ nDst: 6,
+ nSrc: 2,
+ atEOF: false,
+ err: nil,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "empty dst",
+ src: "\u0300",
+ nBuf: 0,
+ dst: "\u0300",
+ nDst: 0,
+ nSrc: 0,
+ atEOF: true,
+ err: transform.ErrShortDst,
+ nSpan: 2,
+ errSpan: nil,
+ }, {
+ desc: "empty dst ascii",
+ src: "a",
+ nBuf: 0,
+ dst: "a",
+ nDst: 0,
+ nSrc: 0,
+ atEOF: true,
+ err: transform.ErrShortDst,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "short dst 1",
+ src: "a\uffe0",
+ nBuf: 4,
+ dst: "a\uffe0",
+ nDst: 3,
+ nSrc: 1,
+ atEOF: false,
+ err: transform.ErrShortDst,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "short dst 2",
+ src: "不夠",
+ nBuf: 3,
+ dst: "不夠",
+ nDst: 3,
+ nSrc: 3,
+ atEOF: true,
+ err: transform.ErrShortDst,
+ nSpan: 6,
+ errSpan: nil,
+ }, {
+ desc: "short dst ascii",
+ src: "ascii",
+ nBuf: 3,
+ dst: "ascii", // U+ff41, ...
+ nDst: 3,
+ nSrc: 1,
+ atEOF: true,
+ err: transform.ErrShortDst,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "ambiguous",
+ src: "\uffe9",
+ nBuf: 4,
+ dst: "\u2190",
+ nDst: 3,
+ nSrc: 3,
+ atEOF: false,
+ err: nil,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }} {
+ tc.doTest(t, Widen)
+ }
+}
+
+func TestNarrowSingleRunes(t *testing.T) {
+ for r := rune(0); r < 0x1FFFF; r++ {
+ if loSurrogate <= r && r <= hiSurrogate {
+ continue
+ }
+ alt, _ := narrowRune(r)
+ want := string(alt)
+ got := Narrow.String(string(r))
+ if got != want {
+ t.Errorf("Narrow().String(%U) = %+q; want %+q", r, got, want)
+ }
+ }
+}
+
+func TestNarrow(t *testing.T) {
+ for _, tc := range []transformTest{{
+ desc: "empty",
+ src: "",
+ nBuf: 10,
+ dst: "",
+ nDst: 0,
+ nSrc: 0,
+ atEOF: false,
+ err: nil,
+ nSpan: 0,
+ errSpan: nil,
+ }, {
+ desc: "short source 1",
+ src: "a\xc2",
+ nBuf: 10,
+ dst: "a\xc2",
+ nDst: 1,
+ nSrc: 1,
+ atEOF: false,
+ err: transform.ErrShortSrc,
+ nSpan: 1,
+ errSpan: transform.ErrShortSrc,
+ }, {
+ desc: "short source 2",
+ src: "a\xe0\x80",
+ nBuf: 10,
+ dst: "a\xe0\x80",
+ nDst: 1,
+ nSrc: 3,
+ atEOF: false,
+ err: transform.ErrShortSrc,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "incomplete but terminated source 1",
+ src: "a\xc2",
+ nBuf: 10,
+ dst: "a\xc2",
+ nDst: 2,
+ nSrc: 4,
+ atEOF: true,
+ err: nil,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "incomplete but terminated source 2",
+ src: "a\xe0\x80",
+ nBuf: 10,
+ dst: "a\xe0\x80",
+ nDst: 3,
+ nSrc: 5,
+ atEOF: true,
+ err: nil,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "exact fit dst",
+ src: "a\uff01",
+ nBuf: 2,
+ dst: "a!",
+ nDst: 2,
+ nSrc: 6,
+ atEOF: false,
+ err: nil,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "exact fit dst some span",
+ src: "a\uff01",
+ nBuf: 2,
+ dst: "a!",
+ nDst: 2,
+ nSrc: 4,
+ atEOF: false,
+ err: nil,
+ nSpan: 1,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "empty dst",
+ src: "\u0300",
+ nBuf: 0,
+ dst: "\u0300",
+ nDst: 0,
+ nSrc: 0,
+ atEOF: true,
+ err: transform.ErrShortDst,
+ nSpan: 2,
+ errSpan: nil,
+ }, {
+ desc: "empty dst ascii",
+ src: "a",
+ nBuf: 0,
+ dst: "a",
+ nDst: 0,
+ nSrc: 0,
+ atEOF: true,
+ err: transform.ErrShortDst,
+ nSpan: 1,
+ errSpan: nil,
+ }, {
+ desc: "short dst 1",
+ src: "a\uffe0", // ¢
+ nBuf: 2,
+ dst: "a\u00a2", // ¢
+ nDst: 1,
+ nSrc: 3,
+ atEOF: false,
+ err: transform.ErrShortDst,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "short dst 2",
+ src: "不夠",
+ nBuf: 3,
+ dst: "不夠",
+ nDst: 3,
+ nSrc: 3,
+ atEOF: true,
+ err: transform.ErrShortDst,
+ nSpan: 6,
+ errSpan: nil,
+ }, {
+ // Create a narrow variant of ambiguous runes, if they exist.
+ desc: "ambiguous",
+ src: "\u2190",
+ nBuf: 4,
+ dst: "\uffe9",
+ nDst: 3,
+ nSrc: 3,
+ atEOF: false,
+ err: nil,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "short dst fast path",
+ src: "fast",
+ nBuf: 3,
+ dst: "fast",
+ nDst: 3,
+ nSrc: 3,
+ atEOF: true,
+ err: transform.ErrShortDst,
+ nSpan: 4,
+ errSpan: nil,
+ }, {
+ desc: "short dst larger buffer",
+ src: "\uff21" + strings.Repeat("0", 127) + "B",
+ nBuf: 128,
+ dst: "A" + strings.Repeat("0", 127) + "B",
+ nDst: 128,
+ nSrc: 130,
+ atEOF: true,
+ err: transform.ErrShortDst,
+ nSpan: 0,
+ errSpan: transform.ErrEndOfSpan,
+ }, {
+ desc: "fast path alternation",
+ src: "fast路徑fast路徑",
+ nBuf: 20,
+ dst: "fast路徑fast路徑",
+ nDst: 20,
+ nSrc: 20,
+ atEOF: true,
+ err: nil,
+ nSpan: 20,
+ errSpan: nil,
+ }} {
+ tc.doTest(t, Narrow)
+ }
+}
+
+func bench(b *testing.B, t Transformer, s string) {
+ dst := make([]byte, 1024)
+ src := []byte(s)
+ b.SetBytes(int64(len(src)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ t.Transform(dst, src, true)
+ }
+}
+
+func changingRunes(f func(r rune) (rune, bool)) string {
+ buf := &bytes.Buffer{}
+ for r := rune(0); r <= 0xFFFF; r++ {
+ if _, ok := foldRune(r); ok {
+ buf.WriteRune(r)
+ }
+ }
+ return buf.String()
+}
+
+func BenchmarkFoldASCII(b *testing.B) {
+ bench(b, Fold, testtext.ASCII)
+}
+
+func BenchmarkFoldCJK(b *testing.B) {
+ bench(b, Fold, testtext.CJK)
+}
+
+func BenchmarkFoldNonCanonical(b *testing.B) {
+ bench(b, Fold, changingRunes(foldRune))
+}
+
+func BenchmarkFoldOther(b *testing.B) {
+ bench(b, Fold, testtext.TwoByteUTF8+testtext.ThreeByteUTF8)
+}
+
+func BenchmarkWideASCII(b *testing.B) {
+ bench(b, Widen, testtext.ASCII)
+}
+
+func BenchmarkWideCJK(b *testing.B) {
+ bench(b, Widen, testtext.CJK)
+}
+
+func BenchmarkWideNonCanonical(b *testing.B) {
+ bench(b, Widen, changingRunes(widenRune))
+}
+
+func BenchmarkWideOther(b *testing.B) {
+ bench(b, Widen, testtext.TwoByteUTF8+testtext.ThreeByteUTF8)
+}
+
+func BenchmarkNarrowASCII(b *testing.B) {
+ bench(b, Narrow, testtext.ASCII)
+}
+
+func BenchmarkNarrowCJK(b *testing.B) {
+ bench(b, Narrow, testtext.CJK)
+}
+
+func BenchmarkNarrowNonCanonical(b *testing.B) {
+ bench(b, Narrow, changingRunes(narrowRune))
+}
+
+func BenchmarkNarrowOther(b *testing.B) {
+ bench(b, Narrow, testtext.TwoByteUTF8+testtext.ThreeByteUTF8)
+}