1 // Copyright 2009 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.
20 func eq(a
, b
[]string) bool {
24 for i
:= 0; i
< len(a
); i
++ {
32 func sliceOfString(s
[][]byte) []string {
33 result
:= make([]string, len(s
))
40 // For ease of reading, the test cases use strings that are converted to byte
41 // slices before invoking the functions.
45 var commas
= "1,2,3,4"
46 var dots
= "1....2....3....4"
48 type BinOpTest
struct {
54 func TestEqual(t
*testing
.T
) {
55 // Run the tests and check for allocation at the same time.
56 allocs
:= testing
.AllocsPerRun(10, func() {
57 for _
, tt
:= range compareTests
{
58 eql
:= Equal(tt
.a
, tt
.b
)
59 if eql
!= (tt
.i
== 0) {
60 t
.Errorf(`Equal(%q, %q) = %v`, tt
.a
, tt
.b
, eql
)
65 t
.Errorf("Equal allocated %v times", allocs
)
69 func TestEqualExhaustive(t
*testing
.T
) {
74 a
:= make([]byte, size
)
75 b
:= make([]byte, size
)
76 b_init
:= make([]byte, size
)
77 // randomish but deterministic data
78 for i
:= 0; i
< size
; i
++ {
80 b_init
[i
] = byte(23*i
+ 100)
83 for len := 0; len <= size
; len++ {
84 for x
:= 0; x
<= size
-len; x
++ {
85 for y
:= 0; y
<= size
-len; y
++ {
87 copy(b
[y
:y
+len], a
[x
:x
+len])
88 if !Equal(a
[x
:x
+len], b
[y
:y
+len]) ||
!Equal(b
[y
:y
+len], a
[x
:x
+len]) {
89 t
.Errorf("Equal(%d, %d, %d) = false", len, x
, y
)
96 // make sure Equal returns false for minimally different strings. The data
97 // is all zeros except for a single one in one location.
98 func TestNotEqual(t
*testing
.T
) {
103 a
:= make([]byte, size
)
104 b
:= make([]byte, size
)
106 for len := 0; len <= size
; len++ {
107 for x
:= 0; x
<= size
-len; x
++ {
108 for y
:= 0; y
<= size
-len; y
++ {
109 for diffpos
:= x
; diffpos
< x
+len; diffpos
++ {
111 if Equal(a
[x
:x
+len], b
[y
:y
+len]) ||
Equal(b
[y
:y
+len], a
[x
:x
+len]) {
112 t
.Errorf("NotEqual(%d, %d, %d, %d) = true", len, x
, y
, diffpos
)
121 var indexTests
= []BinOpTest
{
128 {"oofofoofooo", "f", 2},
129 {"oofofoofooo", "foo", 4},
130 {"barfoobarfoo", "foo", 3},
133 {"abcABCabc", "A", 3},
134 // cases with one byte strings - test IndexByte and special case in Index()
142 {"barfoobarfooyyyzzzyyyzzzyyyzzzyyyxxxzzzyyy", "x", 33},
143 {"foofyfoobarfoobar", "y", 4},
144 {"oooooooooooooooooooooo", "r", -1},
145 {"oxoxoxoxoxoxoxoxoxoxoxoy", "oy", 22},
146 {"oxoxoxoxoxoxoxoxoxoxoxox", "oy", -1},
147 // test fallback to Rabin-Karp.
148 {"000000000000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000001", 5},
151 var lastIndexTests
= []BinOpTest
{
158 {"oofofoofooo", "f", 7},
159 {"oofofoofooo", "foo", 7},
160 {"barfoobarfoo", "foo", 9},
163 {"abcABCabc", "A", 3},
164 {"abcABCabc", "a", 6},
167 var indexAnyTests
= []BinOpTest
{
173 {"\x80", "\xffb", 0},
178 {"a☺b☻c☹d", "cx", len("a☺b☻")},
179 {"a☺b☻c☹d", "uvw☻xyz", len("a☺b")},
180 {"aRegExp*", ".(|)*+?^$[]", 7},
181 {dots
+ dots
+ dots
, " ", -1},
182 {"012abcba210", "\xffb", 4},
183 {"012\x80bcb\x80210", "\xffb", 3},
184 {"0123456\xcf\x80abc", "\xcfb\x80", 10},
187 var lastIndexAnyTests
= []BinOpTest
{
193 {"\x80", "\xffb", 0},
198 {"a☺b☻c☹d", "cx", len("a☺b☻")},
199 {"a☺b☻c☹d", "uvw☻xyz", len("a☺b")},
200 {"a.RegExp*", ".(|)*+?^$[]", 8},
201 {dots
+ dots
+ dots
, " ", -1},
202 {"012abcba210", "\xffb", 6},
203 {"012\x80bcb\x80210", "\xffb", 7},
204 {"0123456\xcf\x80abc", "\xcfb\x80", 10},
207 // Execute f on each test case. funcName should be the name of f; it's used
208 // in failure reports.
209 func runIndexTests(t
*testing
.T
, f
func(s
, sep
[]byte) int, funcName
string, testCases
[]BinOpTest
) {
210 for _
, test
:= range testCases
{
214 if actual
!= test
.i
{
215 t
.Errorf("%s(%q,%q) = %v; want %v", funcName
, a
, b
, actual
, test
.i
)
218 var allocTests
= []struct {
223 // case for function Index.
224 {[]byte("000000000000000000000000000000000000000000000000000000000000000000000001"), []byte("0000000000000000000000000000000000000000000000000000000000000000001"), 5},
225 // case for function LastIndex.
226 {[]byte("000000000000000000000000000000000000000000000000000000000000000010000"), []byte("00000000000000000000000000000000000000000000000000000000000001"), 3},
228 allocs
:= testing
.AllocsPerRun(100, func() {
229 if i
:= Index(allocTests
[1].a
, allocTests
[1].b
); i
!= allocTests
[1].i
{
230 t
.Errorf("Index([]byte(%q), []byte(%q)) = %v; want %v", allocTests
[1].a
, allocTests
[1].b
, i
, allocTests
[1].i
)
232 if i
:= LastIndex(allocTests
[0].a
, allocTests
[0].b
); i
!= allocTests
[0].i
{
233 t
.Errorf("LastIndex([]byte(%q), []byte(%q)) = %v; want %v", allocTests
[0].a
, allocTests
[0].b
, i
, allocTests
[0].i
)
237 t
.Errorf("expected no allocations, got %f", allocs
)
241 func runIndexAnyTests(t
*testing
.T
, f
func(s
[]byte, chars
string) int, funcName
string, testCases
[]BinOpTest
) {
242 for _
, test
:= range testCases
{
244 actual
:= f(a
, test
.b
)
245 if actual
!= test
.i
{
246 t
.Errorf("%s(%q,%q) = %v; want %v", funcName
, a
, test
.b
, actual
, test
.i
)
251 func TestIndex(t
*testing
.T
) { runIndexTests(t
, Index
, "Index", indexTests
) }
252 func TestLastIndex(t
*testing
.T
) { runIndexTests(t
, LastIndex
, "LastIndex", lastIndexTests
) }
253 func TestIndexAny(t
*testing
.T
) { runIndexAnyTests(t
, IndexAny
, "IndexAny", indexAnyTests
) }
254 func TestLastIndexAny(t
*testing
.T
) {
255 runIndexAnyTests(t
, LastIndexAny
, "LastIndexAny", lastIndexAnyTests
)
258 func TestIndexByte(t
*testing
.T
) {
259 for _
, tt
:= range indexTests
{
265 pos
:= IndexByte(a
, b
)
267 t
.Errorf(`IndexByte(%q, '%c') = %v`, tt
.a
, b
, pos
)
269 posp
:= IndexBytePortable(a
, b
)
271 t
.Errorf(`indexBytePortable(%q, '%c') = %v`, tt
.a
, b
, posp
)
276 func TestLastIndexByte(t
*testing
.T
) {
277 testCases
:= []BinOpTest
{
280 {"abcdefabcdef", "a", len("abcdef")}, // something in the middle
281 {"abcdefabcdef", "f", len("abcdefabcde")}, // last byte
282 {"zabcdefabcdef", "z", 0}, // first byte
283 {"a☺b☻c☹d", "b", len("a☺")}, // non-ascii
285 for _
, test
:= range testCases
{
286 actual
:= LastIndexByte([]byte(test
.a
), test
.b
[0])
287 if actual
!= test
.i
{
288 t
.Errorf("LastIndexByte(%q,%c) = %v; want %v", test
.a
, test
.b
[0], actual
, test
.i
)
293 // test a larger buffer with different sizes and alignments
294 func TestIndexByteBig(t
*testing
.T
) {
300 for i
:= 0; i
< n
; i
++ {
301 // different start alignments
303 for j
:= 0; j
< len(b1
); j
++ {
305 pos
:= IndexByte(b1
, 'x')
307 t
.Errorf("IndexByte(%q, 'x') = %v", b1
, pos
)
310 pos
= IndexByte(b1
, 'x')
312 t
.Errorf("IndexByte(%q, 'x') = %v", b1
, pos
)
315 // different end alignments
317 for j
:= 0; j
< len(b1
); j
++ {
319 pos
:= IndexByte(b1
, 'x')
321 t
.Errorf("IndexByte(%q, 'x') = %v", b1
, pos
)
324 pos
= IndexByte(b1
, 'x')
326 t
.Errorf("IndexByte(%q, 'x') = %v", b1
, pos
)
329 // different start and end alignments
330 b1
= b
[i
/2 : n
-(i
+1)/2]
331 for j
:= 0; j
< len(b1
); j
++ {
333 pos
:= IndexByte(b1
, 'x')
335 t
.Errorf("IndexByte(%q, 'x') = %v", b1
, pos
)
338 pos
= IndexByte(b1
, 'x')
340 t
.Errorf("IndexByte(%q, 'x') = %v", b1
, pos
)
346 // test a small index across all page offsets
347 func TestIndexByteSmall(t
*testing
.T
) {
348 b
:= make([]byte, 5015) // bigger than a page
349 // Make sure we find the correct byte even when straddling a page.
350 for i
:= 0; i
<= len(b
)-15; i
++ {
351 for j
:= 0; j
< 15; j
++ {
352 b
[i
+j
] = byte(100 + j
)
354 for j
:= 0; j
< 15; j
++ {
355 p
:= IndexByte(b
[i
:i
+15], byte(100+j
))
357 t
.Errorf("IndexByte(%q, %d) = %d", b
[i
:i
+15], 100+j
, p
)
360 for j
:= 0; j
< 15; j
++ {
364 // Make sure matches outside the slice never trigger.
365 for i
:= 0; i
<= len(b
)-15; i
++ {
366 for j
:= 0; j
< 15; j
++ {
369 for j
:= 0; j
< 15; j
++ {
370 p
:= IndexByte(b
[i
:i
+15], byte(0))
372 t
.Errorf("IndexByte(%q, %d) = %d", b
[i
:i
+15], 0, p
)
375 for j
:= 0; j
< 15; j
++ {
381 func TestIndexRune(t
*testing
.T
) {
392 {"foo☺☻☹bar", '☹', 9},
394 {"some_text=some_value", '=', 9},
398 // RuneError should match any invalid UTF-8 byte sequence.
401 {"☻x�", '�', len("☻x")},
402 {"☻x\xe2\x98", '�', len("☻x")},
403 {"☻x\xe2\x98�", '�', len("☻x")},
404 {"☻x\xe2\x98x", '�', len("☻x")},
406 // Invalid rune values should never match.
407 {"a☺b☻c☹d\xe2\x98�\xff�\xed\xa0\x80", -1, -1},
408 {"a☺b☻c☹d\xe2\x98�\xff�\xed\xa0\x80", 0xD800, -1}, // Surrogate pair
409 {"a☺b☻c☹d\xe2\x98�\xff�\xed\xa0\x80", utf8
.MaxRune
+ 1, -1},
411 for _
, tt
:= range tests
{
412 if got
:= IndexRune([]byte(tt
.in
), tt
.rune
); got
!= tt
.want
{
413 t
.Errorf("IndexRune(%q, %d) = %v; want %v", tt
.in
, tt
.rune
, got
, tt
.want
)
417 haystack
:= []byte("test世界")
418 allocs
:= testing
.AllocsPerRun(1000, func() {
419 if i
:= IndexRune(haystack
, 's'); i
!= 2 {
420 t
.Fatalf("'s' at %d; want 2", i
)
422 if i
:= IndexRune(haystack
, '世'); i
!= 4 {
423 t
.Fatalf("'世' at %d; want 4", i
)
427 if runtime
.Compiler
== "gccgo" {
428 t
.Log("does not work on gccgo without better escape analysis")
430 t
.Errorf("expected no allocations, got %f", allocs
)
435 // test count of a single byte across page offsets
436 func TestCountByte(t
*testing
.T
) {
437 b
:= make([]byte, 5015) // bigger than a page
438 windows
:= []int{1, 2, 3, 4, 15, 16, 17, 31, 32, 33, 63, 64, 65, 128}
439 testCountWindow
:= func(i
, window
int) {
440 for j
:= 0; j
< window
; j
++ {
442 p
:= Count(b
[i
:i
+window
], []byte{100})
444 t
.Errorf("TestCountByte.Count(%q, 100) = %d", b
[i
:i
+window
], p
)
449 maxWnd
:= windows
[len(windows
)-1]
451 for i
:= 0; i
<= 2*maxWnd
; i
++ {
452 for _
, window
:= range windows
{
453 if window
> len(b
[i
:]) {
456 testCountWindow(i
, window
)
457 for j
:= 0; j
< window
; j
++ {
462 for i
:= 4096 - (maxWnd
+ 1); i
< len(b
); i
++ {
463 for _
, window
:= range windows
{
464 if window
> len(b
[i
:]) {
467 testCountWindow(i
, window
)
468 for j
:= 0; j
< window
; j
++ {
475 // Make sure we don't count bytes outside our window
476 func TestCountByteNoMatch(t
*testing
.T
) {
477 b
:= make([]byte, 5015)
478 windows
:= []int{1, 2, 3, 4, 15, 16, 17, 31, 32, 33, 63, 64, 65, 128}
479 for i
:= 0; i
<= len(b
); i
++ {
480 for _
, window
:= range windows
{
481 if window
> len(b
[i
:]) {
484 // Fill the window with non-match
485 for j
:= 0; j
< window
; j
++ {
488 // Try to find something that doesn't exist
489 p
:= Count(b
[i
:i
+window
], []byte{0})
491 t
.Errorf("TestCountByteNoMatch(%q, 0) = %d", b
[i
:i
+window
], p
)
493 for j
:= 0; j
< window
; j
++ {
502 func valName(x
int) string {
503 if s
:= x
>> 20; s
<<20 == x
{
504 return fmt
.Sprintf("%dM", s
)
506 if s
:= x
>> 10; s
<<10 == x
{
507 return fmt
.Sprintf("%dK", s
)
512 func benchBytes(b
*testing
.B
, sizes
[]int, f
func(b
*testing
.B
, n
int)) {
513 for _
, n
:= range sizes
{
514 if isRaceBuilder
&& n
> 4<<10 {
517 b
.Run(valName(n
), func(b
*testing
.B
) {
519 bmbuf
= make([]byte, n
)
527 var indexSizes
= []int{10, 32, 4 << 10, 4 << 20, 64 << 20}
529 var isRaceBuilder
= strings
.HasSuffix(testenv
.Builder(), "-race")
531 func BenchmarkIndexByte(b
*testing
.B
) {
532 benchBytes(b
, indexSizes
, bmIndexByte(IndexByte
))
535 func BenchmarkIndexBytePortable(b
*testing
.B
) {
536 benchBytes(b
, indexSizes
, bmIndexByte(IndexBytePortable
))
539 func bmIndexByte(index
func([]byte, byte) int) func(b
*testing
.B
, n
int) {
540 return func(b
*testing
.B
, n
int) {
543 for i
:= 0; i
< b
.N
; i
++ {
546 b
.Fatal("bad index", j
)
553 func BenchmarkIndexRune(b
*testing
.B
) {
554 benchBytes(b
, indexSizes
, bmIndexRune(IndexRune
))
557 func BenchmarkIndexRuneASCII(b
*testing
.B
) {
558 benchBytes(b
, indexSizes
, bmIndexRuneASCII(IndexRune
))
561 func bmIndexRuneASCII(index
func([]byte, rune
) int) func(b
*testing
.B
, n
int) {
562 return func(b
*testing
.B
, n
int) {
565 for i
:= 0; i
< b
.N
; i
++ {
568 b
.Fatal("bad index", j
)
575 func bmIndexRune(index
func([]byte, rune
) int) func(b
*testing
.B
, n
int) {
576 return func(b
*testing
.B
, n
int) {
578 utf8
.EncodeRune(buf
[n
-3:], '世')
579 for i
:= 0; i
< b
.N
; i
++ {
582 b
.Fatal("bad index", j
)
591 func BenchmarkEqual(b
*testing
.B
) {
592 b
.Run("0", func(b
*testing
.B
) {
596 for i
:= 0; i
< b
.N
; i
++ {
597 eq
:= Equal(buf1
, buf2
)
604 sizes
:= []int{1, 6, 9, 15, 16, 20, 32, 4 << 10, 4 << 20, 64 << 20}
605 benchBytes(b
, sizes
, bmEqual(Equal
))
608 func bmEqual(equal
func([]byte, []byte) bool) func(b
*testing
.B
, n
int) {
609 return func(b
*testing
.B
, n
int) {
610 if len(bmbuf
) < 2*n
{
611 bmbuf
= make([]byte, 2*n
)
614 buf2
:= bmbuf
[n
: 2*n
]
617 for i
:= 0; i
< b
.N
; i
++ {
618 eq
:= equal(buf1
, buf2
)
628 func BenchmarkIndex(b
*testing
.B
) {
629 benchBytes(b
, indexSizes
, func(b
*testing
.B
, n
int) {
632 for i
:= 0; i
< b
.N
; i
++ {
633 j
:= Index(buf
, buf
[n
-7:])
635 b
.Fatal("bad index", j
)
642 func BenchmarkIndexEasy(b
*testing
.B
) {
643 benchBytes(b
, indexSizes
, func(b
*testing
.B
, n
int) {
647 for i
:= 0; i
< b
.N
; i
++ {
648 j
:= Index(buf
, buf
[n
-7:])
650 b
.Fatal("bad index", j
)
658 func BenchmarkCount(b
*testing
.B
) {
659 benchBytes(b
, indexSizes
, func(b
*testing
.B
, n
int) {
662 for i
:= 0; i
< b
.N
; i
++ {
663 j
:= Count(buf
, buf
[n
-7:])
665 b
.Fatal("bad count", j
)
672 func BenchmarkCountEasy(b
*testing
.B
) {
673 benchBytes(b
, indexSizes
, func(b
*testing
.B
, n
int) {
677 for i
:= 0; i
< b
.N
; i
++ {
678 j
:= Count(buf
, buf
[n
-7:])
680 b
.Fatal("bad count", j
)
688 func BenchmarkCountSingle(b
*testing
.B
) {
689 benchBytes(b
, indexSizes
, func(b
*testing
.B
, n
int) {
692 for i
:= 0; i
< len(buf
); i
+= step
{
695 expect
:= (len(buf
) + (step
- 1)) / step
696 for i
:= 0; i
< b
.N
; i
++ {
697 j
:= Count(buf
, []byte{1})
699 b
.Fatal("bad count", j
, expect
)
702 for i
:= 0; i
< len(buf
); i
++ {
708 type SplitTest
struct {
715 var splittests
= []SplitTest
{
716 {"", "", -1, []string{}},
718 {abcd
, "", 2, []string{"a", "bcd"}},
719 {abcd
, "a", -1, []string{"", "bcd"}},
720 {abcd
, "z", -1, []string{"abcd"}},
721 {abcd
, "", -1, []string{"a", "b", "c", "d"}},
722 {commas
, ",", -1, []string{"1", "2", "3", "4"}},
723 {dots
, "...", -1, []string{"1", ".2", ".3", ".4"}},
724 {faces
, "☹", -1, []string{"☺☻", ""}},
725 {faces
, "~", -1, []string{faces
}},
726 {faces
, "", -1, []string{"☺", "☻", "☹"}},
727 {"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}},
728 {"1 2", " ", 3, []string{"1", "2"}},
729 {"123", "", 2, []string{"1", "23"}},
730 {"123", "", 17, []string{"1", "2", "3"}},
733 func TestSplit(t
*testing
.T
) {
734 for _
, tt
:= range splittests
{
735 a
:= SplitN([]byte(tt
.s
), []byte(tt
.sep
), tt
.n
)
737 // Appending to the results should not change future results.
739 for _
, v
:= range a
{
743 result
:= sliceOfString(a
)
744 if !eq(result
, tt
.a
) {
745 t
.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt
.s
, tt
.sep
, tt
.n
, result
, tt
.a
)
748 if tt
.n
== 0 ||
len(a
) == 0 {
752 if want
:= tt
.a
[len(tt
.a
)-1] + "z"; string(x
) != want
{
753 t
.Errorf("last appended result was %s; want %s", x
, want
)
756 s
:= Join(a
, []byte(tt
.sep
))
757 if string(s
) != tt
.s
{
758 t
.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt
.s
, tt
.sep
, tt
.n
, tt
.sep
, s
)
761 b
:= Split([]byte(tt
.s
), []byte(tt
.sep
))
762 if !reflect
.DeepEqual(a
, b
) {
763 t
.Errorf("Split disagrees withSplitN(%q, %q, %d) = %v; want %v", tt
.s
, tt
.sep
, tt
.n
, b
, a
)
768 if cap(in
) == cap(out
) && &in
[:1][0] == &out
[:1][0] {
769 t
.Errorf("Join(%#v, %q) didn't copy", a
, tt
.sep
)
775 var splitaftertests
= []SplitTest
{
776 {abcd
, "a", -1, []string{"a", "bcd"}},
777 {abcd
, "z", -1, []string{"abcd"}},
778 {abcd
, "", -1, []string{"a", "b", "c", "d"}},
779 {commas
, ",", -1, []string{"1,", "2,", "3,", "4"}},
780 {dots
, "...", -1, []string{"1...", ".2...", ".3...", ".4"}},
781 {faces
, "☹", -1, []string{"☺☻☹", ""}},
782 {faces
, "~", -1, []string{faces
}},
783 {faces
, "", -1, []string{"☺", "☻", "☹"}},
784 {"1 2 3 4", " ", 3, []string{"1 ", "2 ", "3 4"}},
785 {"1 2 3", " ", 3, []string{"1 ", "2 ", "3"}},
786 {"1 2", " ", 3, []string{"1 ", "2"}},
787 {"123", "", 2, []string{"1", "23"}},
788 {"123", "", 17, []string{"1", "2", "3"}},
791 func TestSplitAfter(t
*testing
.T
) {
792 for _
, tt
:= range splitaftertests
{
793 a
:= SplitAfterN([]byte(tt
.s
), []byte(tt
.sep
), tt
.n
)
795 // Appending to the results should not change future results.
797 for _
, v
:= range a
{
801 result
:= sliceOfString(a
)
802 if !eq(result
, tt
.a
) {
803 t
.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt
.s
, tt
.sep
, tt
.n
, result
, tt
.a
)
807 if want
:= tt
.a
[len(tt
.a
)-1] + "z"; string(x
) != want
{
808 t
.Errorf("last appended result was %s; want %s", x
, want
)
812 if string(s
) != tt
.s
{
813 t
.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt
.s
, tt
.sep
, tt
.n
, tt
.sep
, s
)
816 b
:= SplitAfter([]byte(tt
.s
), []byte(tt
.sep
))
817 if !reflect
.DeepEqual(a
, b
) {
818 t
.Errorf("SplitAfter disagrees withSplitAfterN(%q, %q, %d) = %v; want %v", tt
.s
, tt
.sep
, tt
.n
, b
, a
)
824 type FieldsTest
struct {
829 var fieldstests
= []FieldsTest
{
832 {" \t ", []string{}},
833 {" abc ", []string{"abc"}},
834 {"1 2 3 4", []string{"1", "2", "3", "4"}},
835 {"1 2 3 4", []string{"1", "2", "3", "4"}},
836 {"1\t\t2\t\t3\t4", []string{"1", "2", "3", "4"}},
837 {"1\u20002\u20013\u20024", []string{"1", "2", "3", "4"}},
838 {"\u2000\u2001\u2002", []string{}},
839 {"\n™\t™\n", []string{"™", "™"}},
840 {faces
, []string{faces
}},
843 func TestFields(t
*testing
.T
) {
844 for _
, tt
:= range fieldstests
{
848 // Appending to the results should not change future results.
850 for _
, v
:= range a
{
854 result
:= sliceOfString(a
)
855 if !eq(result
, tt
.a
) {
856 t
.Errorf("Fields(%q) = %v; want %v", tt
.s
, a
, tt
.a
)
860 if string(b
) != tt
.s
{
861 t
.Errorf("slice changed to %s; want %s", string(b
), tt
.s
)
864 if want
:= tt
.a
[len(tt
.a
)-1] + "z"; string(x
) != want
{
865 t
.Errorf("last appended result was %s; want %s", x
, want
)
871 func TestFieldsFunc(t
*testing
.T
) {
872 for _
, tt
:= range fieldstests
{
873 a
:= FieldsFunc([]byte(tt
.s
), unicode
.IsSpace
)
874 result
:= sliceOfString(a
)
875 if !eq(result
, tt
.a
) {
876 t
.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt
.s
, a
, tt
.a
)
880 pred
:= func(c rune
) bool { return c
== 'X' }
881 var fieldsFuncTests
= []FieldsTest
{
884 {"XXhiXXX", []string{"hi"}},
885 {"aXXbXXXcX", []string{"a", "b", "c"}},
887 for _
, tt
:= range fieldsFuncTests
{
889 a
:= FieldsFunc(b
, pred
)
891 // Appending to the results should not change future results.
893 for _
, v
:= range a
{
897 result
:= sliceOfString(a
)
898 if !eq(result
, tt
.a
) {
899 t
.Errorf("FieldsFunc(%q) = %v, want %v", tt
.s
, a
, tt
.a
)
902 if string(b
) != tt
.s
{
903 t
.Errorf("slice changed to %s; want %s", b
, tt
.s
)
906 if want
:= tt
.a
[len(tt
.a
)-1] + "z"; string(x
) != want
{
907 t
.Errorf("last appended result was %s; want %s", x
, want
)
913 // Test case for any function which accepts and returns a byte slice.
914 // For ease of creation, we write the input byte slice as a string.
915 type StringTest
struct {
920 var upperTests
= []StringTest
{
922 {"ONLYUPPER", []byte("ONLYUPPER")},
923 {"abc", []byte("ABC")},
924 {"AbC123", []byte("ABC123")},
925 {"azAZ09_", []byte("AZAZ09_")},
926 {"longStrinGwitHmixofsmaLLandcAps", []byte("LONGSTRINGWITHMIXOFSMALLANDCAPS")},
927 {"long\u0250string\u0250with\u0250nonascii\u2C6Fchars", []byte("LONG\u2C6FSTRING\u2C6FWITH\u2C6FNONASCII\u2C6FCHARS")},
928 {"\u0250\u0250\u0250\u0250\u0250", []byte("\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F")}, // grows one byte per char
929 {"a\u0080\U0010FFFF", []byte("A\u0080\U0010FFFF")}, // test utf8.RuneSelf and utf8.MaxRune
932 var lowerTests
= []StringTest
{
934 {"abc", []byte("abc")},
935 {"AbC123", []byte("abc123")},
936 {"azAZ09_", []byte("azaz09_")},
937 {"longStrinGwitHmixofsmaLLandcAps", []byte("longstringwithmixofsmallandcaps")},
938 {"LONG\u2C6FSTRING\u2C6FWITH\u2C6FNONASCII\u2C6FCHARS", []byte("long\u0250string\u0250with\u0250nonascii\u0250chars")},
939 {"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", []byte("\u0251\u0251\u0251\u0251\u0251")}, // shrinks one byte per char
940 {"A\u0080\U0010FFFF", []byte("a\u0080\U0010FFFF")}, // test utf8.RuneSelf and utf8.MaxRune
943 const space
= "\t\v\r\f\n\u0085\u00a0\u2000\u3000"
945 var trimSpaceTests
= []StringTest
{
949 {"abc", []byte("abc")},
950 {space
+ "abc" + space
, []byte("abc")},
954 {" \t\r\n \t\t\r\r\n\n ", nil},
955 {" \t\r\n x\t\t\r\r\n\n ", []byte("x")},
956 {" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", []byte("x\t\t\r\r\ny")},
957 {"1 \t\r\n2", []byte("1 \t\r\n2")},
958 {" x\x80", []byte("x\x80")},
959 {" x\xc0", []byte("x\xc0")},
960 {"x \xc0\xc0 ", []byte("x \xc0\xc0")},
961 {"x \xc0", []byte("x \xc0")},
962 {"x \xc0 ", []byte("x \xc0")},
963 {"x \xc0\xc0 ", []byte("x \xc0\xc0")},
964 {"x ☺\xc0\xc0 ", []byte("x ☺\xc0\xc0")},
965 {"x ☺ ", []byte("x ☺")},
968 // Execute f on each test case. funcName should be the name of f; it's used
969 // in failure reports.
970 func runStringTests(t
*testing
.T
, f
func([]byte) []byte, funcName
string, testCases
[]StringTest
) {
971 for _
, tc
:= range testCases
{
972 actual
:= f([]byte(tc
.in
))
973 if actual
== nil && tc
.out
!= nil {
974 t
.Errorf("%s(%q) = nil; want %q", funcName
, tc
.in
, tc
.out
)
976 if actual
!= nil && tc
.out
== nil {
977 t
.Errorf("%s(%q) = %q; want nil", funcName
, tc
.in
, actual
)
979 if !Equal(actual
, tc
.out
) {
980 t
.Errorf("%s(%q) = %q; want %q", funcName
, tc
.in
, actual
, tc
.out
)
985 func tenRunes(r rune
) string {
986 runes
:= make([]rune
, 10)
987 for i
:= range runes
{
993 // User-defined self-inverse mapping function
994 func rot13(r rune
) rune
{
996 if r
>= 'a' && r
<= 'z' {
997 return ((r
- 'a' + step
) % 26) + 'a'
999 if r
>= 'A' && r
<= 'Z' {
1000 return ((r
- 'A' + step
) % 26) + 'A'
1005 func TestMap(t
*testing
.T
) {
1006 // Run a couple of awful growth/shrinkage tests
1009 // 1. Grow. This triggers two reallocations in Map.
1010 maxRune
:= func(r rune
) rune
{ return unicode
.MaxRune
}
1011 m
:= Map(maxRune
, []byte(a
))
1012 expect
:= tenRunes(unicode
.MaxRune
)
1013 if string(m
) != expect
{
1014 t
.Errorf("growing: expected %q got %q", expect
, m
)
1018 minRune
:= func(r rune
) rune
{ return 'a' }
1019 m
= Map(minRune
, []byte(tenRunes(unicode
.MaxRune
)))
1021 if string(m
) != expect
{
1022 t
.Errorf("shrinking: expected %q got %q", expect
, m
)
1026 m
= Map(rot13
, []byte("a to zed"))
1028 if string(m
) != expect
{
1029 t
.Errorf("rot13: expected %q got %q", expect
, m
)
1033 m
= Map(rot13
, Map(rot13
, []byte("a to zed")))
1035 if string(m
) != expect
{
1036 t
.Errorf("rot13: expected %q got %q", expect
, m
)
1040 dropNotLatin
:= func(r rune
) rune
{
1041 if unicode
.Is(unicode
.Latin
, r
) {
1046 m
= Map(dropNotLatin
, []byte("Hello, 세계"))
1048 if string(m
) != expect
{
1049 t
.Errorf("drop: expected %q got %q", expect
, m
)
1053 invalidRune
:= func(r rune
) rune
{
1054 return utf8
.MaxRune
+ 1
1056 m
= Map(invalidRune
, []byte("x"))
1058 if string(m
) != expect
{
1059 t
.Errorf("invalidRune: expected %q got %q", expect
, m
)
1063 func TestToUpper(t
*testing
.T
) { runStringTests(t
, ToUpper
, "ToUpper", upperTests
) }
1065 func TestToLower(t
*testing
.T
) { runStringTests(t
, ToLower
, "ToLower", lowerTests
) }
1067 func BenchmarkToUpper(b
*testing
.B
) {
1068 for _
, tc
:= range upperTests
{
1069 tin
:= []byte(tc
.in
)
1070 b
.Run(tc
.in
, func(b
*testing
.B
) {
1071 for i
:= 0; i
< b
.N
; i
++ {
1072 actual
:= ToUpper(tin
)
1073 if !Equal(actual
, tc
.out
) {
1074 b
.Errorf("ToUpper(%q) = %q; want %q", tc
.in
, actual
, tc
.out
)
1081 func BenchmarkToLower(b
*testing
.B
) {
1082 for _
, tc
:= range lowerTests
{
1083 tin
:= []byte(tc
.in
)
1084 b
.Run(tc
.in
, func(b
*testing
.B
) {
1085 for i
:= 0; i
< b
.N
; i
++ {
1086 actual
:= ToLower(tin
)
1087 if !Equal(actual
, tc
.out
) {
1088 b
.Errorf("ToLower(%q) = %q; want %q", tc
.in
, actual
, tc
.out
)
1095 var toValidUTF8Tests
= []struct {
1101 {"abc", "\uFFFD", "abc"},
1102 {"\uFDDD", "\uFFFD", "\uFDDD"},
1103 {"a\xffb", "\uFFFD", "a\uFFFDb"},
1104 {"a\xffb\uFFFD", "X", "aXb\uFFFD"},
1105 {"a☺\xffb☺\xC0\xAFc☺\xff", "", "a☺b☺c☺"},
1106 {"a☺\xffb☺\xC0\xAFc☺\xff", "日本語", "a☺日本語b☺日本語c☺日本語"},
1107 {"\xC0\xAF", "\uFFFD", "\uFFFD"},
1108 {"\xE0\x80\xAF", "\uFFFD", "\uFFFD"},
1109 {"\xed\xa0\x80", "abc", "abc"},
1110 {"\xed\xbf\xbf", "\uFFFD", "\uFFFD"},
1111 {"\xF0\x80\x80\xaf", "☺", "☺"},
1112 {"\xF8\x80\x80\x80\xAF", "\uFFFD", "\uFFFD"},
1113 {"\xFC\x80\x80\x80\x80\xAF", "\uFFFD", "\uFFFD"},
1116 func TestToValidUTF8(t
*testing
.T
) {
1117 for _
, tc
:= range toValidUTF8Tests
{
1118 got
:= ToValidUTF8([]byte(tc
.in
), []byte(tc
.repl
))
1119 if !Equal(got
, []byte(tc
.out
)) {
1120 t
.Errorf("ToValidUTF8(%q, %q) = %q; want %q", tc
.in
, tc
.repl
, got
, tc
.out
)
1125 func TestTrimSpace(t
*testing
.T
) { runStringTests(t
, TrimSpace
, "TrimSpace", trimSpaceTests
) }
1127 type RepeatTest
struct {
1132 var RepeatTests
= []RepeatTest
{
1138 {"-", "----------", 10},
1139 {"abc ", "abc abc abc ", 3},
1142 func TestRepeat(t
*testing
.T
) {
1143 for _
, tt
:= range RepeatTests
{
1144 tin
:= []byte(tt
.in
)
1145 tout
:= []byte(tt
.out
)
1146 a
:= Repeat(tin
, tt
.count
)
1147 if !Equal(a
, tout
) {
1148 t
.Errorf("Repeat(%q, %d) = %q; want %q", tin
, tt
.count
, a
, tout
)
1154 func repeat(b
[]byte, count
int) (err error
) {
1156 if r
:= recover(); r
!= nil {
1157 switch v
:= r
.(type) {
1161 err
= fmt
.Errorf("%s", v
)
1171 // See Issue golang.org/issue/16237
1172 func TestRepeatCatchesOverflow(t
*testing
.T
) {
1173 tests
:= [...]struct {
1178 0: {"--", -2147483647, "negative"},
1179 1: {"", int(^uint(0) >> 1), ""},
1181 3: {"gopher", 0, ""},
1182 4: {"-", -1, "negative"},
1183 5: {"--", -102, "negative"},
1184 6: {string(make([]byte, 255)), int((^uint(0))/255 + 1), "overflow"},
1187 for i
, tt
:= range tests
{
1188 err
:= repeat([]byte(tt
.s
), tt
.count
)
1189 if tt
.errStr
== "" {
1191 t
.Errorf("#%d panicked %v", i
, err
)
1196 if err
== nil ||
!strings
.Contains(err
.Error(), tt
.errStr
) {
1197 t
.Errorf("#%d expected %q got %q", i
, tt
.errStr
, err
)
1202 func runesEqual(a
, b
[]rune
) bool {
1203 if len(a
) != len(b
) {
1206 for i
, r
:= range a
{
1214 type RunesTest
struct {
1220 var RunesTests
= []RunesTest
{
1221 {"", []rune
{}, false},
1222 {" ", []rune
{32}, false},
1223 {"ABC", []rune
{65, 66, 67}, false},
1224 {"abc", []rune
{97, 98, 99}, false},
1225 {"\u65e5\u672c\u8a9e", []rune
{26085, 26412, 35486}, false},
1226 {"ab\x80c", []rune
{97, 98, 0xFFFD, 99}, true},
1227 {"ab\xc0c", []rune
{97, 98, 0xFFFD, 99}, true},
1230 func TestRunes(t
*testing
.T
) {
1231 for _
, tt
:= range RunesTests
{
1232 tin
:= []byte(tt
.in
)
1234 if !runesEqual(a
, tt
.out
) {
1235 t
.Errorf("Runes(%q) = %v; want %v", tin
, a
, tt
.out
)
1239 // can only test reassembly if we didn't lose information
1242 t
.Errorf("string(Runes(%q)) = %x; want %x", tin
, s
, tin
)
1248 type TrimTest
struct {
1253 var trimTests
= []TrimTest
{
1254 {"Trim", "abba", "a", "bb"},
1255 {"Trim", "abba", "ab", ""},
1256 {"TrimLeft", "abba", "ab", ""},
1257 {"TrimRight", "abba", "ab", ""},
1258 {"TrimLeft", "abba", "a", "bba"},
1259 {"TrimLeft", "abba", "b", "abba"},
1260 {"TrimRight", "abba", "a", "abb"},
1261 {"TrimRight", "abba", "b", "abba"},
1262 {"Trim", "<tag>", "<>", "tag"},
1263 {"Trim", "* listitem", " *", "listitem"},
1264 {"Trim", `"quote"`, `"`, "quote"},
1265 {"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
1266 {"Trim", "\x80test\xff", "\xff", "test"},
1267 {"Trim", " Ġ ", " ", "Ġ"},
1268 {"Trim", " Ġİ0", "0 ", "Ġİ"},
1269 //empty string tests
1270 {"Trim", "abba", "", "abba"},
1271 {"Trim", "", "123", ""},
1272 {"Trim", "", "", ""},
1273 {"TrimLeft", "abba", "", "abba"},
1274 {"TrimLeft", "", "123", ""},
1275 {"TrimLeft", "", "", ""},
1276 {"TrimRight", "abba", "", "abba"},
1277 {"TrimRight", "", "123", ""},
1278 {"TrimRight", "", "", ""},
1279 {"TrimRight", "☺\xc0", "☺", "☺\xc0"},
1280 {"TrimPrefix", "aabb", "a", "abb"},
1281 {"TrimPrefix", "aabb", "b", "aabb"},
1282 {"TrimSuffix", "aabb", "a", "aabb"},
1283 {"TrimSuffix", "aabb", "b", "aab"},
1286 func TestTrim(t
*testing
.T
) {
1287 for _
, tc
:= range trimTests
{
1289 var f
func([]byte, string) []byte
1290 var fb
func([]byte, []byte) []byte
1303 t
.Errorf("Undefined trim function %s", name
)
1307 actual
= string(f([]byte(tc
.in
), tc
.arg
))
1309 actual
= string(fb([]byte(tc
.in
), []byte(tc
.arg
)))
1311 if actual
!= tc
.out
{
1312 t
.Errorf("%s(%q, %q) = %q; want %q", name
, tc
.in
, tc
.arg
, actual
, tc
.out
)
1317 type predicate
struct {
1322 var isSpace
= predicate
{unicode
.IsSpace
, "IsSpace"}
1323 var isDigit
= predicate
{unicode
.IsDigit
, "IsDigit"}
1324 var isUpper
= predicate
{unicode
.IsUpper
, "IsUpper"}
1325 var isValidRune
= predicate
{
1327 return r
!= utf8
.RuneError
1332 type TrimFuncTest
struct {
1340 func not(p predicate
) predicate
{
1349 var trimFuncTests
= []TrimFuncTest
{
1350 {isSpace
, space
+ " hello " + space
,
1352 []byte("hello " + space
),
1353 []byte(space
+ " hello")},
1354 {isDigit
, "\u0e50\u0e5212hello34\u0e50\u0e51",
1356 []byte("hello34\u0e50\u0e51"),
1357 []byte("\u0e50\u0e5212hello")},
1358 {isUpper
, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F",
1360 []byte("helloEF\u2C6F\u2C6FGH\u2C6F\u2C6F"),
1361 []byte("\u2C6F\u2C6F\u2C6F\u2C6FABCDhello")},
1362 {not(isSpace
), "hello" + space
+ "hello",
1364 []byte(space
+ "hello"),
1365 []byte("hello" + space
)},
1366 {not(isDigit
), "hello\u0e50\u0e521234\u0e50\u0e51helo",
1367 []byte("\u0e50\u0e521234\u0e50\u0e51"),
1368 []byte("\u0e50\u0e521234\u0e50\u0e51helo"),
1369 []byte("hello\u0e50\u0e521234\u0e50\u0e51")},
1370 {isValidRune
, "ab\xc0a\xc0cd",
1371 []byte("\xc0a\xc0"),
1372 []byte("\xc0a\xc0cd"),
1373 []byte("ab\xc0a\xc0")},
1374 {not(isValidRune
), "\xc0a\xc0",
1378 // The nils returned by TrimLeftFunc are odd behavior, but we need
1379 // to preserve backwards compatibility.
1390 func TestTrimFunc(t
*testing
.T
) {
1391 for _
, tc
:= range trimFuncTests
{
1392 trimmers
:= []struct {
1394 trim
func(s
[]byte, f
func(r rune
) bool) []byte
1397 {"TrimFunc", TrimFunc
, tc
.trimOut
},
1398 {"TrimLeftFunc", TrimLeftFunc
, tc
.leftOut
},
1399 {"TrimRightFunc", TrimRightFunc
, tc
.rightOut
},
1401 for _
, trimmer
:= range trimmers
{
1402 actual
:= trimmer
.trim([]byte(tc
.in
), tc
.f
.f
)
1403 if actual
== nil && trimmer
.out
!= nil {
1404 t
.Errorf("%s(%q, %q) = nil; want %q", trimmer
.name
, tc
.in
, tc
.f
.name
, trimmer
.out
)
1406 if actual
!= nil && trimmer
.out
== nil {
1407 t
.Errorf("%s(%q, %q) = %q; want nil", trimmer
.name
, tc
.in
, tc
.f
.name
, actual
)
1409 if !Equal(actual
, trimmer
.out
) {
1410 t
.Errorf("%s(%q, %q) = %q; want %q", trimmer
.name
, tc
.in
, tc
.f
.name
, actual
, trimmer
.out
)
1416 type IndexFuncTest
struct {
1422 var indexFuncTests
= []IndexFuncTest
{
1423 {"", isValidRune
, -1, -1},
1424 {"abc", isDigit
, -1, -1},
1425 {"0123", isDigit
, 0, 3},
1426 {"a1b", isDigit
, 1, 1},
1427 {space
, isSpace
, 0, len(space
) - 3}, // last rune in space is 3 bytes
1428 {"\u0e50\u0e5212hello34\u0e50\u0e51", isDigit
, 0, 18},
1429 {"\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", isUpper
, 0, 34},
1430 {"12\u0e50\u0e52hello34\u0e50\u0e51", not(isDigit
), 8, 12},
1432 // tests of invalid UTF-8
1433 {"\x801", isDigit
, 1, 1},
1434 {"\x80abc", isDigit
, -1, -1},
1435 {"\xc0a\xc0", isValidRune
, 1, 1},
1436 {"\xc0a\xc0", not(isValidRune
), 0, 2},
1437 {"\xc0☺\xc0", not(isValidRune
), 0, 4},
1438 {"\xc0☺\xc0\xc0", not(isValidRune
), 0, 5},
1439 {"ab\xc0a\xc0cd", not(isValidRune
), 2, 4},
1440 {"a\xe0\x80cd", not(isValidRune
), 1, 2},
1443 func TestIndexFunc(t
*testing
.T
) {
1444 for _
, tc
:= range indexFuncTests
{
1445 first
:= IndexFunc([]byte(tc
.in
), tc
.f
.f
)
1446 if first
!= tc
.first
{
1447 t
.Errorf("IndexFunc(%q, %s) = %d; want %d", tc
.in
, tc
.f
.name
, first
, tc
.first
)
1449 last
:= LastIndexFunc([]byte(tc
.in
), tc
.f
.f
)
1450 if last
!= tc
.last
{
1451 t
.Errorf("LastIndexFunc(%q, %s) = %d; want %d", tc
.in
, tc
.f
.name
, last
, tc
.last
)
1456 type ReplaceTest
struct {
1463 var ReplaceTests
= []ReplaceTest
{
1464 {"hello", "l", "L", 0, "hello"},
1465 {"hello", "l", "L", -1, "heLLo"},
1466 {"hello", "x", "X", -1, "hello"},
1467 {"", "x", "X", -1, ""},
1468 {"radar", "r", "<r>", -1, "<r>ada<r>"},
1469 {"", "", "<>", -1, "<>"},
1470 {"banana", "a", "<>", -1, "b<>n<>n<>"},
1471 {"banana", "a", "<>", 1, "b<>nana"},
1472 {"banana", "a", "<>", 1000, "b<>n<>n<>"},
1473 {"banana", "an", "<>", -1, "b<><>a"},
1474 {"banana", "ana", "<>", -1, "b<>na"},
1475 {"banana", "", "<>", -1, "<>b<>a<>n<>a<>n<>a<>"},
1476 {"banana", "", "<>", 10, "<>b<>a<>n<>a<>n<>a<>"},
1477 {"banana", "", "<>", 6, "<>b<>a<>n<>a<>n<>a"},
1478 {"banana", "", "<>", 5, "<>b<>a<>n<>a<>na"},
1479 {"banana", "", "<>", 1, "<>banana"},
1480 {"banana", "a", "a", -1, "banana"},
1481 {"banana", "a", "a", 1, "banana"},
1482 {"☺☻☹", "", "<>", -1, "<>☺<>☻<>☹<>"},
1485 func TestReplace(t
*testing
.T
) {
1486 for _
, tt
:= range ReplaceTests
{
1487 in
:= append([]byte(tt
.in
), "<spare>"...)
1488 in
= in
[:len(tt
.in
)]
1489 out
:= Replace(in
, []byte(tt
.old
), []byte(tt
.new), tt
.n
)
1490 if s
:= string(out
); s
!= tt
.out
{
1491 t
.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt
.in
, tt
.old
, tt
.new, tt
.n
, s
, tt
.out
)
1493 if cap(in
) == cap(out
) && &in
[:1][0] == &out
[:1][0] {
1494 t
.Errorf("Replace(%q, %q, %q, %d) didn't copy", tt
.in
, tt
.old
, tt
.new, tt
.n
)
1497 out
:= ReplaceAll(in
, []byte(tt
.old
), []byte(tt
.new))
1498 if s
:= string(out
); s
!= tt
.out
{
1499 t
.Errorf("ReplaceAll(%q, %q, %q) = %q, want %q", tt
.in
, tt
.old
, tt
.new, s
, tt
.out
)
1505 type TitleTest
struct {
1509 var TitleTests
= []TitleTest
{
1512 {" aaa aaa aaa ", " Aaa Aaa Aaa "},
1513 {" Aaa Aaa Aaa ", " Aaa Aaa Aaa "},
1514 {"123a456", "123a456"},
1515 {"double-blind", "Double-Blind"},
1517 {"with_underscore", "With_underscore"},
1518 {"unicode \xe2\x80\xa8 line separator", "Unicode \xe2\x80\xa8 Line Separator"},
1521 func TestTitle(t
*testing
.T
) {
1522 for _
, tt
:= range TitleTests
{
1523 if s
:= string(Title([]byte(tt
.in
))); s
!= tt
.out
{
1524 t
.Errorf("Title(%q) = %q, want %q", tt
.in
, s
, tt
.out
)
1529 var ToTitleTests
= []TitleTest
{
1532 {" aaa aaa aaa ", " AAA AAA AAA "},
1533 {" Aaa Aaa Aaa ", " AAA AAA AAA "},
1534 {"123a456", "123A456"},
1535 {"double-blind", "DOUBLE-BLIND"},
1539 func TestToTitle(t
*testing
.T
) {
1540 for _
, tt
:= range ToTitleTests
{
1541 if s
:= string(ToTitle([]byte(tt
.in
))); s
!= tt
.out
{
1542 t
.Errorf("ToTitle(%q) = %q, want %q", tt
.in
, s
, tt
.out
)
1547 var EqualFoldTests
= []struct {
1551 {"abc", "abc", true},
1552 {"ABcd", "ABcd", true},
1553 {"123abc", "123ABC", true},
1554 {"αβδ", "ΑΒΔ", true},
1555 {"abc", "xyz", false},
1556 {"abc", "XYZ", false},
1557 {"abcdefghijk", "abcdefghijX", false},
1558 {"abcdefghijk", "abcdefghij\u212A", true},
1559 {"abcdefghijK", "abcdefghij\u212A", true},
1560 {"abcdefghijkz", "abcdefghij\u212Ay", false},
1561 {"abcdefghijKz", "abcdefghij\u212Ay", false},
1564 func TestEqualFold(t
*testing
.T
) {
1565 for _
, tt
:= range EqualFoldTests
{
1566 if out
:= EqualFold([]byte(tt
.s
), []byte(tt
.t
)); out
!= tt
.out
{
1567 t
.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt
.s
, tt
.t
, out
, tt
.out
)
1569 if out
:= EqualFold([]byte(tt
.t
), []byte(tt
.s
)); out
!= tt
.out
{
1570 t
.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt
.t
, tt
.s
, out
, tt
.out
)
1575 var cutTests
= []struct {
1577 before
, after
string
1580 {"abc", "b", "a", "c", true},
1581 {"abc", "a", "", "bc", true},
1582 {"abc", "c", "ab", "", true},
1583 {"abc", "abc", "", "", true},
1584 {"abc", "", "", "abc", true},
1585 {"abc", "d", "abc", "", false},
1586 {"", "d", "", "", false},
1587 {"", "", "", "", true},
1590 func TestCut(t
*testing
.T
) {
1591 for _
, tt
:= range cutTests
{
1592 if before
, after
, found
:= Cut([]byte(tt
.s
), []byte(tt
.sep
)); string(before
) != tt
.before ||
string(after
) != tt
.after || found
!= tt
.found
{
1593 t
.Errorf("Cut(%q, %q) = %q, %q, %v, want %q, %q, %v", tt
.s
, tt
.sep
, before
, after
, found
, tt
.before
, tt
.after
, tt
.found
)
1598 func TestBufferGrowNegative(t
*testing
.T
) {
1600 if err
:= recover(); err
== nil {
1601 t
.Fatal("Grow(-1) should have panicked")
1608 func TestBufferTruncateNegative(t
*testing
.T
) {
1610 if err
:= recover(); err
== nil {
1611 t
.Fatal("Truncate(-1) should have panicked")
1618 func TestBufferTruncateOutOfRange(t
*testing
.T
) {
1620 if err
:= recover(); err
== nil {
1621 t
.Fatal("Truncate(20) should have panicked")
1625 b
.Write(make([]byte, 10))
1629 var containsTests
= []struct {
1633 {[]byte("hello"), []byte("hel"), true},
1634 {[]byte("日本語"), []byte("日本"), true},
1635 {[]byte("hello"), []byte("Hello, world"), false},
1636 {[]byte("東京"), []byte("京東"), false},
1639 func TestContains(t
*testing
.T
) {
1640 for _
, tt
:= range containsTests
{
1641 if got
:= Contains(tt
.b
, tt
.subslice
); got
!= tt
.want
{
1642 t
.Errorf("Contains(%q, %q) = %v, want %v", tt
.b
, tt
.subslice
, got
, tt
.want
)
1647 var ContainsAnyTests
= []struct {
1652 {[]byte(""), "", false},
1653 {[]byte(""), "a", false},
1654 {[]byte(""), "abc", false},
1655 {[]byte("a"), "", false},
1656 {[]byte("a"), "a", true},
1657 {[]byte("aaa"), "a", true},
1658 {[]byte("abc"), "xyz", false},
1659 {[]byte("abc"), "xcz", true},
1660 {[]byte("a☺b☻c☹d"), "uvw☻xyz", true},
1661 {[]byte("aRegExp*"), ".(|)*+?^$[]", true},
1662 {[]byte(dots
+ dots
+ dots
), " ", false},
1665 func TestContainsAny(t
*testing
.T
) {
1666 for _
, ct
:= range ContainsAnyTests
{
1667 if ContainsAny(ct
.b
, ct
.substr
) != ct
.expected
{
1668 t
.Errorf("ContainsAny(%s, %s) = %v, want %v",
1669 ct
.b
, ct
.substr
, !ct
.expected
, ct
.expected
)
1674 var ContainsRuneTests
= []struct {
1679 {[]byte(""), 'a', false},
1680 {[]byte("a"), 'a', true},
1681 {[]byte("aaa"), 'a', true},
1682 {[]byte("abc"), 'y', false},
1683 {[]byte("abc"), 'c', true},
1684 {[]byte("a☺b☻c☹d"), 'x', false},
1685 {[]byte("a☺b☻c☹d"), '☻', true},
1686 {[]byte("aRegExp*"), '*', true},
1689 func TestContainsRune(t
*testing
.T
) {
1690 for _
, ct
:= range ContainsRuneTests
{
1691 if ContainsRune(ct
.b
, ct
.r
) != ct
.expected
{
1692 t
.Errorf("ContainsRune(%q, %q) = %v, want %v",
1693 ct
.b
, ct
.r
, !ct
.expected
, ct
.expected
)
1698 var makeFieldsInput
= func() []byte {
1699 x
:= make([]byte, 1<<20)
1700 // Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space.
1702 switch rand
.Intn(10) {
1706 if i
> 0 && x
[i
-1] == 'x' {
1718 var makeFieldsInputASCII
= func() []byte {
1719 x
:= make([]byte, 1<<20)
1720 // Input is ~10% space, rest ASCII non-space.
1722 if rand
.Intn(10) == 0 {
1731 var bytesdata
= []struct {
1735 {"ASCII", makeFieldsInputASCII()},
1736 {"Mixed", makeFieldsInput()},
1739 func BenchmarkFields(b
*testing
.B
) {
1740 for _
, sd
:= range bytesdata
{
1741 b
.Run(sd
.name
, func(b
*testing
.B
) {
1742 for j
:= 1 << 4; j
<= 1<<20; j
<<= 4 {
1743 b
.Run(fmt
.Sprintf("%d", j
), func(b
*testing
.B
) {
1745 b
.SetBytes(int64(j
))
1747 for i
:= 0; i
< b
.N
; i
++ {
1756 func BenchmarkFieldsFunc(b
*testing
.B
) {
1757 for _
, sd
:= range bytesdata
{
1758 b
.Run(sd
.name
, func(b
*testing
.B
) {
1759 for j
:= 1 << 4; j
<= 1<<20; j
<<= 4 {
1760 b
.Run(fmt
.Sprintf("%d", j
), func(b
*testing
.B
) {
1762 b
.SetBytes(int64(j
))
1764 for i
:= 0; i
< b
.N
; i
++ {
1765 FieldsFunc(data
, unicode
.IsSpace
)
1773 func BenchmarkTrimSpace(b
*testing
.B
) {
1778 {"NoTrim", []byte("typical")},
1779 {"ASCII", []byte(" foo bar ")},
1780 {"SomeNonASCII", []byte(" \u2000\t\r\n x\t\t\r\r\ny\n \u3000 ")},
1781 {"JustNonASCII", []byte("\u2000\u2000\u2000☺☺☺☺\u3000\u3000\u3000")},
1783 for _
, test
:= range tests
{
1784 b
.Run(test
.name
, func(b
*testing
.B
) {
1785 for i
:= 0; i
< b
.N
; i
++ {
1786 TrimSpace(test
.input
)
1792 func BenchmarkToValidUTF8(b
*testing
.B
) {
1797 {"Valid", []byte("typical")},
1798 {"InvalidASCII", []byte("foo\xffbar")},
1799 {"InvalidNonASCII", []byte("日本語\xff日本語")},
1801 replacement
:= []byte("\uFFFD")
1803 for _
, test
:= range tests
{
1804 b
.Run(test
.name
, func(b
*testing
.B
) {
1805 for i
:= 0; i
< b
.N
; i
++ {
1806 ToValidUTF8(test
.input
, replacement
)
1812 func makeBenchInputHard() []byte {
1813 tokens
:= [...]string{
1814 "<a>", "<p>", "<b>", "<strong>",
1815 "</a>", "</p>", "</b>", "</strong>",
1818 x
:= make([]byte, 0, 1<<20)
1820 i
:= rand
.Intn(len(tokens
))
1821 if len(x
)+len(tokens
[i
]) >= 1<<20 {
1824 x
= append(x
, tokens
[i
]...)
1829 var benchInputHard
= makeBenchInputHard()
1831 func benchmarkIndexHard(b
*testing
.B
, sep
[]byte) {
1832 for i
:= 0; i
< b
.N
; i
++ {
1833 Index(benchInputHard
, sep
)
1837 func benchmarkLastIndexHard(b
*testing
.B
, sep
[]byte) {
1838 for i
:= 0; i
< b
.N
; i
++ {
1839 LastIndex(benchInputHard
, sep
)
1843 func benchmarkCountHard(b
*testing
.B
, sep
[]byte) {
1844 for i
:= 0; i
< b
.N
; i
++ {
1845 Count(benchInputHard
, sep
)
1849 func BenchmarkIndexHard1(b
*testing
.B
) { benchmarkIndexHard(b
, []byte("<>")) }
1850 func BenchmarkIndexHard2(b
*testing
.B
) { benchmarkIndexHard(b
, []byte("</pre>")) }
1851 func BenchmarkIndexHard3(b
*testing
.B
) { benchmarkIndexHard(b
, []byte("<b>hello world</b>")) }
1852 func BenchmarkIndexHard4(b
*testing
.B
) {
1853 benchmarkIndexHard(b
, []byte("<pre><b>hello</b><strong>world</strong></pre>"))
1856 func BenchmarkLastIndexHard1(b
*testing
.B
) { benchmarkLastIndexHard(b
, []byte("<>")) }
1857 func BenchmarkLastIndexHard2(b
*testing
.B
) { benchmarkLastIndexHard(b
, []byte("</pre>")) }
1858 func BenchmarkLastIndexHard3(b
*testing
.B
) { benchmarkLastIndexHard(b
, []byte("<b>hello world</b>")) }
1860 func BenchmarkCountHard1(b
*testing
.B
) { benchmarkCountHard(b
, []byte("<>")) }
1861 func BenchmarkCountHard2(b
*testing
.B
) { benchmarkCountHard(b
, []byte("</pre>")) }
1862 func BenchmarkCountHard3(b
*testing
.B
) { benchmarkCountHard(b
, []byte("<b>hello world</b>")) }
1864 func BenchmarkSplitEmptySeparator(b
*testing
.B
) {
1865 for i
:= 0; i
< b
.N
; i
++ {
1866 Split(benchInputHard
, nil)
1870 func BenchmarkSplitSingleByteSeparator(b
*testing
.B
) {
1872 for i
:= 0; i
< b
.N
; i
++ {
1873 Split(benchInputHard
, sep
)
1877 func BenchmarkSplitMultiByteSeparator(b
*testing
.B
) {
1878 sep
:= []byte("hello")
1879 for i
:= 0; i
< b
.N
; i
++ {
1880 Split(benchInputHard
, sep
)
1884 func BenchmarkSplitNSingleByteSeparator(b
*testing
.B
) {
1886 for i
:= 0; i
< b
.N
; i
++ {
1887 SplitN(benchInputHard
, sep
, 10)
1891 func BenchmarkSplitNMultiByteSeparator(b
*testing
.B
) {
1892 sep
:= []byte("hello")
1893 for i
:= 0; i
< b
.N
; i
++ {
1894 SplitN(benchInputHard
, sep
, 10)
1898 func BenchmarkRepeat(b
*testing
.B
) {
1899 for i
:= 0; i
< b
.N
; i
++ {
1900 Repeat([]byte("-"), 80)
1904 func BenchmarkBytesCompare(b
*testing
.B
) {
1905 for n
:= 1; n
<= 2048; n
<<= 1 {
1906 b
.Run(fmt
.Sprint(n
), func(b
*testing
.B
) {
1907 var x
= make([]byte, n
)
1908 var y
= make([]byte, n
)
1910 for i
:= 0; i
< n
; i
++ {
1914 for i
:= 0; i
< n
; i
++ {
1919 for i
:= 0; i
< b
.N
; i
++ {
1926 func BenchmarkIndexAnyASCII(b
*testing
.B
) {
1927 x
:= Repeat([]byte{'#'}, 2048) // Never matches set
1928 cs
:= "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz"
1929 for k
:= 1; k
<= 2048; k
<<= 4 {
1930 for j
:= 1; j
<= 64; j
<<= 1 {
1931 b
.Run(fmt
.Sprintf("%d:%d", k
, j
), func(b
*testing
.B
) {
1932 for i
:= 0; i
< b
.N
; i
++ {
1933 IndexAny(x
[:k
], cs
[:j
])
1940 func BenchmarkIndexAnyUTF8(b
*testing
.B
) {
1941 x
:= Repeat([]byte{'#'}, 2048) // Never matches set
1942 cs
:= "你好世界, hello world. 你好世界, hello world. 你好世界, hello world."
1943 for k
:= 1; k
<= 2048; k
<<= 4 {
1944 for j
:= 1; j
<= 64; j
<<= 1 {
1945 b
.Run(fmt
.Sprintf("%d:%d", k
, j
), func(b
*testing
.B
) {
1946 for i
:= 0; i
< b
.N
; i
++ {
1947 IndexAny(x
[:k
], cs
[:j
])
1954 func BenchmarkLastIndexAnyASCII(b
*testing
.B
) {
1955 x
:= Repeat([]byte{'#'}, 2048) // Never matches set
1956 cs
:= "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz"
1957 for k
:= 1; k
<= 2048; k
<<= 4 {
1958 for j
:= 1; j
<= 64; j
<<= 1 {
1959 b
.Run(fmt
.Sprintf("%d:%d", k
, j
), func(b
*testing
.B
) {
1960 for i
:= 0; i
< b
.N
; i
++ {
1961 LastIndexAny(x
[:k
], cs
[:j
])
1968 func BenchmarkLastIndexAnyUTF8(b
*testing
.B
) {
1969 x
:= Repeat([]byte{'#'}, 2048) // Never matches set
1970 cs
:= "你好世界, hello world. 你好世界, hello world. 你好世界, hello world."
1971 for k
:= 1; k
<= 2048; k
<<= 4 {
1972 for j
:= 1; j
<= 64; j
<<= 1 {
1973 b
.Run(fmt
.Sprintf("%d:%d", k
, j
), func(b
*testing
.B
) {
1974 for i
:= 0; i
< b
.N
; i
++ {
1975 LastIndexAny(x
[:k
], cs
[:j
])
1982 func BenchmarkTrimASCII(b
*testing
.B
) {
1983 cs
:= "0123456789abcdef"
1984 for k
:= 1; k
<= 4096; k
<<= 4 {
1985 for j
:= 1; j
<= 16; j
<<= 1 {
1986 b
.Run(fmt
.Sprintf("%d:%d", k
, j
), func(b
*testing
.B
) {
1987 x
:= Repeat([]byte(cs
[:j
]), k
) // Always matches set
1988 for i
:= 0; i
< b
.N
; i
++ {
1996 func BenchmarkTrimByte(b
*testing
.B
) {
1997 x
:= []byte(" the quick brown fox ")
1998 for i
:= 0; i
< b
.N
; i
++ {
2003 func BenchmarkIndexPeriodic(b
*testing
.B
) {
2005 for _
, skip
:= range [...]int{2, 4, 8, 16, 32, 64} {
2006 b
.Run(fmt
.Sprintf("IndexPeriodic%d", skip
), func(b
*testing
.B
) {
2007 buf
:= make([]byte, 1<<16)
2008 for i
:= 0; i
< len(buf
); i
+= skip
{
2011 for i
:= 0; i
< b
.N
; i
++ {