Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / go / strings / strings_test.go
blob657c8e89064242595740332ca8848337635fcd0e
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.
5 package strings_test
7 import (
8 "os"
9 . "strings"
10 "testing"
11 "unicode"
12 "utf8"
15 func eq(a, b []string) bool {
16 if len(a) != len(b) {
17 return false
19 for i := 0; i < len(a); i++ {
20 if a[i] != b[i] {
21 return false
24 return true
27 var abcd = "abcd"
28 var faces = "☺☻☹"
29 var commas = "1,2,3,4"
30 var dots = "1....2....3....4"
32 type IndexTest struct {
33 s string
34 sep string
35 out int
38 var indexTests = []IndexTest{
39 {"", "", 0},
40 {"", "a", -1},
41 {"", "foo", -1},
42 {"fo", "foo", -1},
43 {"foo", "foo", 0},
44 {"oofofoofooo", "f", 2},
45 {"oofofoofooo", "foo", 4},
46 {"barfoobarfoo", "foo", 3},
47 {"foo", "", 0},
48 {"foo", "o", 1},
49 {"abcABCabc", "A", 3},
50 // cases with one byte strings - test special case in Index()
51 {"", "a", -1},
52 {"x", "a", -1},
53 {"x", "x", 0},
54 {"abc", "a", 0},
55 {"abc", "b", 1},
56 {"abc", "c", 2},
57 {"abc", "x", -1},
60 var lastIndexTests = []IndexTest{
61 {"", "", 0},
62 {"", "a", -1},
63 {"", "foo", -1},
64 {"fo", "foo", -1},
65 {"foo", "foo", 0},
66 {"foo", "f", 0},
67 {"oofofoofooo", "f", 7},
68 {"oofofoofooo", "foo", 7},
69 {"barfoobarfoo", "foo", 9},
70 {"foo", "", 3},
71 {"foo", "o", 2},
72 {"abcABCabc", "A", 3},
73 {"abcABCabc", "a", 6},
76 var indexAnyTests = []IndexTest{
77 {"", "", -1},
78 {"", "a", -1},
79 {"", "abc", -1},
80 {"a", "", -1},
81 {"a", "a", 0},
82 {"aaa", "a", 0},
83 {"abc", "xyz", -1},
84 {"abc", "xcz", 2},
85 {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
86 {"aRegExp*", ".(|)*+?^$[]", 7},
87 {dots + dots + dots, " ", -1},
90 // Execute f on each test case. funcName should be the name of f; it's used
91 // in failure reports.
92 func runIndexTests(t *testing.T, f func(s, sep string) int, funcName string, testCases []IndexTest) {
93 for _, test := range testCases {
94 actual := f(test.s, test.sep)
95 if actual != test.out {
96 t.Errorf("%s(%q,%q) = %v; want %v", funcName, test.s, test.sep, actual, test.out)
101 func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) }
102 func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) }
103 func TestIndexAny(t *testing.T) { runIndexTests(t, IndexAny, "IndexAny", indexAnyTests) }
105 type ExplodeTest struct {
106 s string
107 n int
108 a []string
111 var explodetests = []ExplodeTest{
112 {"", -1, []string{}},
113 {abcd, 4, []string{"a", "b", "c", "d"}},
114 {faces, 3, []string{"☺", "☻", "☹"}},
115 {abcd, 2, []string{"a", "bcd"}},
118 func TestExplode(t *testing.T) {
119 for _, tt := range explodetests {
120 a := Split(tt.s, "", tt.n)
121 if !eq(a, tt.a) {
122 t.Errorf("explode(%q, %d) = %v; want %v", tt.s, tt.n, a, tt.a)
123 continue
125 s := Join(a, "")
126 if s != tt.s {
127 t.Errorf(`Join(explode(%q, %d), "") = %q`, tt.s, tt.n, s)
132 type SplitTest struct {
133 s string
134 sep string
135 n int
136 a []string
139 var splittests = []SplitTest{
140 {abcd, "a", 0, nil},
141 {abcd, "a", -1, []string{"", "bcd"}},
142 {abcd, "z", -1, []string{"abcd"}},
143 {abcd, "", -1, []string{"a", "b", "c", "d"}},
144 {commas, ",", -1, []string{"1", "2", "3", "4"}},
145 {dots, "...", -1, []string{"1", ".2", ".3", ".4"}},
146 {faces, "☹", -1, []string{"☺☻", ""}},
147 {faces, "~", -1, []string{faces}},
148 {faces, "", -1, []string{"☺", "☻", "☹"}},
149 {"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}},
150 {"1 2", " ", 3, []string{"1", "2"}},
151 {"123", "", 2, []string{"1", "23"}},
152 {"123", "", 17, []string{"1", "2", "3"}},
155 func TestSplit(t *testing.T) {
156 for _, tt := range splittests {
157 a := Split(tt.s, tt.sep, tt.n)
158 if !eq(a, tt.a) {
159 t.Errorf("Split(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, a, tt.a)
160 continue
162 if tt.n == 0 {
163 continue
165 s := Join(a, tt.sep)
166 if s != tt.s {
167 t.Errorf("Join(Split(%q, %q, %d), %q) = %q", tt.s, tt.sep, tt.n, tt.sep, s)
172 var splitaftertests = []SplitTest{
173 {abcd, "a", -1, []string{"a", "bcd"}},
174 {abcd, "z", -1, []string{"abcd"}},
175 {abcd, "", -1, []string{"a", "b", "c", "d"}},
176 {commas, ",", -1, []string{"1,", "2,", "3,", "4"}},
177 {dots, "...", -1, []string{"1...", ".2...", ".3...", ".4"}},
178 {faces, "☹", -1, []string{"☺☻☹", ""}},
179 {faces, "~", -1, []string{faces}},
180 {faces, "", -1, []string{"☺", "☻", "☹"}},
181 {"1 2 3 4", " ", 3, []string{"1 ", "2 ", "3 4"}},
182 {"1 2 3", " ", 3, []string{"1 ", "2 ", "3"}},
183 {"1 2", " ", 3, []string{"1 ", "2"}},
184 {"123", "", 2, []string{"1", "23"}},
185 {"123", "", 17, []string{"1", "2", "3"}},
188 func TestSplitAfter(t *testing.T) {
189 for _, tt := range splitaftertests {
190 a := SplitAfter(tt.s, tt.sep, tt.n)
191 if !eq(a, tt.a) {
192 t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, a, tt.a)
193 continue
195 s := Join(a, "")
196 if s != tt.s {
197 t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s)
202 type FieldsTest struct {
203 s string
204 a []string
207 var fieldstests = []FieldsTest{
208 {"", []string{}},
209 {" ", []string{}},
210 {" \t ", []string{}},
211 {" abc ", []string{"abc"}},
212 {"1 2 3 4", []string{"1", "2", "3", "4"}},
213 {"1 2 3 4", []string{"1", "2", "3", "4"}},
214 {"1\t\t2\t\t3\t4", []string{"1", "2", "3", "4"}},
215 {"1\u20002\u20013\u20024", []string{"1", "2", "3", "4"}},
216 {"\u2000\u2001\u2002", []string{}},
217 {"\n\t\n", []string{"™", "™"}},
218 {faces, []string{faces}},
221 func TestFields(t *testing.T) {
222 for _, tt := range fieldstests {
223 a := Fields(tt.s)
224 if !eq(a, tt.a) {
225 t.Errorf("Fields(%q) = %v; want %v", tt.s, a, tt.a)
226 continue
231 func TestFieldsFunc(t *testing.T) {
232 pred := func(c int) bool { return c == 'X' }
233 var fieldsFuncTests = []FieldsTest{
234 {"", []string{}},
235 {"XX", []string{}},
236 {"XXhiXXX", []string{"hi"}},
237 {"aXXbXXXcX", []string{"a", "b", "c"}},
239 for _, tt := range fieldsFuncTests {
240 a := FieldsFunc(tt.s, pred)
241 if !eq(a, tt.a) {
242 t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a)
248 // Test case for any function which accepts and returns a single string.
249 type StringTest struct {
250 in, out string
253 // Execute f on each test case. funcName should be the name of f; it's used
254 // in failure reports.
255 func runStringTests(t *testing.T, f func(string) string, funcName string, testCases []StringTest) {
256 for _, tc := range testCases {
257 actual := f(tc.in)
258 if actual != tc.out {
259 t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out)
264 var upperTests = []StringTest{
265 {"", ""},
266 {"abc", "ABC"},
267 {"AbC123", "ABC123"},
268 {"azAZ09_", "AZAZ09_"},
269 {"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char
272 var lowerTests = []StringTest{
273 {"", ""},
274 {"abc", "abc"},
275 {"AbC123", "abc123"},
276 {"azAZ09_", "azaz09_"},
277 {"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char
280 const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000"
282 var trimSpaceTests = []StringTest{
283 {"", ""},
284 {"abc", "abc"},
285 {space + "abc" + space, "abc"},
286 {" ", ""},
287 {" \t\r\n \t\t\r\r\n\n ", ""},
288 {" \t\r\n x\t\t\r\r\n\n ", "x"},
289 {" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"},
290 {"1 \t\r\n2", "1 \t\r\n2"},
291 {" x\x80", "x\x80"},
292 {" x\xc0", "x\xc0"},
293 {"x \xc0\xc0 ", "x \xc0\xc0"},
294 {"x \xc0", "x \xc0"},
295 {"x \xc0 ", "x \xc0"},
296 {"x \xc0\xc0 ", "x \xc0\xc0"},
297 {"x ☺\xc0\xc0 ", "x ☺\xc0\xc0"},
298 {"x ☺ ", "x ☺"},
301 func tenRunes(rune int) string {
302 r := make([]int, 10)
303 for i := range r {
304 r[i] = rune
306 return string(r)
309 // User-defined self-inverse mapping function
310 func rot13(rune int) int {
311 step := 13
312 if rune >= 'a' && rune <= 'z' {
313 return ((rune - 'a' + step) % 26) + 'a'
315 if rune >= 'A' && rune <= 'Z' {
316 return ((rune - 'A' + step) % 26) + 'A'
318 return rune
321 func TestMap(t *testing.T) {
322 // Run a couple of awful growth/shrinkage tests
323 a := tenRunes('a')
324 // 1. Grow. This triggers two reallocations in Map.
325 maxRune := func(rune int) int { return unicode.MaxRune }
326 m := Map(maxRune, a)
327 expect := tenRunes(unicode.MaxRune)
328 if m != expect {
329 t.Errorf("growing: expected %q got %q", expect, m)
332 // 2. Shrink
333 minRune := func(rune int) int { return 'a' }
334 m = Map(minRune, tenRunes(unicode.MaxRune))
335 expect = a
336 if m != expect {
337 t.Errorf("shrinking: expected %q got %q", expect, m)
340 // 3. Rot13
341 m = Map(rot13, "a to zed")
342 expect = "n gb mrq"
343 if m != expect {
344 t.Errorf("rot13: expected %q got %q", expect, m)
347 // 4. Rot13^2
348 m = Map(rot13, Map(rot13, "a to zed"))
349 expect = "a to zed"
350 if m != expect {
351 t.Errorf("rot13: expected %q got %q", expect, m)
354 // 5. Drop
355 dropNotLatin := func(rune int) int {
356 if unicode.Is(unicode.Latin, rune) {
357 return rune
359 return -1
361 m = Map(dropNotLatin, "Hello, 세계")
362 expect = "Hello"
363 if m != expect {
364 t.Errorf("drop: expected %q got %q", expect, m)
368 func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) }
370 func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) }
372 func TestSpecialCase(t *testing.T) {
373 lower := "abcçdefgğhıijklmnoöprsştuüvyz"
374 upper := "ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZ"
375 u := ToUpperSpecial(unicode.TurkishCase, upper)
376 if u != upper {
377 t.Errorf("Upper(upper) is %s not %s", u, upper)
379 u = ToUpperSpecial(unicode.TurkishCase, lower)
380 if u != upper {
381 t.Errorf("Upper(lower) is %s not %s", u, upper)
383 l := ToLowerSpecial(unicode.TurkishCase, lower)
384 if l != lower {
385 t.Errorf("Lower(lower) is %s not %s", l, lower)
387 l = ToLowerSpecial(unicode.TurkishCase, upper)
388 if l != lower {
389 t.Errorf("Lower(upper) is %s not %s", l, lower)
393 func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
395 type TrimTest struct {
396 f func(string, string) string
397 in, cutset, out string
400 var trimTests = []TrimTest{
401 {Trim, "abba", "a", "bb"},
402 {Trim, "abba", "ab", ""},
403 {TrimLeft, "abba", "ab", ""},
404 {TrimRight, "abba", "ab", ""},
405 {TrimLeft, "abba", "a", "bba"},
406 {TrimRight, "abba", "a", "abb"},
407 {Trim, "<tag>", "<>", "tag"},
408 {Trim, "* listitem", " *", "listitem"},
409 {Trim, `"quote"`, `"`, "quote"},
410 {Trim, "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
411 //empty string tests
412 {Trim, "abba", "", "abba"},
413 {Trim, "", "123", ""},
414 {Trim, "", "", ""},
415 {TrimLeft, "abba", "", "abba"},
416 {TrimLeft, "", "123", ""},
417 {TrimLeft, "", "", ""},
418 {TrimRight, "abba", "", "abba"},
419 {TrimRight, "", "123", ""},
420 {TrimRight, "", "", ""},
421 {TrimRight, "☺\xc0", "☺", "☺\xc0"},
424 func TestTrim(t *testing.T) {
425 for _, tc := range trimTests {
426 actual := tc.f(tc.in, tc.cutset)
427 var name string
428 switch tc.f {
429 case Trim:
430 name = "Trim"
431 case TrimLeft:
432 name = "TrimLeft"
433 case TrimRight:
434 name = "TrimRight"
435 default:
436 t.Error("Undefined trim function")
438 if actual != tc.out {
439 t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
444 type predicate struct {
445 f func(r int) bool
446 name string
449 var isSpace = predicate{unicode.IsSpace, "IsSpace"}
450 var isDigit = predicate{unicode.IsDigit, "IsDigit"}
451 var isUpper = predicate{unicode.IsUpper, "IsUpper"}
452 var isValidRune = predicate{
453 func(r int) bool {
454 return r != utf8.RuneError
456 "IsValidRune",
459 type TrimFuncTest struct {
460 f predicate
461 in, out string
464 func not(p predicate) predicate {
465 return predicate{
466 func(r int) bool {
467 return !p.f(r)
469 "not " + p.name,
473 var trimFuncTests = []TrimFuncTest{
474 {isSpace, space + " hello " + space, "hello"},
475 {isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"},
476 {isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"},
477 {not(isSpace), "hello" + space + "hello", space},
478 {not(isDigit), "hello\u0e50\u0e521234\u0e50\u0e51helo", "\u0e50\u0e521234\u0e50\u0e51"},
479 {isValidRune, "ab\xc0a\xc0cd", "\xc0a\xc0"},
480 {not(isValidRune), "\xc0a\xc0", "a"},
483 func TestTrimFunc(t *testing.T) {
484 for _, tc := range trimFuncTests {
485 actual := TrimFunc(tc.in, tc.f.f)
486 if actual != tc.out {
487 t.Errorf("TrimFunc(%q, %q) = %q; want %q", tc.in, tc.f.name, actual, tc.out)
492 type IndexFuncTest struct {
493 in string
494 f predicate
495 first, last int
498 var indexFuncTests = []IndexFuncTest{
499 {"", isValidRune, -1, -1},
500 {"abc", isDigit, -1, -1},
501 {"0123", isDigit, 0, 3},
502 {"a1b", isDigit, 1, 1},
503 {space, isSpace, 0, len(space) - 3}, // last rune in space is 3 bytes
504 {"\u0e50\u0e5212hello34\u0e50\u0e51", isDigit, 0, 18},
505 {"\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", isUpper, 0, 34},
506 {"12\u0e50\u0e52hello34\u0e50\u0e51", not(isDigit), 8, 12},
508 // tests of invalid UTF-8
509 {"\x801", isDigit, 1, 1},
510 {"\x80abc", isDigit, -1, -1},
511 {"\xc0a\xc0", isValidRune, 1, 1},
512 {"\xc0a\xc0", not(isValidRune), 0, 2},
513 {"\xc0\xc0", not(isValidRune), 0, 4},
514 {"\xc0\xc0\xc0", not(isValidRune), 0, 5},
515 {"ab\xc0a\xc0cd", not(isValidRune), 2, 4},
516 {"a\xe0\x80cd", not(isValidRune), 1, 2},
517 {"\x80\x80\x80\x80", not(isValidRune), 0, 3},
520 func TestIndexFunc(t *testing.T) {
521 for _, tc := range indexFuncTests {
522 first := IndexFunc(tc.in, tc.f.f)
523 if first != tc.first {
524 t.Errorf("IndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, first, tc.first)
526 last := LastIndexFunc(tc.in, tc.f.f)
527 if last != tc.last {
528 t.Errorf("LastIndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, last, tc.last)
533 func equal(m string, s1, s2 string, t *testing.T) bool {
534 if s1 == s2 {
535 return true
537 e1 := Split(s1, "", -1)
538 e2 := Split(s2, "", -1)
539 for i, c1 := range e1 {
540 if i > len(e2) {
541 break
543 r1, _ := utf8.DecodeRuneInString(c1)
544 r2, _ := utf8.DecodeRuneInString(e2[i])
545 if r1 != r2 {
546 t.Errorf("%s diff at %d: U+%04X U+%04X", m, i, r1, r2)
549 return false
552 func TestCaseConsistency(t *testing.T) {
553 // Make a string of all the runes.
554 a := make([]int, unicode.MaxRune+1)
555 for i := range a {
556 a[i] = i
558 s := string(a)
559 // convert the cases.
560 upper := ToUpper(s)
561 lower := ToLower(s)
563 // Consistency checks
564 if n := utf8.RuneCountInString(upper); n != unicode.MaxRune+1 {
565 t.Error("rune count wrong in upper:", n)
567 if n := utf8.RuneCountInString(lower); n != unicode.MaxRune+1 {
568 t.Error("rune count wrong in lower:", n)
570 if !equal("ToUpper(upper)", ToUpper(upper), upper, t) {
571 t.Error("ToUpper(upper) consistency fail")
573 if !equal("ToLower(lower)", ToLower(lower), lower, t) {
574 t.Error("ToLower(lower) consistency fail")
577 These fail because of non-one-to-oneness of the data, such as multiple
578 upper case 'I' mapping to 'i'. We comment them out but keep them for
579 interest.
580 For instance: CAPITAL LETTER I WITH DOT ABOVE:
581 unicode.ToUpper(unicode.ToLower('\u0130')) != '\u0130'
583 if !equal("ToUpper(lower)", ToUpper(lower), upper, t) {
584 t.Error("ToUpper(lower) consistency fail");
586 if !equal("ToLower(upper)", ToLower(upper), lower, t) {
587 t.Error("ToLower(upper) consistency fail");
592 type RepeatTest struct {
593 in, out string
594 count int
597 var RepeatTests = []RepeatTest{
598 {"", "", 0},
599 {"", "", 1},
600 {"", "", 2},
601 {"-", "", 0},
602 {"-", "-", 1},
603 {"-", "----------", 10},
604 {"abc ", "abc abc abc ", 3},
607 func TestRepeat(t *testing.T) {
608 for _, tt := range RepeatTests {
609 a := Repeat(tt.in, tt.count)
610 if !equal("Repeat(s)", a, tt.out, t) {
611 t.Errorf("Repeat(%v, %d) = %v; want %v", tt.in, tt.count, a, tt.out)
612 continue
617 func runesEqual(a, b []int) bool {
618 if len(a) != len(b) {
619 return false
621 for i, r := range a {
622 if r != b[i] {
623 return false
626 return true
629 type RunesTest struct {
630 in string
631 out []int
632 lossy bool
635 var RunesTests = []RunesTest{
636 {"", []int{}, false},
637 {" ", []int{32}, false},
638 {"ABC", []int{65, 66, 67}, false},
639 {"abc", []int{97, 98, 99}, false},
640 {"\u65e5\u672c\u8a9e", []int{26085, 26412, 35486}, false},
641 {"ab\x80c", []int{97, 98, 0xFFFD, 99}, true},
642 {"ab\xc0c", []int{97, 98, 0xFFFD, 99}, true},
645 func TestRunes(t *testing.T) {
646 for _, tt := range RunesTests {
647 a := []int(tt.in)
648 if !runesEqual(a, tt.out) {
649 t.Errorf("[]int(%q) = %v; want %v", tt.in, a, tt.out)
650 continue
652 if !tt.lossy {
653 // can only test reassembly if we didn't lose information
654 s := string(a)
655 if s != tt.in {
656 t.Errorf("string([]int(%q)) = %x; want %x", tt.in, s, tt.in)
662 func TestReadRune(t *testing.T) {
663 testStrings := []string{"", abcd, faces, commas}
664 for _, s := range testStrings {
665 reader := NewReader(s)
666 res := ""
667 for {
668 r, _, e := reader.ReadRune()
669 if e == os.EOF {
670 break
672 if e != nil {
673 t.Errorf("Reading %q: %s", s, e)
674 break
676 res += string(r)
678 if res != s {
679 t.Errorf("Reader(%q).ReadRune() produced %q", s, res)
684 type ReplaceTest struct {
685 in string
686 old, new string
687 n int
688 out string
691 var ReplaceTests = []ReplaceTest{
692 {"hello", "l", "L", 0, "hello"},
693 {"hello", "l", "L", -1, "heLLo"},
694 {"hello", "x", "X", -1, "hello"},
695 {"", "x", "X", -1, ""},
696 {"radar", "r", "<r>", -1, "<r>ada<r>"},
697 {"", "", "<>", -1, "<>"},
698 {"banana", "a", "<>", -1, "b<>n<>n<>"},
699 {"banana", "a", "<>", 1, "b<>nana"},
700 {"banana", "a", "<>", 1000, "b<>n<>n<>"},
701 {"banana", "an", "<>", -1, "b<><>a"},
702 {"banana", "ana", "<>", -1, "b<>na"},
703 {"banana", "", "<>", -1, "<>b<>a<>n<>a<>n<>a<>"},
704 {"banana", "", "<>", 10, "<>b<>a<>n<>a<>n<>a<>"},
705 {"banana", "", "<>", 6, "<>b<>a<>n<>a<>n<>a"},
706 {"banana", "", "<>", 5, "<>b<>a<>n<>a<>na"},
707 {"banana", "", "<>", 1, "<>banana"},
708 {"banana", "a", "a", -1, "banana"},
709 {"banana", "a", "a", 1, "banana"},
710 {"☺☻☹", "", "<>", -1, "<>☺<>☻<>☹<>"},
713 func TestReplace(t *testing.T) {
714 for _, tt := range ReplaceTests {
715 if s := Replace(tt.in, tt.old, tt.new, tt.n); s != tt.out {
716 t.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt.in, tt.old, tt.new, tt.n, s, tt.out)
721 type TitleTest struct {
722 in, out string
725 var TitleTests = []TitleTest{
726 {"", ""},
727 {"a", "A"},
728 {" aaa aaa aaa ", " Aaa Aaa Aaa "},
729 {" Aaa Aaa Aaa ", " Aaa Aaa Aaa "},
730 {"123a456", "123a456"},
731 {"double-blind", "Double-Blind"},
732 {"ÿøû", "Ÿøû"},
735 func TestTitle(t *testing.T) {
736 for _, tt := range TitleTests {
737 if s := Title(tt.in); s != tt.out {
738 t.Errorf("Title(%q) = %q, want %q", tt.in, s, tt.out)
743 type ContainsTest struct {
744 str, substr string
745 expected bool
748 var ContainsTests = []ContainsTest{
749 {"abc", "bc", true},
750 {"abc", "bcd", false},
751 {"abc", "", true},
752 {"", "a", false},
755 func TestContains(t *testing.T) {
756 for _, ct := range ContainsTests {
757 if Contains(ct.str, ct.substr) != ct.expected {
758 t.Errorf("Contains(%s, %s) = %v, want %v",
759 ct.str, ct.substr, !ct.expected, ct.expected)