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.
19 func eq(a
, b
[]string) bool {
23 for i
:= 0; i
< len(a
); i
++ {
33 var commas
= "1,2,3,4"
34 var dots
= "1....2....3....4"
36 type IndexTest
struct {
42 var indexTests
= []IndexTest
{
48 {"oofofoofooo", "f", 2},
49 {"oofofoofooo", "foo", 4},
50 {"barfoobarfoo", "foo", 3},
53 {"abcABCabc", "A", 3},
54 // cases with one byte strings - test special case in Index()
64 var lastIndexTests
= []IndexTest
{
71 {"oofofoofooo", "f", 7},
72 {"oofofoofooo", "foo", 7},
73 {"barfoobarfoo", "foo", 9},
76 {"abcABCabc", "A", 3},
77 {"abcABCabc", "a", 6},
80 var indexAnyTests
= []IndexTest
{
89 {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
90 {"aRegExp*", ".(|)*+?^$[]", 7},
91 {dots
+ dots
+ dots
, " ", -1},
93 var lastIndexAnyTests
= []IndexTest
{
102 {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
103 {"a.RegExp*", ".(|)*+?^$[]", 8},
104 {dots
+ dots
+ dots
, " ", -1},
107 // Execute f on each test case. funcName should be the name of f; it's used
108 // in failure reports.
109 func runIndexTests(t
*testing
.T
, f
func(s
, sep
string) int, funcName
string, testCases
[]IndexTest
) {
110 for _
, test
:= range testCases
{
111 actual
:= f(test
.s
, test
.sep
)
112 if actual
!= test
.out
{
113 t
.Errorf("%s(%q,%q) = %v; want %v", funcName
, test
.s
, test
.sep
, actual
, test
.out
)
118 func TestIndex(t
*testing
.T
) { runIndexTests(t
, Index
, "Index", indexTests
) }
119 func TestLastIndex(t
*testing
.T
) { runIndexTests(t
, LastIndex
, "LastIndex", lastIndexTests
) }
120 func TestIndexAny(t
*testing
.T
) { runIndexTests(t
, IndexAny
, "IndexAny", indexAnyTests
) }
121 func TestLastIndexAny(t
*testing
.T
) { runIndexTests(t
, LastIndexAny
, "LastIndexAny", lastIndexAnyTests
) }
123 var indexRuneTests
= []struct {
129 {"some_text=some_value", '=', 9},
134 func TestIndexRune(t
*testing
.T
) {
135 for _
, test
:= range indexRuneTests
{
136 if actual
:= IndexRune(test
.s
, test
.rune
); actual
!= test
.out
{
137 t
.Errorf("IndexRune(%q,%d)= %v; want %v", test
.s
, test
.rune
, actual
, test
.out
)
142 const benchmarkString
= "some_text=some☺value"
144 func BenchmarkIndexRune(b
*testing
.B
) {
145 if got
:= IndexRune(benchmarkString
, '☺'); got
!= 14 {
146 b
.Fatalf("wrong index: expected 14, got=%d", got
)
148 for i
:= 0; i
< b
.N
; i
++ {
149 IndexRune(benchmarkString
, '☺')
153 func BenchmarkIndexRuneFastPath(b
*testing
.B
) {
154 if got
:= IndexRune(benchmarkString
, 'v'); got
!= 17 {
155 b
.Fatalf("wrong index: expected 17, got=%d", got
)
157 for i
:= 0; i
< b
.N
; i
++ {
158 IndexRune(benchmarkString
, 'v')
162 func BenchmarkIndex(b
*testing
.B
) {
163 if got
:= Index(benchmarkString
, "v"); got
!= 17 {
164 b
.Fatalf("wrong index: expected 17, got=%d", got
)
166 for i
:= 0; i
< b
.N
; i
++ {
167 Index(benchmarkString
, "v")
171 func BenchmarkIndexByte(b
*testing
.B
) {
172 if got
:= IndexByte(benchmarkString
, 'v'); got
!= 17 {
173 b
.Fatalf("wrong index: expected 17, got=%d", got
)
175 for i
:= 0; i
< b
.N
; i
++ {
176 IndexByte(benchmarkString
, 'v')
180 var explodetests
= []struct {
185 {"", -1, []string{}},
186 {abcd
, 4, []string{"a", "b", "c", "d"}},
187 {faces
, 3, []string{"☺", "☻", "☹"}},
188 {abcd
, 2, []string{"a", "bcd"}},
191 func TestExplode(t
*testing
.T
) {
192 for _
, tt
:= range explodetests
{
193 a
:= SplitN(tt
.s
, "", tt
.n
)
195 t
.Errorf("explode(%q, %d) = %v; want %v", tt
.s
, tt
.n
, a
, tt
.a
)
200 t
.Errorf(`Join(explode(%q, %d), "") = %q`, tt
.s
, tt
.n
, s
)
205 type SplitTest
struct {
212 var splittests
= []SplitTest
{
214 {abcd
, "a", -1, []string{"", "bcd"}},
215 {abcd
, "z", -1, []string{"abcd"}},
216 {abcd
, "", -1, []string{"a", "b", "c", "d"}},
217 {commas
, ",", -1, []string{"1", "2", "3", "4"}},
218 {dots
, "...", -1, []string{"1", ".2", ".3", ".4"}},
219 {faces
, "☹", -1, []string{"☺☻", ""}},
220 {faces
, "~", -1, []string{faces
}},
221 {faces
, "", -1, []string{"☺", "☻", "☹"}},
222 {"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}},
223 {"1 2", " ", 3, []string{"1", "2"}},
224 {"123", "", 2, []string{"1", "23"}},
225 {"123", "", 17, []string{"1", "2", "3"}},
228 func TestSplit(t
*testing
.T
) {
229 for _
, tt
:= range splittests
{
230 a
:= SplitN(tt
.s
, tt
.sep
, tt
.n
)
232 t
.Errorf("Split(%q, %q, %d) = %v; want %v", tt
.s
, tt
.sep
, tt
.n
, a
, tt
.a
)
240 t
.Errorf("Join(Split(%q, %q, %d), %q) = %q", tt
.s
, tt
.sep
, tt
.n
, tt
.sep
, s
)
243 b
:= Split(tt
.s
, tt
.sep
)
244 if !reflect
.DeepEqual(a
, b
) {
245 t
.Errorf("Split disagrees with SplitN(%q, %q, %d) = %v; want %v", tt
.s
, tt
.sep
, tt
.n
, b
, a
)
251 var splitaftertests
= []SplitTest
{
252 {abcd
, "a", -1, []string{"a", "bcd"}},
253 {abcd
, "z", -1, []string{"abcd"}},
254 {abcd
, "", -1, []string{"a", "b", "c", "d"}},
255 {commas
, ",", -1, []string{"1,", "2,", "3,", "4"}},
256 {dots
, "...", -1, []string{"1...", ".2...", ".3...", ".4"}},
257 {faces
, "☹", -1, []string{"☺☻☹", ""}},
258 {faces
, "~", -1, []string{faces
}},
259 {faces
, "", -1, []string{"☺", "☻", "☹"}},
260 {"1 2 3 4", " ", 3, []string{"1 ", "2 ", "3 4"}},
261 {"1 2 3", " ", 3, []string{"1 ", "2 ", "3"}},
262 {"1 2", " ", 3, []string{"1 ", "2"}},
263 {"123", "", 2, []string{"1", "23"}},
264 {"123", "", 17, []string{"1", "2", "3"}},
267 func TestSplitAfter(t
*testing
.T
) {
268 for _
, tt
:= range splitaftertests
{
269 a
:= SplitAfterN(tt
.s
, tt
.sep
, tt
.n
)
271 t
.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt
.s
, tt
.sep
, tt
.n
, a
, tt
.a
)
276 t
.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt
.s
, tt
.sep
, tt
.n
, tt
.sep
, s
)
279 b
:= SplitAfter(tt
.s
, tt
.sep
)
280 if !reflect
.DeepEqual(a
, b
) {
281 t
.Errorf("SplitAfter disagrees with SplitAfterN(%q, %q, %d) = %v; want %v", tt
.s
, tt
.sep
, tt
.n
, b
, a
)
287 type FieldsTest
struct {
292 var fieldstests
= []FieldsTest
{
295 {" \t ", []string{}},
296 {" abc ", []string{"abc"}},
297 {"1 2 3 4", []string{"1", "2", "3", "4"}},
298 {"1 2 3 4", []string{"1", "2", "3", "4"}},
299 {"1\t\t2\t\t3\t4", []string{"1", "2", "3", "4"}},
300 {"1\u20002\u20013\u20024", []string{"1", "2", "3", "4"}},
301 {"\u2000\u2001\u2002", []string{}},
302 {"\n™\t™\n", []string{"™", "™"}},
303 {faces
, []string{faces
}},
306 func TestFields(t
*testing
.T
) {
307 for _
, tt
:= range fieldstests
{
310 t
.Errorf("Fields(%q) = %v; want %v", tt
.s
, a
, tt
.a
)
316 var FieldsFuncTests
= []FieldsTest
{
319 {"XXhiXXX", []string{"hi"}},
320 {"aXXbXXXcX", []string{"a", "b", "c"}},
323 func TestFieldsFunc(t
*testing
.T
) {
324 for _
, tt
:= range fieldstests
{
325 a
:= FieldsFunc(tt
.s
, unicode
.IsSpace
)
327 t
.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt
.s
, a
, tt
.a
)
331 pred
:= func(c rune
) bool { return c
== 'X' }
332 for _
, tt
:= range FieldsFuncTests
{
333 a
:= FieldsFunc(tt
.s
, pred
)
335 t
.Errorf("FieldsFunc(%q) = %v, want %v", tt
.s
, a
, tt
.a
)
340 // Test case for any function which accepts and returns a single string.
341 type StringTest
struct {
345 // Execute f on each test case. funcName should be the name of f; it's used
346 // in failure reports.
347 func runStringTests(t
*testing
.T
, f
func(string) string, funcName
string, testCases
[]StringTest
) {
348 for _
, tc
:= range testCases
{
350 if actual
!= tc
.out
{
351 t
.Errorf("%s(%q) = %q; want %q", funcName
, tc
.in
, actual
, tc
.out
)
356 var upperTests
= []StringTest
{
359 {"AbC123", "ABC123"},
360 {"azAZ09_", "AZAZ09_"},
361 {"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char
364 var lowerTests
= []StringTest
{
367 {"AbC123", "abc123"},
368 {"azAZ09_", "azaz09_"},
369 {"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char
372 const space
= "\t\v\r\f\n\u0085\u00a0\u2000\u3000"
374 var trimSpaceTests
= []StringTest
{
377 {space
+ "abc" + space
, "abc"},
379 {" \t\r\n \t\t\r\r\n\n ", ""},
380 {" \t\r\n x\t\t\r\r\n\n ", "x"},
381 {" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"},
382 {"1 \t\r\n2", "1 \t\r\n2"},
385 {"x \xc0\xc0 ", "x \xc0\xc0"},
386 {"x \xc0", "x \xc0"},
387 {"x \xc0 ", "x \xc0"},
388 {"x \xc0\xc0 ", "x \xc0\xc0"},
389 {"x ☺\xc0\xc0 ", "x ☺\xc0\xc0"},
393 func tenRunes(ch rune
) string {
394 r
:= make([]rune
, 10)
401 // User-defined self-inverse mapping function
402 func rot13(r rune
) rune
{
404 if r
>= 'a' && r
<= 'z' {
405 return ((r
- 'a' + step
) % 26) + 'a'
407 if r
>= 'A' && r
<= 'Z' {
408 return ((r
- 'A' + step
) % 26) + 'A'
413 func TestMap(t
*testing
.T
) {
414 // Run a couple of awful growth/shrinkage tests
416 // 1. Grow. This triggers two reallocations in Map.
417 maxRune
:= func(rune
) rune
{ return unicode
.MaxRune
}
419 expect
:= tenRunes(unicode
.MaxRune
)
421 t
.Errorf("growing: expected %q got %q", expect
, m
)
425 minRune
:= func(rune
) rune
{ return 'a' }
426 m
= Map(minRune
, tenRunes(unicode
.MaxRune
))
429 t
.Errorf("shrinking: expected %q got %q", expect
, m
)
433 m
= Map(rot13
, "a to zed")
436 t
.Errorf("rot13: expected %q got %q", expect
, m
)
440 m
= Map(rot13
, Map(rot13
, "a to zed"))
443 t
.Errorf("rot13: expected %q got %q", expect
, m
)
447 dropNotLatin
:= func(r rune
) rune
{
448 if unicode
.Is(unicode
.Latin
, r
) {
453 m
= Map(dropNotLatin
, "Hello, 세계")
456 t
.Errorf("drop: expected %q got %q", expect
, m
)
460 identity
:= func(r rune
) rune
{
463 orig
:= "Input string that we expect not to be copied."
464 m
= Map(identity
, orig
)
465 if (*reflect
.StringHeader
)(unsafe
.Pointer(&orig
)).Data
!=
466 (*reflect
.StringHeader
)(unsafe
.Pointer(&m
)).Data
{
467 t
.Error("unexpected copy during identity map")
471 func TestToUpper(t
*testing
.T
) { runStringTests(t
, ToUpper
, "ToUpper", upperTests
) }
473 func TestToLower(t
*testing
.T
) { runStringTests(t
, ToLower
, "ToLower", lowerTests
) }
475 func BenchmarkMapNoChanges(b
*testing
.B
) {
476 identity
:= func(r rune
) rune
{
479 for i
:= 0; i
< b
.N
; i
++ {
480 Map(identity
, "Some string that won't be modified.")
484 func TestSpecialCase(t
*testing
.T
) {
485 lower
:= "abcçdefgğhıijklmnoöprsştuüvyz"
486 upper
:= "ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZ"
487 u
:= ToUpperSpecial(unicode
.TurkishCase
, upper
)
489 t
.Errorf("Upper(upper) is %s not %s", u
, upper
)
491 u
= ToUpperSpecial(unicode
.TurkishCase
, lower
)
493 t
.Errorf("Upper(lower) is %s not %s", u
, upper
)
495 l
:= ToLowerSpecial(unicode
.TurkishCase
, lower
)
497 t
.Errorf("Lower(lower) is %s not %s", l
, lower
)
499 l
= ToLowerSpecial(unicode
.TurkishCase
, upper
)
501 t
.Errorf("Lower(upper) is %s not %s", l
, lower
)
505 func TestTrimSpace(t
*testing
.T
) { runStringTests(t
, TrimSpace
, "TrimSpace", trimSpaceTests
) }
507 var trimTests
= []struct {
511 {"Trim", "abba", "a", "bb"},
512 {"Trim", "abba", "ab", ""},
513 {"TrimLeft", "abba", "ab", ""},
514 {"TrimRight", "abba", "ab", ""},
515 {"TrimLeft", "abba", "a", "bba"},
516 {"TrimRight", "abba", "a", "abb"},
517 {"Trim", "<tag>", "<>", "tag"},
518 {"Trim", "* listitem", " *", "listitem"},
519 {"Trim", `"quote"`, `"`, "quote"},
520 {"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
522 {"Trim", "abba", "", "abba"},
523 {"Trim", "", "123", ""},
524 {"Trim", "", "", ""},
525 {"TrimLeft", "abba", "", "abba"},
526 {"TrimLeft", "", "123", ""},
527 {"TrimLeft", "", "", ""},
528 {"TrimRight", "abba", "", "abba"},
529 {"TrimRight", "", "123", ""},
530 {"TrimRight", "", "", ""},
531 {"TrimRight", "☺\xc0", "☺", "☺\xc0"},
532 {"TrimPrefix", "aabb", "a", "abb"},
533 {"TrimPrefix", "aabb", "b", "aabb"},
534 {"TrimSuffix", "aabb", "a", "aabb"},
535 {"TrimSuffix", "aabb", "b", "aab"},
538 func TestTrim(t
*testing
.T
) {
539 for _
, tc
:= range trimTests
{
541 var f
func(string, string) string
554 t
.Errorf("Undefined trim function %s", name
)
556 actual
:= f(tc
.in
, tc
.arg
)
557 if actual
!= tc
.out
{
558 t
.Errorf("%s(%q, %q) = %q; want %q", name
, tc
.in
, tc
.arg
, actual
, tc
.out
)
563 type predicate
struct {
568 var isSpace
= predicate
{unicode
.IsSpace
, "IsSpace"}
569 var isDigit
= predicate
{unicode
.IsDigit
, "IsDigit"}
570 var isUpper
= predicate
{unicode
.IsUpper
, "IsUpper"}
571 var isValidRune
= predicate
{
573 return r
!= utf8
.RuneError
578 func not(p predicate
) predicate
{
587 var trimFuncTests
= []struct {
591 {isSpace
, space
+ " hello " + space
, "hello"},
592 {isDigit
, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"},
593 {isUpper
, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"},
594 {not(isSpace
), "hello" + space
+ "hello", space
},
595 {not(isDigit
), "hello\u0e50\u0e521234\u0e50\u0e51helo", "\u0e50\u0e521234\u0e50\u0e51"},
596 {isValidRune
, "ab\xc0a\xc0cd", "\xc0a\xc0"},
597 {not(isValidRune
), "\xc0a\xc0", "a"},
600 func TestTrimFunc(t
*testing
.T
) {
601 for _
, tc
:= range trimFuncTests
{
602 actual
:= TrimFunc(tc
.in
, tc
.f
.f
)
603 if actual
!= tc
.out
{
604 t
.Errorf("TrimFunc(%q, %q) = %q; want %q", tc
.in
, tc
.f
.name
, actual
, tc
.out
)
609 var indexFuncTests
= []struct {
614 {"", isValidRune
, -1, -1},
615 {"abc", isDigit
, -1, -1},
616 {"0123", isDigit
, 0, 3},
617 {"a1b", isDigit
, 1, 1},
618 {space
, isSpace
, 0, len(space
) - 3}, // last rune in space is 3 bytes
619 {"\u0e50\u0e5212hello34\u0e50\u0e51", isDigit
, 0, 18},
620 {"\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", isUpper
, 0, 34},
621 {"12\u0e50\u0e52hello34\u0e50\u0e51", not(isDigit
), 8, 12},
623 // tests of invalid UTF-8
624 {"\x801", isDigit
, 1, 1},
625 {"\x80abc", isDigit
, -1, -1},
626 {"\xc0a\xc0", isValidRune
, 1, 1},
627 {"\xc0a\xc0", not(isValidRune
), 0, 2},
628 {"\xc0☺\xc0", not(isValidRune
), 0, 4},
629 {"\xc0☺\xc0\xc0", not(isValidRune
), 0, 5},
630 {"ab\xc0a\xc0cd", not(isValidRune
), 2, 4},
631 {"a\xe0\x80cd", not(isValidRune
), 1, 2},
632 {"\x80\x80\x80\x80", not(isValidRune
), 0, 3},
635 func TestIndexFunc(t
*testing
.T
) {
636 for _
, tc
:= range indexFuncTests
{
637 first
:= IndexFunc(tc
.in
, tc
.f
.f
)
638 if first
!= tc
.first
{
639 t
.Errorf("IndexFunc(%q, %s) = %d; want %d", tc
.in
, tc
.f
.name
, first
, tc
.first
)
641 last
:= LastIndexFunc(tc
.in
, tc
.f
.f
)
643 t
.Errorf("LastIndexFunc(%q, %s) = %d; want %d", tc
.in
, tc
.f
.name
, last
, tc
.last
)
648 func equal(m
string, s1
, s2
string, t
*testing
.T
) bool {
654 for i
, c1
:= range e1
{
658 r1
, _
:= utf8
.DecodeRuneInString(c1
)
659 r2
, _
:= utf8
.DecodeRuneInString(e2
[i
])
661 t
.Errorf("%s diff at %d: U+%04X U+%04X", m
, i
, r1
, r2
)
667 func TestCaseConsistency(t
*testing
.T
) {
668 // Make a string of all the runes.
669 numRunes
:= int(unicode
.MaxRune
+ 1)
673 a
:= make([]rune
, numRunes
)
678 // convert the cases.
682 // Consistency checks
683 if n
:= utf8
.RuneCountInString(upper
); n
!= numRunes
{
684 t
.Error("rune count wrong in upper:", n
)
686 if n
:= utf8
.RuneCountInString(lower
); n
!= numRunes
{
687 t
.Error("rune count wrong in lower:", n
)
689 if !equal("ToUpper(upper)", ToUpper(upper
), upper
, t
) {
690 t
.Error("ToUpper(upper) consistency fail")
692 if !equal("ToLower(lower)", ToLower(lower
), lower
, t
) {
693 t
.Error("ToLower(lower) consistency fail")
696 These fail because of non-one-to-oneness of the data, such as multiple
697 upper case 'I' mapping to 'i'. We comment them out but keep them for
699 For instance: CAPITAL LETTER I WITH DOT ABOVE:
700 unicode.ToUpper(unicode.ToLower('\u0130')) != '\u0130'
702 if !equal("ToUpper(lower)", ToUpper(lower), upper, t) {
703 t.Error("ToUpper(lower) consistency fail");
705 if !equal("ToLower(upper)", ToLower(upper), lower, t) {
706 t.Error("ToLower(upper) consistency fail");
711 var RepeatTests
= []struct {
720 {"-", "----------", 10},
721 {"abc ", "abc abc abc ", 3},
724 func TestRepeat(t
*testing
.T
) {
725 for _
, tt
:= range RepeatTests
{
726 a
:= Repeat(tt
.in
, tt
.count
)
727 if !equal("Repeat(s)", a
, tt
.out
, t
) {
728 t
.Errorf("Repeat(%v, %d) = %v; want %v", tt
.in
, tt
.count
, a
, tt
.out
)
734 func runesEqual(a
, b
[]rune
) bool {
735 if len(a
) != len(b
) {
738 for i
, r
:= range a
{
746 var RunesTests
= []struct {
751 {"", []rune
{}, false},
752 {" ", []rune
{32}, false},
753 {"ABC", []rune
{65, 66, 67}, false},
754 {"abc", []rune
{97, 98, 99}, false},
755 {"\u65e5\u672c\u8a9e", []rune
{26085, 26412, 35486}, false},
756 {"ab\x80c", []rune
{97, 98, 0xFFFD, 99}, true},
757 {"ab\xc0c", []rune
{97, 98, 0xFFFD, 99}, true},
760 func TestRunes(t
*testing
.T
) {
761 for _
, tt
:= range RunesTests
{
763 if !runesEqual(a
, tt
.out
) {
764 t
.Errorf("[]rune(%q) = %v; want %v", tt
.in
, a
, tt
.out
)
768 // can only test reassembly if we didn't lose information
771 t
.Errorf("string([]rune(%q)) = %x; want %x", tt
.in
, s
, tt
.in
)
777 func TestReadByte(t
*testing
.T
) {
778 testStrings
:= []string{"", abcd
, faces
, commas
}
779 for _
, s
:= range testStrings
{
780 reader
:= NewReader(s
)
781 if e
:= reader
.UnreadByte(); e
== nil {
782 t
.Errorf("Unreading %q at beginning: expected error", s
)
786 b
, e
:= reader
.ReadByte()
791 t
.Errorf("Reading %q: %s", s
, e
)
795 // unread and read again
796 e
= reader
.UnreadByte()
798 t
.Errorf("Unreading %q: %s", s
, e
)
801 b1
, e
:= reader
.ReadByte()
803 t
.Errorf("Reading %q after unreading: %s", s
, e
)
807 t
.Errorf("Reading %q after unreading: want byte %q, got %q", s
, b
, b1
)
811 if res
.String() != s
{
812 t
.Errorf("Reader(%q).ReadByte() produced %q", s
, res
.String())
817 func TestReadRune(t
*testing
.T
) {
818 testStrings
:= []string{"", abcd
, faces
, commas
}
819 for _
, s
:= range testStrings
{
820 reader
:= NewReader(s
)
821 if e
:= reader
.UnreadRune(); e
== nil {
822 t
.Errorf("Unreading %q at beginning: expected error", s
)
826 r
, z
, e
:= reader
.ReadRune()
831 t
.Errorf("Reading %q: %s", s
, e
)
835 // unread and read again
836 e
= reader
.UnreadRune()
838 t
.Errorf("Unreading %q: %s", s
, e
)
841 r1
, z1
, e
:= reader
.ReadRune()
843 t
.Errorf("Reading %q after unreading: %s", s
, e
)
847 t
.Errorf("Reading %q after unreading: want rune %q, got %q", s
, r
, r1
)
851 t
.Errorf("Reading %q after unreading: want size %d, got %d", s
, z
, z1
)
856 t
.Errorf("Reader(%q).ReadRune() produced %q", s
, res
)
861 var UnreadRuneErrorTests
= []struct {
865 {"Read", func(r
*Reader
) { r
.Read([]byte{0}) }},
866 {"ReadByte", func(r
*Reader
) { r
.ReadByte() }},
867 {"UnreadRune", func(r
*Reader
) { r
.UnreadRune() }},
868 {"Seek", func(r
*Reader
) { r
.Seek(0, 1) }},
869 {"WriteTo", func(r
*Reader
) { r
.WriteTo(&bytes
.Buffer
{}) }},
872 func TestUnreadRuneError(t
*testing
.T
) {
873 for _
, tt
:= range UnreadRuneErrorTests
{
874 reader
:= NewReader("0123456789")
875 if _
, _
, err
:= reader
.ReadRune(); err
!= nil {
880 err
:= reader
.UnreadRune()
882 t
.Errorf("Unreading after %s: expected error", tt
.name
)
887 var ReplaceTests
= []struct {
893 {"hello", "l", "L", 0, "hello"},
894 {"hello", "l", "L", -1, "heLLo"},
895 {"hello", "x", "X", -1, "hello"},
896 {"", "x", "X", -1, ""},
897 {"radar", "r", "<r>", -1, "<r>ada<r>"},
898 {"", "", "<>", -1, "<>"},
899 {"banana", "a", "<>", -1, "b<>n<>n<>"},
900 {"banana", "a", "<>", 1, "b<>nana"},
901 {"banana", "a", "<>", 1000, "b<>n<>n<>"},
902 {"banana", "an", "<>", -1, "b<><>a"},
903 {"banana", "ana", "<>", -1, "b<>na"},
904 {"banana", "", "<>", -1, "<>b<>a<>n<>a<>n<>a<>"},
905 {"banana", "", "<>", 10, "<>b<>a<>n<>a<>n<>a<>"},
906 {"banana", "", "<>", 6, "<>b<>a<>n<>a<>n<>a"},
907 {"banana", "", "<>", 5, "<>b<>a<>n<>a<>na"},
908 {"banana", "", "<>", 1, "<>banana"},
909 {"banana", "a", "a", -1, "banana"},
910 {"banana", "a", "a", 1, "banana"},
911 {"☺☻☹", "", "<>", -1, "<>☺<>☻<>☹<>"},
914 func TestReplace(t
*testing
.T
) {
915 for _
, tt
:= range ReplaceTests
{
916 if s
:= Replace(tt
.in
, tt
.old
, tt
.new, tt
.n
); s
!= tt
.out
{
917 t
.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt
.in
, tt
.old
, tt
.new, tt
.n
, s
, tt
.out
)
922 var TitleTests
= []struct {
927 {" aaa aaa aaa ", " Aaa Aaa Aaa "},
928 {" Aaa Aaa Aaa ", " Aaa Aaa Aaa "},
929 {"123a456", "123a456"},
930 {"double-blind", "Double-Blind"},
932 {"with_underscore", "With_underscore"},
933 {"unicode \xe2\x80\xa8 line separator", "Unicode \xe2\x80\xa8 Line Separator"},
936 func TestTitle(t
*testing
.T
) {
937 for _
, tt
:= range TitleTests
{
938 if s
:= Title(tt
.in
); s
!= tt
.out
{
939 t
.Errorf("Title(%q) = %q, want %q", tt
.in
, s
, tt
.out
)
944 var ContainsTests
= []struct {
949 {"abc", "bcd", false},
954 func TestContains(t
*testing
.T
) {
955 for _
, ct
:= range ContainsTests
{
956 if Contains(ct
.str
, ct
.substr
) != ct
.expected
{
957 t
.Errorf("Contains(%s, %s) = %v, want %v",
958 ct
.str
, ct
.substr
, !ct
.expected
, ct
.expected
)
963 var ContainsAnyTests
= []struct {
973 {"abc", "xyz", false},
974 {"abc", "xcz", true},
975 {"a☺b☻c☹d", "uvw☻xyz", true},
976 {"aRegExp*", ".(|)*+?^$[]", true},
977 {dots
+ dots
+ dots
, " ", false},
980 func TestContainsAny(t
*testing
.T
) {
981 for _
, ct
:= range ContainsAnyTests
{
982 if ContainsAny(ct
.str
, ct
.substr
) != ct
.expected
{
983 t
.Errorf("ContainsAny(%s, %s) = %v, want %v",
984 ct
.str
, ct
.substr
, !ct
.expected
, ct
.expected
)
989 var ContainsRuneTests
= []struct {
999 {"a☺b☻c☹d", 'x', false},
1000 {"a☺b☻c☹d", '☻', true},
1001 {"aRegExp*", '*', true},
1004 func TestContainsRune(t
*testing
.T
) {
1005 for _
, ct
:= range ContainsRuneTests
{
1006 if ContainsRune(ct
.str
, ct
.r
) != ct
.expected
{
1007 t
.Errorf("ContainsRune(%q, %q) = %v, want %v",
1008 ct
.str
, ct
.r
, !ct
.expected
, ct
.expected
)
1013 var EqualFoldTests
= []struct {
1017 {"abc", "abc", true},
1018 {"ABcd", "ABcd", true},
1019 {"123abc", "123ABC", true},
1020 {"αβδ", "ΑΒΔ", true},
1021 {"abc", "xyz", false},
1022 {"abc", "XYZ", false},
1023 {"abcdefghijk", "abcdefghijX", false},
1024 {"abcdefghijk", "abcdefghij\u212A", true},
1025 {"abcdefghijK", "abcdefghij\u212A", true},
1026 {"abcdefghijkz", "abcdefghij\u212Ay", false},
1027 {"abcdefghijKz", "abcdefghij\u212Ay", false},
1030 func TestEqualFold(t
*testing
.T
) {
1031 for _
, tt
:= range EqualFoldTests
{
1032 if out
:= EqualFold(tt
.s
, tt
.t
); out
!= tt
.out
{
1033 t
.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt
.s
, tt
.t
, out
, tt
.out
)
1035 if out
:= EqualFold(tt
.t
, tt
.s
); out
!= tt
.out
{
1036 t
.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt
.t
, tt
.s
, out
, tt
.out
)
1041 var CountTests
= []struct {
1046 {"", "notempty", 0},
1047 {"notempty", "", 9},
1048 {"smaller", "not smaller", 0},
1049 {"12345678987654321", "6", 2},
1050 {"611161116", "6", 3},
1051 {"notequal", "NotEqual", 0},
1052 {"equal", "equal", 1},
1053 {"abc1231231123q", "123", 3},
1057 func TestCount(t
*testing
.T
) {
1058 for _
, tt
:= range CountTests
{
1059 if num
:= Count(tt
.s
, tt
.sep
); num
!= tt
.num
{
1060 t
.Errorf("Count(\"%s\", \"%s\") = %d, want %d", tt
.s
, tt
.sep
, num
, tt
.num
)
1065 func makeBenchInputHard() string {
1066 tokens
:= [...]string{
1067 "<a>", "<p>", "<b>", "<strong>",
1068 "</a>", "</p>", "</b>", "</strong>",
1071 x
:= make([]byte, 0, 1<<20)
1072 for len(x
) < 1<<20 {
1073 i
:= rand
.Intn(len(tokens
))
1074 x
= append(x
, tokens
[i
]...)
1079 var benchInputHard
= makeBenchInputHard()
1081 func benchmarkIndexHard(b
*testing
.B
, sep
string) {
1082 for i
:= 0; i
< b
.N
; i
++ {
1083 Index(benchInputHard
, sep
)
1087 func benchmarkCountHard(b
*testing
.B
, sep
string) {
1088 for i
:= 0; i
< b
.N
; i
++ {
1089 Count(benchInputHard
, sep
)
1093 func BenchmarkIndexHard1(b
*testing
.B
) { benchmarkIndexHard(b
, "<>") }
1094 func BenchmarkIndexHard2(b
*testing
.B
) { benchmarkIndexHard(b
, "</pre>") }
1095 func BenchmarkIndexHard3(b
*testing
.B
) { benchmarkIndexHard(b
, "<b>hello world</b>") }
1097 func BenchmarkCountHard1(b
*testing
.B
) { benchmarkCountHard(b
, "<>") }
1098 func BenchmarkCountHard2(b
*testing
.B
) { benchmarkCountHard(b
, "</pre>") }
1099 func BenchmarkCountHard3(b
*testing
.B
) { benchmarkCountHard(b
, "<b>hello world</b>") }
1101 var benchInputTorture
= Repeat("ABC", 1<<10) + "123" + Repeat("ABC", 1<<10)
1102 var benchNeedleTorture
= Repeat("ABC", 1<<10+1)
1104 func BenchmarkIndexTorture(b
*testing
.B
) {
1105 for i
:= 0; i
< b
.N
; i
++ {
1106 Index(benchInputTorture
, benchNeedleTorture
)
1110 func BenchmarkCountTorture(b
*testing
.B
) {
1111 for i
:= 0; i
< b
.N
; i
++ {
1112 Count(benchInputTorture
, benchNeedleTorture
)
1116 func BenchmarkCountTortureOverlapping(b
*testing
.B
) {
1117 A
:= Repeat("ABC", 1<<20)
1118 B
:= Repeat("ABC", 1<<10)
1119 for i
:= 0; i
< b
.N
; i
++ {
1124 var makeFieldsInput
= func() string {
1125 x
:= make([]byte, 1<<20)
1126 // Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space.
1128 switch rand
.Intn(10) {
1132 if i
> 0 && x
[i
-1] == 'x' {
1144 var fieldsInput
= makeFieldsInput()
1146 func BenchmarkFields(b
*testing
.B
) {
1147 b
.SetBytes(int64(len(fieldsInput
)))
1148 for i
:= 0; i
< b
.N
; i
++ {
1153 func BenchmarkFieldsFunc(b
*testing
.B
) {
1154 b
.SetBytes(int64(len(fieldsInput
)))
1155 for i
:= 0; i
< b
.N
; i
++ {
1156 FieldsFunc(fieldsInput
, unicode
.IsSpace
)
1160 func BenchmarkSplit1(b
*testing
.B
) {
1161 for i
:= 0; i
< b
.N
; i
++ {
1162 Split(benchInputHard
, "")
1166 func BenchmarkSplit2(b
*testing
.B
) {
1167 for i
:= 0; i
< b
.N
; i
++ {
1168 Split(benchInputHard
, "/")
1172 func BenchmarkSplit3(b
*testing
.B
) {
1173 for i
:= 0; i
< b
.N
; i
++ {
1174 Split(benchInputHard
, "hello")