github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/text/runes/runes_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 runes
     6  
     7  import (
     8  	"strings"
     9  	"testing"
    10  	"unicode/utf8"
    11  
    12  	"golang.org/x/text/transform"
    13  )
    14  
    15  type transformTest struct {
    16  	desc    string
    17  	szDst   int
    18  	atEOF   bool
    19  	repl    string
    20  	in      string
    21  	out     string // result string of first call to Transform
    22  	outFull string // transform of entire input string
    23  	err     error
    24  
    25  	t transform.Transformer
    26  }
    27  
    28  const large = 10240
    29  
    30  func (tt *transformTest) check(t *testing.T, i int) {
    31  	if tt.t == nil {
    32  		return
    33  	}
    34  	dst := make([]byte, tt.szDst)
    35  	src := []byte(tt.in)
    36  	nDst, nSrc, err := tt.t.Transform(dst, src, tt.atEOF)
    37  	if err != tt.err {
    38  		t.Errorf("%d:%s:error: got %v; want %v", i, tt.desc, err, tt.err)
    39  	}
    40  	if got := string(dst[:nDst]); got != tt.out {
    41  		t.Errorf("%d:%s:out: got %q; want %q", i, tt.desc, got, tt.out)
    42  	}
    43  
    44  	// Calls tt.t.Transform for the remainder of the input. We use this to test
    45  	// the nSrc return value.
    46  	out := make([]byte, large)
    47  	n := copy(out, dst[:nDst])
    48  	nDst, _, _ = tt.t.Transform(out[n:], src[nSrc:], true)
    49  	if got, want := string(out[:n+nDst]), tt.outFull; got != want {
    50  		t.Errorf("%d:%s:outFull: got %q; want %q", i, tt.desc, got, want)
    51  	}
    52  }
    53  
    54  func idem(r rune) rune { return r }
    55  
    56  func TestMap(t *testing.T) {
    57  	runes := []rune{'a', 'ç', '中', '\U00012345', 'a'}
    58  	// Default mapper used for this test.
    59  	rotate := Map(func(r rune) rune {
    60  		for i, m := range runes {
    61  			if m == r {
    62  				return runes[i+1]
    63  			}
    64  		}
    65  		return r
    66  	})
    67  
    68  	for i, tt := range []transformTest{{
    69  		desc:    "empty",
    70  		szDst:   large,
    71  		atEOF:   true,
    72  		in:      "",
    73  		out:     "",
    74  		outFull: "",
    75  		t:       rotate,
    76  	}, {
    77  		desc:    "no change",
    78  		szDst:   1,
    79  		atEOF:   true,
    80  		in:      "b",
    81  		out:     "b",
    82  		outFull: "b",
    83  		t:       rotate,
    84  	}, {
    85  		desc:    "short dst",
    86  		szDst:   2,
    87  		atEOF:   true,
    88  		in:      "aaaa",
    89  		out:     "ç",
    90  		outFull: "çççç",
    91  		err:     transform.ErrShortDst,
    92  		t:       rotate,
    93  	}, {
    94  		desc:    "short dst ascii, no change",
    95  		szDst:   2,
    96  		atEOF:   true,
    97  		in:      "bbb",
    98  		out:     "bb",
    99  		outFull: "bbb",
   100  		err:     transform.ErrShortDst,
   101  		t:       rotate,
   102  	}, {
   103  		desc:    "short dst writing error",
   104  		szDst:   2,
   105  		atEOF:   false,
   106  		in:      "a\x80",
   107  		out:     "ç",
   108  		outFull: "ç\ufffd",
   109  		err:     transform.ErrShortDst,
   110  		t:       rotate,
   111  	}, {
   112  		desc:    "short dst writing incomplete rune",
   113  		szDst:   2,
   114  		atEOF:   true,
   115  		in:      "a\xc0",
   116  		out:     "ç",
   117  		outFull: "ç\ufffd",
   118  		err:     transform.ErrShortDst,
   119  		t:       rotate,
   120  	}, {
   121  		desc:    "short dst, longer",
   122  		szDst:   5,
   123  		atEOF:   true,
   124  		in:      "Hellø",
   125  		out:     "Hell",
   126  		outFull: "Hellø",
   127  		err:     transform.ErrShortDst,
   128  		t:       rotate,
   129  	}, {
   130  		desc:    "short dst, single",
   131  		szDst:   1,
   132  		atEOF:   false,
   133  		in:      "ø",
   134  		out:     "",
   135  		outFull: "ø",
   136  		err:     transform.ErrShortDst,
   137  		t:       Map(idem),
   138  	}, {
   139  		desc:    "short dst, longer, writing error",
   140  		szDst:   8,
   141  		atEOF:   false,
   142  		in:      "\x80Hello\x80",
   143  		out:     "\ufffdHello",
   144  		outFull: "\ufffdHello\ufffd",
   145  		err:     transform.ErrShortDst,
   146  		t:       rotate,
   147  	}, {
   148  		desc:    "short src",
   149  		szDst:   2,
   150  		atEOF:   false,
   151  		in:      "a\xc2",
   152  		out:     "ç",
   153  		outFull: "ç\ufffd",
   154  		err:     transform.ErrShortSrc,
   155  		t:       rotate,
   156  	}, {
   157  		desc:    "invalid input, atEOF",
   158  		szDst:   large,
   159  		atEOF:   true,
   160  		in:      "\x80",
   161  		out:     "\ufffd",
   162  		outFull: "\ufffd",
   163  		t:       rotate,
   164  	}, {
   165  		desc:    "invalid input, !atEOF",
   166  		szDst:   large,
   167  		atEOF:   false,
   168  		in:      "\x80",
   169  		out:     "\ufffd",
   170  		outFull: "\ufffd",
   171  		t:       rotate,
   172  	}, {
   173  		desc:    "invalid input, incomplete rune atEOF",
   174  		szDst:   large,
   175  		atEOF:   true,
   176  		in:      "\xc0",
   177  		out:     "\ufffd",
   178  		outFull: "\ufffd",
   179  		t:       rotate,
   180  	}, {
   181  		desc:    "misc correct",
   182  		szDst:   large,
   183  		atEOF:   true,
   184  		in:      "a\U00012345 ç!",
   185  		out:     "ça 中!",
   186  		outFull: "ça 中!",
   187  		t:       rotate,
   188  	}, {
   189  		desc:    "misc correct and invalid",
   190  		szDst:   large,
   191  		atEOF:   true,
   192  		in:      "Hello\x80 w\x80orl\xc0d!\xc0",
   193  		out:     "Hello\ufffd w\ufffdorl\ufffdd!\ufffd",
   194  		outFull: "Hello\ufffd w\ufffdorl\ufffdd!\ufffd",
   195  		t:       rotate,
   196  	}, {
   197  		desc:    "misc correct and invalid, short src",
   198  		szDst:   large,
   199  		atEOF:   false,
   200  		in:      "Hello\x80 w\x80orl\xc0d!\xc2",
   201  		out:     "Hello\ufffd w\ufffdorl\ufffdd!",
   202  		outFull: "Hello\ufffd w\ufffdorl\ufffdd!\ufffd",
   203  		err:     transform.ErrShortSrc,
   204  		t:       rotate,
   205  	}, {
   206  		desc:    "misc correct and invalid, short src, replacing RuneError",
   207  		szDst:   large,
   208  		atEOF:   false,
   209  		in:      "Hel\ufffdlo\x80 w\x80orl\xc0d!\xc2",
   210  		out:     "Hel?lo? w?orl?d!",
   211  		outFull: "Hel?lo? w?orl?d!?",
   212  		err:     transform.ErrShortSrc,
   213  		t: Map(func(r rune) rune {
   214  			if r == utf8.RuneError {
   215  				return '?'
   216  			}
   217  			return r
   218  		}),
   219  	}} {
   220  		tt.check(t, i)
   221  	}
   222  }
   223  
   224  func TestRemove(t *testing.T) {
   225  	remove := Remove(Predicate(func(r rune) bool {
   226  		return strings.ContainsRune("aeiou\u0300\uFF24\U00012345", r)
   227  	}))
   228  
   229  	for i, tt := range []transformTest{
   230  		0: {
   231  			szDst:   large,
   232  			atEOF:   true,
   233  			in:      "",
   234  			out:     "",
   235  			outFull: "",
   236  			t:       remove,
   237  		},
   238  		1: {
   239  			szDst:   0,
   240  			atEOF:   true,
   241  			in:      "aaaa",
   242  			out:     "",
   243  			outFull: "",
   244  			t:       remove,
   245  		},
   246  		2: {
   247  			szDst:   1,
   248  			atEOF:   true,
   249  			in:      "aaaa",
   250  			out:     "",
   251  			outFull: "",
   252  			t:       remove,
   253  		},
   254  		3: {
   255  			szDst:   1,
   256  			atEOF:   true,
   257  			in:      "baaaa",
   258  			out:     "b",
   259  			outFull: "b",
   260  			t:       remove,
   261  		},
   262  		4: {
   263  			szDst:   2,
   264  			atEOF:   true,
   265  			in:      "açaaa",
   266  			out:     "ç",
   267  			outFull: "ç",
   268  			t:       remove,
   269  		},
   270  		5: {
   271  			szDst:   2,
   272  			atEOF:   true,
   273  			in:      "aaaç",
   274  			out:     "ç",
   275  			outFull: "ç",
   276  			t:       remove,
   277  		},
   278  		6: {
   279  			szDst:   2,
   280  			atEOF:   false,
   281  			in:      "a\x80",
   282  			out:     "",
   283  			outFull: "\ufffd",
   284  			err:     transform.ErrShortDst,
   285  			t:       remove,
   286  		},
   287  		7: {
   288  			szDst:   1,
   289  			atEOF:   true,
   290  			in:      "a\xc0",
   291  			out:     "",
   292  			outFull: "\ufffd",
   293  			err:     transform.ErrShortDst,
   294  			t:       remove,
   295  		},
   296  		8: {
   297  			szDst:   1,
   298  			atEOF:   false,
   299  			in:      "a\xc2",
   300  			out:     "",
   301  			outFull: "\ufffd",
   302  			err:     transform.ErrShortSrc,
   303  			t:       remove,
   304  		},
   305  		9: {
   306  			szDst:   large,
   307  			atEOF:   true,
   308  			in:      "\x80",
   309  			out:     "\ufffd",
   310  			outFull: "\ufffd",
   311  			t:       remove,
   312  		},
   313  		10: {
   314  			szDst:   large,
   315  			atEOF:   false,
   316  			in:      "\x80",
   317  			out:     "\ufffd",
   318  			outFull: "\ufffd",
   319  			t:       remove,
   320  		},
   321  		11: {
   322  			szDst:   large,
   323  			atEOF:   true,
   324  			in:      "\xc0",
   325  			out:     "\ufffd",
   326  			outFull: "\ufffd",
   327  			t:       remove,
   328  		},
   329  		12: {
   330  			szDst:   large,
   331  			atEOF:   true,
   332  			in:      "Hello \U00012345world!",
   333  			out:     "Hll wrld!",
   334  			outFull: "Hll wrld!",
   335  			t:       remove,
   336  		},
   337  		13: {
   338  			szDst:   large,
   339  			atEOF:   true,
   340  			in:      "Hello\x80 w\x80orl\xc0d!\xc0",
   341  			out:     "Hll\ufffd w\ufffdrl\ufffdd!\ufffd",
   342  			outFull: "Hll\ufffd w\ufffdrl\ufffdd!\ufffd",
   343  			t:       remove,
   344  		},
   345  		14: {
   346  			szDst:   large,
   347  			atEOF:   false,
   348  			in:      "Hello\x80 w\x80orl\xc0d!\xc2",
   349  			out:     "Hll\ufffd w\ufffdrl\ufffdd!",
   350  			outFull: "Hll\ufffd w\ufffdrl\ufffdd!\ufffd",
   351  			err:     transform.ErrShortSrc,
   352  			t:       remove,
   353  		},
   354  		15: {
   355  			szDst:   large,
   356  			atEOF:   false,
   357  			in:      "Hel\ufffdlo\x80 w\x80orl\xc0d!\xc2",
   358  			out:     "Hello world!",
   359  			outFull: "Hello world!",
   360  			err:     transform.ErrShortSrc,
   361  			t:       Remove(Predicate(func(r rune) bool { return r == utf8.RuneError })),
   362  		},
   363  		16: {
   364  			szDst:   4,
   365  			atEOF:   true,
   366  			in:      "Hellø",
   367  			out:     "Hll",
   368  			outFull: "Hllø",
   369  			err:     transform.ErrShortDst,
   370  			t:       remove,
   371  		},
   372  		17: {
   373  			szDst:   4,
   374  			atEOF:   false,
   375  			in:      "Hellø",
   376  			out:     "Hll",
   377  			outFull: "Hllø",
   378  			err:     transform.ErrShortDst,
   379  			t:       remove,
   380  		},
   381  		18: {
   382  			szDst:   8,
   383  			atEOF:   false,
   384  			in:      "\x80Hello\uFF24\x80",
   385  			out:     "\ufffdHll",
   386  			outFull: "\ufffdHll\ufffd",
   387  			err:     transform.ErrShortDst,
   388  			t:       remove,
   389  		},
   390  	} {
   391  		tt.check(t, i)
   392  	}
   393  }
   394  
   395  func TestReplaceIllFormed(t *testing.T) {
   396  	replace := ReplaceIllFormed()
   397  
   398  	for i, tt := range []transformTest{
   399  		0: {
   400  			szDst:   large,
   401  			atEOF:   true,
   402  			in:      "",
   403  			out:     "",
   404  			outFull: "",
   405  			t:       replace,
   406  		},
   407  		1: {
   408  			szDst:   1,
   409  			atEOF:   true,
   410  			in:      "aa",
   411  			out:     "a",
   412  			outFull: "aa",
   413  			err:     transform.ErrShortDst,
   414  			t:       replace,
   415  		},
   416  		2: {
   417  			szDst:   1,
   418  			atEOF:   true,
   419  			in:      "a\x80",
   420  			out:     "a",
   421  			outFull: "a\ufffd",
   422  			err:     transform.ErrShortDst,
   423  			t:       replace,
   424  		},
   425  		3: {
   426  			szDst:   1,
   427  			atEOF:   true,
   428  			in:      "a\xc0",
   429  			out:     "a",
   430  			outFull: "a\ufffd",
   431  			err:     transform.ErrShortDst,
   432  			t:       replace,
   433  		},
   434  		4: {
   435  			szDst:   large,
   436  			atEOF:   true,
   437  			in:      "\x80",
   438  			out:     "\ufffd",
   439  			outFull: "\ufffd",
   440  			t:       replace,
   441  		},
   442  		5: {
   443  			szDst:   large,
   444  			atEOF:   false,
   445  			in:      "\x80",
   446  			out:     "\ufffd",
   447  			outFull: "\ufffd",
   448  			t:       replace,
   449  		},
   450  		6: {
   451  			szDst:   large,
   452  			atEOF:   true,
   453  			in:      "\xc2",
   454  			out:     "\ufffd",
   455  			outFull: "\ufffd",
   456  			t:       replace,
   457  		},
   458  		7: {
   459  			szDst:   large,
   460  			atEOF:   false,
   461  			in:      "\xc2",
   462  			out:     "",
   463  			outFull: "\ufffd",
   464  			err:     transform.ErrShortSrc,
   465  			t:       replace,
   466  		},
   467  		8: {
   468  			szDst:   large,
   469  			atEOF:   true,
   470  			in:      "Hello world!",
   471  			out:     "Hello world!",
   472  			outFull: "Hello world!",
   473  			t:       replace,
   474  		},
   475  		9: {
   476  			szDst:   large,
   477  			atEOF:   true,
   478  			in:      "Hello\x80 w\x80orl\xc2d!\xc2",
   479  			out:     "Hello\ufffd w\ufffdorl\ufffdd!\ufffd",
   480  			outFull: "Hello\ufffd w\ufffdorl\ufffdd!\ufffd",
   481  			t:       replace,
   482  		},
   483  		10: {
   484  			szDst:   large,
   485  			atEOF:   false,
   486  			in:      "Hello\x80 w\x80orl\xc2d!\xc2",
   487  			out:     "Hello\ufffd w\ufffdorl\ufffdd!",
   488  			outFull: "Hello\ufffd w\ufffdorl\ufffdd!\ufffd",
   489  			err:     transform.ErrShortSrc,
   490  			t:       replace,
   491  		},
   492  		16: {
   493  			szDst:   10,
   494  			atEOF:   false,
   495  			in:      "\x80Hello\x80",
   496  			out:     "\ufffdHello",
   497  			outFull: "\ufffdHello\ufffd",
   498  			err:     transform.ErrShortDst,
   499  			t:       replace,
   500  		},
   501  	} {
   502  		tt.check(t, i)
   503  	}
   504  }
   505  
   506  func TestMapAlloc(t *testing.T) {
   507  	if n := testing.AllocsPerRun(3, func() {
   508  		Map(idem).Transform(nil, nil, false)
   509  	}); n > 0 {
   510  		t.Errorf("got %f; want 0", n)
   511  	}
   512  }
   513  
   514  func rmNop(r rune) bool { return false }
   515  
   516  func TestRemoveAlloc(t *testing.T) {
   517  	if n := testing.AllocsPerRun(3, func() {
   518  		Remove(Predicate(rmNop)).Transform(nil, nil, false)
   519  	}); n > 0 {
   520  		t.Errorf("got %f; want 0", n)
   521  	}
   522  }
   523  
   524  func TestReplaceIllFormedAlloc(t *testing.T) {
   525  	if n := testing.AllocsPerRun(3, func() {
   526  		ReplaceIllFormed().Transform(nil, nil, false)
   527  	}); n > 0 {
   528  		t.Errorf("got %f; want 0", n)
   529  	}
   530  }
   531  
   532  func BenchmarkRemove(b *testing.B) {
   533  	dst := make([]byte, len(input))
   534  	src := []byte(input)
   535  
   536  	r := Remove(Predicate(func(r rune) bool { return r == 'e' }))
   537  	b.ResetTimer()
   538  
   539  	for i := 0; i < b.N; i++ {
   540  		r.Transform(dst, src, true)
   541  	}
   542  }
   543  
   544  func BenchmarkMapAll(b *testing.B) {
   545  	dst := make([]byte, 2*len(input))
   546  	src := []byte(input)
   547  
   548  	r := Map(func(r rune) rune { return 'a' })
   549  	b.ResetTimer()
   550  
   551  	for i := 0; i < b.N; i++ {
   552  		r.Transform(dst, src, true)
   553  	}
   554  }
   555  
   556  func BenchmarkMapNone(b *testing.B) {
   557  	dst := make([]byte, 2*len(input))
   558  	src := []byte(input)
   559  
   560  	r := Map(func(r rune) rune { return r })
   561  	b.ResetTimer()
   562  
   563  	for i := 0; i < b.N; i++ {
   564  		r.Transform(dst, src, true)
   565  	}
   566  }
   567  
   568  func BenchmarkReplaceIllFormed(b *testing.B) {
   569  	dst := make([]byte, 2*len(input))
   570  	src := []byte(input)
   571  
   572  	t := ReplaceIllFormed()
   573  	b.ResetTimer()
   574  
   575  	for i := 0; i < b.N; i++ {
   576  		t.Transform(dst, src, true)
   577  	}
   578  }
   579  
   580  var (
   581  	input = strings.Repeat("Thé qüick brøwn føx jumps øver the lazy døg. ", 100)
   582  )