123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- // 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 precis
- import (
- "bytes"
- "fmt"
- "reflect"
- "testing"
- "golang.org/x/text/internal/testtext"
- "golang.org/x/text/transform"
- )
- type testCase struct {
- input string
- output string
- err error
- }
- func doTests(t *testing.T, fn func(t *testing.T, p *Profile, tc testCase)) {
- for _, g := range enforceTestCases {
- for i, tc := range g.cases {
- name := fmt.Sprintf("%s:%d:%+q", g.name, i, tc.input)
- testtext.Run(t, name, func(t *testing.T) {
- fn(t, g.p, tc)
- })
- }
- }
- }
- func TestString(t *testing.T) {
- doTests(t, func(t *testing.T, p *Profile, tc testCase) {
- if e, err := p.String(tc.input); tc.err != err || e != tc.output {
- t.Errorf("got %+q (err: %v); want %+q (err: %v)", e, err, tc.output, tc.err)
- }
- })
- }
- func TestBytes(t *testing.T) {
- doTests(t, func(t *testing.T, p *Profile, tc testCase) {
- if e, err := p.Bytes([]byte(tc.input)); tc.err != err || string(e) != tc.output {
- t.Errorf("got %+q (err: %v); want %+q (err: %v)", string(e), err, tc.output, tc.err)
- }
- })
- t.Run("Copy", func(t *testing.T) {
- // Test that calling Bytes with something that doesn't transform returns a
- // copy.
- orig := []byte("hello")
- b, _ := NewFreeform().Bytes(orig)
- if reflect.ValueOf(b).Pointer() == reflect.ValueOf(orig).Pointer() {
- t.Error("original and result are the same slice; should be a copy")
- }
- })
- }
- func TestAppend(t *testing.T) {
- doTests(t, func(t *testing.T, p *Profile, tc testCase) {
- if e, err := p.Append(nil, []byte(tc.input)); tc.err != err || string(e) != tc.output {
- t.Errorf("got %+q (err: %v); want %+q (err: %v)", string(e), err, tc.output, tc.err)
- }
- })
- }
- func TestStringMallocs(t *testing.T) {
- if n := testtext.AllocsPerRun(100, func() { UsernameCaseMapped.String("helloworld") }); n > 0 {
- // TODO: reduce this to 0.
- t.Skipf("got %f allocs, want 0", n)
- }
- }
- func TestAppendMallocs(t *testing.T) {
- str := []byte("helloworld")
- out := make([]byte, 0, len(str))
- if n := testtext.AllocsPerRun(100, func() { UsernameCaseMapped.Append(out, str) }); n > 0 {
- t.Errorf("got %f allocs, want 0", n)
- }
- }
- func TestTransformMallocs(t *testing.T) {
- str := []byte("helloworld")
- out := make([]byte, 0, len(str))
- tr := UsernameCaseMapped.NewTransformer()
- if n := testtext.AllocsPerRun(100, func() {
- tr.Reset()
- tr.Transform(out, str, true)
- }); n > 0 {
- t.Errorf("got %f allocs, want 0", n)
- }
- }
- func min(a, b int) int {
- if a < b {
- return a
- }
- return b
- }
- // TestTransformerShortBuffers tests that the precis.Transformer implements the
- // spirit, not just the letter (the method signatures), of the
- // transform.Transformer interface.
- //
- // In particular, it tests that, if one or both of the dst or src buffers are
- // short, so that multiple Transform calls are required to complete the overall
- // transformation, the end result is identical to one Transform call with
- // sufficiently long buffers.
- func TestTransformerShortBuffers(t *testing.T) {
- srcUnit := []byte("a\u0300cce\u0301nts") // NFD normalization form.
- wantUnit := []byte("àccénts") // NFC normalization form.
- src := bytes.Repeat(srcUnit, 16)
- want := bytes.Repeat(wantUnit, 16)
- const long = 4096
- dst := make([]byte, long)
- // 5, 7, 9, 11, 13, 16 and 17 are all pair-wise co-prime, which means that
- // slicing the dst and src buffers into 5, 7, 13 and 17 byte chunks will
- // fall at different places inside the repeated srcUnit's and wantUnit's.
- if len(srcUnit) != 11 || len(wantUnit) != 9 || len(src) > long || len(want) > long {
- t.Fatal("inconsistent lengths")
- }
- tr := NewFreeform().NewTransformer()
- for _, deltaD := range []int{5, 7, 13, 17, long} {
- loop:
- for _, deltaS := range []int{5, 7, 13, 17, long} {
- tr.Reset()
- d0 := 0
- s0 := 0
- for {
- d1 := min(len(dst), d0+deltaD)
- s1 := min(len(src), s0+deltaS)
- nDst, nSrc, err := tr.Transform(dst[d0:d1:d1], src[s0:s1:s1], s1 == len(src))
- d0 += nDst
- s0 += nSrc
- if err == nil {
- break
- }
- if err == transform.ErrShortDst || err == transform.ErrShortSrc {
- continue
- }
- t.Errorf("deltaD=%d, deltaS=%d: %v", deltaD, deltaS, err)
- continue loop
- }
- if s0 != len(src) {
- t.Errorf("deltaD=%d, deltaS=%d: s0: got %d, want %d", deltaD, deltaS, s0, len(src))
- continue
- }
- if d0 != len(want) {
- t.Errorf("deltaD=%d, deltaS=%d: d0: got %d, want %d", deltaD, deltaS, d0, len(want))
- continue
- }
- got := dst[:d0]
- if !bytes.Equal(got, want) {
- t.Errorf("deltaD=%d, deltaS=%d:\ngot %q\nwant %q", deltaD, deltaS, got, want)
- continue
- }
- }
- }
- }
|