// Copyright 2009 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file. package strings_test import ( "bytes" "io" "math/rand" "reflect" . "strings" "testing" "unicode" "unicode/utf8" "unsafe") func eq(a, b []string) bool { if len(a) != len(b) { return false } for i := 0; i < len(a); i++ { if a[i] != b[i] { return false } } return true} var abcd = "abcd"var faces = "☺☻☹"var commas = "1,2,3,4"var dots = "1....2....3....4" type IndexTest struct { s string sep string out int} var indexTests = []IndexTest{ {"", "", 0}, {"", "a", -1}, {"", "foo", -1}, {"fo", "foo", -1}, {"foo", "foo", 0}, {"oofofoofooo", "f", 2}, {"oofofoofooo", "foo", 4}, {"barfoobarfoo", "foo", 3}, {"foo", "", 0}, {"foo", "o", 1}, {"abcABCabc", "A", 3}, // cases with one byte strings - test special case in Index() {"", "a", -1}, {"x", "a", -1}, {"x", "x", 0}, {"abc", "a", 0}, {"abc", "b", 1}, {"abc", "c", 2}, {"abc", "x", -1}, // test special cases in Index() for short strings {"", "ab", -1}, {"bc", "ab", -1}, {"ab", "ab", 0}, {"xab", "ab", 1}, {"xab"[:2], "ab", -1}, {"", "abc", -1}, {"xbc", "abc", -1}, {"abc", "abc", 0}, {"xabc", "abc", 1}, {"xabc"[:3], "abc", -1}, {"xabxc", "abc", -1}, {"", "abcd", -1}, {"xbcd", "abcd", -1}, {"abcd", "abcd", 0}, {"xabcd", "abcd", 1}, {"xyabcd"[:5], "abcd", -1}, {"xbcqq", "abcqq", -1}, {"abcqq", "abcqq", 0}, {"xabcqq", "abcqq", 1}, {"xyabcqq"[:6], "abcqq", -1}, {"xabxcqq", "abcqq", -1}, {"xabcqxq", "abcqq", -1}, {"", "01234567", -1}, {"32145678", "01234567", -1}, {"01234567", "01234567", 0}, {"x01234567", "01234567", 1}, {"xx01234567"[:9], "01234567", -1}, {"", "0123456789", -1}, {"3214567844", "0123456789", -1}, {"0123456789", "0123456789", 0}, {"x0123456789", "0123456789", 1}, {"xyz0123456789"[:12], "0123456789", -1}, {"x01234567x89", "0123456789", -1}, {"", "0123456789012345", -1}, {"3214567889012345", "0123456789012345", -1}, {"0123456789012345", "0123456789012345", 0}, {"x0123456789012345", "0123456789012345", 1}, {"", "01234567890123456789", -1}, {"32145678890123456789", "01234567890123456789", -1}, {"01234567890123456789", "01234567890123456789", 0}, {"x01234567890123456789", "01234567890123456789", 1}, {"xyz01234567890123456789"[:22], "01234567890123456789", -1}, {"", "0123456789012345678901234567890", -1}, {"321456788901234567890123456789012345678911", "0123456789012345678901234567890", -1}, {"0123456789012345678901234567890", "0123456789012345678901234567890", 0}, {"x0123456789012345678901234567890", "0123456789012345678901234567890", 1}, {"xyz0123456789012345678901234567890"[:33], "0123456789012345678901234567890", -1}, {"", "01234567890123456789012345678901", -1}, {"32145678890123456789012345678901234567890211", "01234567890123456789012345678901", -1}, {"01234567890123456789012345678901", "01234567890123456789012345678901", 0}, {"x01234567890123456789012345678901", "01234567890123456789012345678901", 1}, {"xyz01234567890123456789012345678901"[:34], "01234567890123456789012345678901", -1},} var lastIndexTests = []IndexTest{ {"", "", 0}, {"", "a", -1}, {"", "foo", -1}, {"fo", "foo", -1}, {"foo", "foo", 0}, {"foo", "f", 0}, {"oofofoofooo", "f", 7}, {"oofofoofooo", "foo", 7}, {"barfoobarfoo", "foo", 9}, {"foo", "", 3}, {"foo", "o", 2}, {"abcABCabc", "A", 3}, {"abcABCabc", "a", 6},} var indexAnyTests = []IndexTest{ {"", "", -1}, {"", "a", -1}, {"", "abc", -1}, {"a", "", -1}, {"a", "a", 0}, {"aaa", "a", 0}, {"abc", "xyz", -1}, {"abc", "xcz", 2}, {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")}, {"aRegExp*", ".(|)*+?^$[]", 7}, {dots + dots + dots, " ", -1},}var lastIndexAnyTests = []IndexTest{ {"", "", -1}, {"", "a", -1}, {"", "abc", -1}, {"a", "", -1}, {"a", "a", 0}, {"aaa", "a", 2}, {"abc", "xyz", -1}, {"abc", "ab", 1}, {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")}, {"a.RegExp*", ".(|)*+?^$[]", 8}, {dots + dots + dots, " ", -1},} // Execute f on each test case. funcName should be the name of f; it's used// in failure reports.func runIndexTests(t *testing.T, f func(s, sep string) int, funcName string, testCases []IndexTest) { for _, test := range testCases { actual := f(test.s, test.sep) if actual != test.out { t.Errorf("%s(%q,%q) = %v; want %v", funcName, test.s, test.sep, actual, test.out) } }} func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) }func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) }func TestIndexAny(t *testing.T) { runIndexTests(t, IndexAny, "IndexAny", indexAnyTests) }func TestLastIndexAny(t *testing.T) { runIndexTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests) } func TestLastIndexByte(t *testing.T) { testCases := []IndexTest{ {"", "q", -1}, {"abcdef", "q", -1}, {"abcdefabcdef", "a", len("abcdef")}, // something in the middle {"abcdefabcdef", "f", len("abcdefabcde")}, // last byte {"zabcdefabcdef", "z", 0}, // first byte {"a☺b☻c☹d", "b", len("a☺")}, // non-ascii } for _, test := range testCases { actual := LastIndexByte(test.s, test.sep[0]) if actual != test.out { t.Errorf("LastIndexByte(%q,%c) = %v; want %v", test.s, test.sep[0], actual, test.out) } }} var indexRuneTests = []struct { s string rune rune out int}{ {"a A x", 'A', 2}, {"some_text=some_value", '=', 9}, {"☺a", 'a', 3}, {"a☻☺b", '☺', 4},} func TestIndexRune(t *testing.T) { for _, test := range indexRuneTests { if actual := IndexRune(test.s, test.rune); actual != test.out { t.Errorf("IndexRune(%q,%d)= %v; want %v", test.s, test.rune, actual, test.out) } }} const benchmarkString = "some_text=some☺value" func BenchmarkIndexRune(b *testing.B) { if got := IndexRune(benchmarkString, '☺'); got != 14 { b.Fatalf("wrong index: expected 14, got=%d", got) } for i := 0; i < b.N; i++ { IndexRune(benchmarkString, '☺') }} func BenchmarkIndexRuneFastPath(b *testing.B) { if got := IndexRune(benchmarkString, 'v'); got != 17 { b.Fatalf("wrong index: expected 17, got=%d", got) } for i := 0; i < b.N; i++ { IndexRune(benchmarkString, 'v') }} func BenchmarkIndex(b *testing.B) { if got := Index(benchmarkString, "v"); got != 17 { b.Fatalf("wrong index: expected 17, got=%d", got) } for i := 0; i < b.N; i++ { Index(benchmarkString, "v") }} func BenchmarkLastIndex(b *testing.B) { if got := Index(benchmarkString, "v"); got != 17 { b.Fatalf("wrong index: expected 17, got=%d", got) } for i := 0; i < b.N; i++ { LastIndex(benchmarkString, "v") }} func BenchmarkIndexByte(b *testing.B) { if got := IndexByte(benchmarkString, 'v'); got != 17 { b.Fatalf("wrong index: expected 17, got=%d", got) } for i := 0; i < b.N; i++ { IndexByte(benchmarkString, 'v') }} var explodetests = []struct { s string n int a []string}{ {"", -1, []string{}}, {abcd, 4, []string{"a", "b", "c", "d"}}, {faces, 3, []string{"☺", "☻", "☹"}}, {abcd, 2, []string{"a", "bcd"}},} func TestExplode(t *testing.T) { for _, tt := range explodetests { a := SplitN(tt.s, "", tt.n) if !eq(a, tt.a) { t.Errorf("explode(%q, %d) = %v; want %v", tt.s, tt.n, a, tt.a) continue } s := Join(a, "") if s != tt.s { t.Errorf(`Join(explode(%q, %d), "") = %q`, tt.s, tt.n, s) } }} type SplitTest struct { s string sep string n int a []string} var splittests = []SplitTest{ {abcd, "a", 0, nil}, {abcd, "a", -1, []string{"", "bcd"}}, {abcd, "z", -1, []string{"abcd"}}, {abcd, "", -1, []string{"a", "b", "c", "d"}}, {commas, ",", -1, []string{"1", "2", "3", "4"}}, {dots, "...", -1, []string{"1", ".2", ".3", ".4"}}, {faces, "☹", -1, []string{"☺☻", ""}}, {faces, "~", -1, []string{faces}}, {faces, "", -1, []string{"☺", "☻", "☹"}}, {"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}}, {"1 2", " ", 3, []string{"1", "2"}}, {"123", "", 2, []string{"1", "23"}}, {"123", "", 17, []string{"1", "2", "3"}},} func TestSplit(t *testing.T) { for _, tt := range splittests { a := SplitN(tt.s, tt.sep, tt.n) if !eq(a, tt.a) { t.Errorf("Split(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, a, tt.a) continue } if tt.n == 0 { continue } s := Join(a, tt.sep) if s != tt.s { t.Errorf("Join(Split(%q, %q, %d), %q) = %q", tt.s, tt.sep, tt.n, tt.sep, s) } if tt.n < 0 { b := Split(tt.s, tt.sep) if !reflect.DeepEqual(a, b) { t.Errorf("Split disagrees with SplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a) } } }} var splitaftertests = []SplitTest{ {abcd, "a", -1, []string{"a", "bcd"}}, {abcd, "z", -1, []string{"abcd"}}, {abcd, "", -1, []string{"a", "b", "c", "d"}}, {commas, ",", -1, []string{"1,", "2,", "3,", "4"}}, {dots, "...", -1, []string{"1...", ".2...", ".3...", ".4"}}, {faces, "☹", -1, []string{"☺☻☹", ""}}, {faces, "~", -1, []string{faces}}, {faces, "", -1, []string{"☺", "☻", "☹"}}, {"1 2 3 4", " ", 3, []string{"1 ", "2 ", "3 4"}}, {"1 2 3", " ", 3, []string{"1 ", "2 ", "3"}}, {"1 2", " ", 3, []string{"1 ", "2"}}, {"123", "", 2, []string{"1", "23"}}, {"123", "", 17, []string{"1", "2", "3"}},} func TestSplitAfter(t *testing.T) { for _, tt := range splitaftertests { a := SplitAfterN(tt.s, tt.sep, tt.n) if !eq(a, tt.a) { t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, a, tt.a) continue } s := Join(a, "") if s != tt.s { t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s) } if tt.n < 0 { b := SplitAfter(tt.s, tt.sep) if !reflect.DeepEqual(a, b) { t.Errorf("SplitAfter disagrees with SplitAfterN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a) } } }} type FieldsTest struct { s string a []string} var fieldstests = []FieldsTest{ {"", []string{}}, {" ", []string{}}, {" \t ", []string{}}, {" abc ", []string{"abc"}}, {"1 2 3 4", []string{"1", "2", "3", "4"}}, {"1 2 3 4", []string{"1", "2", "3", "4"}}, {"1\t\t2\t\t3\t4", []string{"1", "2", "3", "4"}}, {"1\u20002\u20013\u20024", []string{"1", "2", "3", "4"}}, {"\u2000\u2001\u2002", []string{}}, {"\n™\t™\n", []string{"™", "™"}}, {faces, []string{faces}},} func TestFields(t *testing.T) { for _, tt := range fieldstests { a := Fields(tt.s) if !eq(a, tt.a) { t.Errorf("Fields(%q) = %v; want %v", tt.s, a, tt.a) continue } }} var FieldsFuncTests = []FieldsTest{ {"", []string{}}, {"XX", []string{}}, {"XXhiXXX", []string{"hi"}}, {"aXXbXXXcX", []string{"a", "b", "c"}},} func TestFieldsFunc(t *testing.T) { for _, tt := range fieldstests { a := FieldsFunc(tt.s, unicode.IsSpace) if !eq(a, tt.a) { t.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt.s, a, tt.a) continue } } pred := func(c rune) bool { return c == 'X' } for _, tt := range FieldsFuncTests { a := FieldsFunc(tt.s, pred) if !eq(a, tt.a) { t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a) } }} // Test case for any function which accepts and returns a single string.type StringTest struct { in, out string} // Execute f on each test case. funcName should be the name of f; it's used// in failure reports.func runStringTests(t *testing.T, f func(string) string, funcName string, testCases []StringTest) { for _, tc := range testCases { actual := f(tc.in) if actual != tc.out { t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out) } }} var upperTests = []StringTest{ {"", ""}, {"abc", "ABC"}, {"AbC123", "ABC123"}, {"azAZ09_", "AZAZ09_"}, {"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char} var lowerTests = []StringTest{ {"", ""}, {"abc", "abc"}, {"AbC123", "abc123"}, {"azAZ09_", "azaz09_"}, {"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char} const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000" var trimSpaceTests = []StringTest{ {"", ""}, {"abc", "abc"}, {space + "abc" + space, "abc"}, {" ", ""}, {" \t\r\n \t\t\r\r\n\n ", ""}, {" \t\r\n x\t\t\r\r\n\n ", "x"}, {" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"}, {"1 \t\r\n2", "1 \t\r\n2"}, {" x\x80", "x\x80"}, {" x\xc0", "x\xc0"}, {"x \xc0\xc0 ", "x \xc0\xc0"}, {"x \xc0", "x \xc0"}, {"x \xc0 ", "x \xc0"}, {"x \xc0\xc0 ", "x \xc0\xc0"}, {"x ☺\xc0\xc0 ", "x ☺\xc0\xc0"}, {"x ☺ ", "x ☺"},} func tenRunes(ch rune) string { r := make([]rune, 10) for i := range r { r[i] = ch } return string(r)} // User-defined self-inverse mapping functionfunc rot13(r rune) rune { step := rune(13) if r >= 'a' && r <= 'z' { return ((r - 'a' + step) % 26) + 'a' } if r >= 'A' && r <= 'Z' { return ((r - 'A' + step) % 26) + 'A' } return r} func TestMap(t *testing.T) { // Run a couple of awful growth/shrinkage tests a := tenRunes('a') // 1. Grow. This triggers two reallocations in Map. maxRune := func(rune) rune { return unicode.MaxRune } m := Map(maxRune, a) expect := tenRunes(unicode.MaxRune) if m != expect { t.Errorf("growing: expected %q got %q", expect, m)Lines 1–500 of 1303. Load more
// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package strings_test import ( "bytes" "io" "math/rand" "reflect" . "strings" "testing" "unicode" "unicode/utf8" "unsafe" ) func eq(a, b []string) bool { if len(a) != len(b) { return false } for i := 0; i < len(a); i++ { if a[i] != b[i] { return false } } return true } var abcd = "abcd" var faces = "☺☻☹" var commas = "1,2,3,4" var dots = "1....2....3....4" type IndexTest struct { s string sep string out int } var indexTests = []IndexTest{ {"", "", 0}, {"", "a", -1}, {"", "foo", -1}, {"fo", "foo", -1}, {"foo", "foo", 0}, {"oofofoofooo", "f", 2}, {"oofofoofooo", "foo", 4}, {"barfoobarfoo", "foo", 3}, {"foo", "", 0}, {"foo", "o", 1}, {"abcABCabc", "A", 3}, // cases with one byte strings - test special case in Index() {"", "a", -1}, {"x", "a", -1}, {"x", "x", 0}, {"abc", "a", 0}, {"abc", "b", 1}, {"abc", "c", 2}, {"abc", "x", -1}, // test special cases in Index() for short strings {"", "ab", -1}, {"bc", "ab", -1}, {"ab", "ab", 0}, {"xab", "ab", 1}, {"xab"[:2], "ab", -1}, {"", "abc", -1}, {"xbc", "abc", -1}, {"abc", "abc", 0}, {"xabc", "abc", 1}, {"xabc"[:3], "abc", -1}, {"xabxc", "abc", -1}, {"", "abcd", -1}, {"xbcd", "abcd", -1}, {"abcd", "abcd", 0}, {"xabcd", "abcd", 1}, {"xyabcd"[:5], "abcd", -1}, {"xbcqq", "abcqq", -1}, {"abcqq", "abcqq", 0}, {"xabcqq", "abcqq", 1}, {"xyabcqq"[:6], "abcqq", -1}, {"xabxcqq", "abcqq", -1}, {"xabcqxq", "abcqq", -1}, {"", "01234567", -1}, {"32145678", "01234567", -1}, {"01234567", "01234567", 0}, {"x01234567", "01234567", 1}, {"xx01234567"[:9], "01234567", -1}, {"", "0123456789", -1}, {"3214567844", "0123456789", -1}, {"0123456789", "0123456789", 0}, {"x0123456789", "0123456789", 1}, {"xyz0123456789"[:12], "0123456789", -1}, {"x01234567x89", "0123456789", -1}, {"", "0123456789012345", -1}, {"3214567889012345", "0123456789012345", -1}, {"0123456789012345", "0123456789012345", 0}, {"x0123456789012345", "0123456789012345", 1}, {"", "01234567890123456789", -1}, {"32145678890123456789", "01234567890123456789", -1}, {"01234567890123456789", "01234567890123456789", 0}, {"x01234567890123456789", "01234567890123456789", 1}, {"xyz01234567890123456789"[:22], "01234567890123456789", -1}, {"", "0123456789012345678901234567890", -1}, {"321456788901234567890123456789012345678911", "0123456789012345678901234567890", -1}, {"0123456789012345678901234567890", "0123456789012345678901234567890", 0}, {"x0123456789012345678901234567890", "0123456789012345678901234567890", 1}, {"xyz0123456789012345678901234567890"[:33], "0123456789012345678901234567890", -1}, {"", "01234567890123456789012345678901", -1}, {"32145678890123456789012345678901234567890211", "01234567890123456789012345678901", -1}, {"01234567890123456789012345678901", "01234567890123456789012345678901", 0}, {"x01234567890123456789012345678901", "01234567890123456789012345678901", 1}, {"xyz01234567890123456789012345678901"[:34], "01234567890123456789012345678901", -1}, } var lastIndexTests = []IndexTest{ {"", "", 0}, {"", "a", -1}, {"", "foo", -1}, {"fo", "foo", -1}, {"foo", "foo", 0}, {"foo", "f", 0}, {"oofofoofooo", "f", 7}, {"oofofoofooo", "foo", 7}, {"barfoobarfoo", "foo", 9}, {"foo", "", 3}, {"foo", "o", 2}, {"abcABCabc", "A", 3}, {"abcABCabc", "a", 6}, } var indexAnyTests = []IndexTest{ {"", "", -1}, {"", "a", -1}, {"", "abc", -1}, {"a", "", -1}, {"a", "a", 0}, {"aaa", "a", 0}, {"abc", "xyz", -1}, {"abc", "xcz", 2}, {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")}, {"aRegExp*", ".(|)*+?^$[]", 7}, {dots + dots + dots, " ", -1}, } var lastIndexAnyTests = []IndexTest{ {"", "", -1}, {"", "a", -1}, {"", "abc", -1}, {"a", "", -1}, {"a", "a", 0}, {"aaa", "a", 2}, {"abc", "xyz", -1}, {"abc", "ab", 1}, {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")}, {"a.RegExp*", ".(|)*+?^$[]", 8}, {dots + dots + dots, " ", -1}, } // Execute f on each test case. funcName should be the name of f; it's used // in failure reports. func runIndexTests(t *testing.T, f func(s, sep string) int, funcName string, testCases []IndexTest) { for _, test := range testCases { actual := f(test.s, test.sep) if actual != test.out { t.Errorf("%s(%q,%q) = %v; want %v", funcName, test.s, test.sep, actual, test.out) } } } func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) } func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) } func TestIndexAny(t *testing.T) { runIndexTests(t, IndexAny, "IndexAny", indexAnyTests) } func TestLastIndexAny(t *testing.T) { runIndexTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests) } func TestLastIndexByte(t *testing.T) { testCases := []IndexTest{ {"", "q", -1}, {"abcdef", "q", -1}, {"abcdefabcdef", "a", len("abcdef")}, // something in the middle {"abcdefabcdef", "f", len("abcdefabcde")}, // last byte {"zabcdefabcdef", "z", 0}, // first byte {"a☺b☻c☹d", "b", len("a☺")}, // non-ascii } for _, test := range testCases { actual := LastIndexByte(test.s, test.sep[0]) if actual != test.out { t.Errorf("LastIndexByte(%q,%c) = %v; want %v", test.s, test.sep[0], actual, test.out) } } } var indexRuneTests = []struct { s string rune rune out int }{ {"a A x", 'A', 2}, {"some_text=some_value", '=', 9}, {"☺a", 'a', 3}, {"a☻☺b", '☺', 4}, } func TestIndexRune(t *testing.T) { for _, test := range indexRuneTests { if actual := IndexRune(test.s, test.rune); actual != test.out { t.Errorf("IndexRune(%q,%d)= %v; want %v", test.s, test.rune, actual, test.out) } } } const benchmarkString = "some_text=some☺value" func BenchmarkIndexRune(b *testing.B) { if got := IndexRune(benchmarkString, '☺'); got != 14 { b.Fatalf("wrong index: expected 14, got=%d", got) } for i := 0; i < b.N; i++ { IndexRune(benchmarkString, '☺') } } func BenchmarkIndexRuneFastPath(b *testing.B) { if got := IndexRune(benchmarkString, 'v'); got != 17 { b.Fatalf("wrong index: expected 17, got=%d", got) } for i := 0; i < b.N; i++ { IndexRune(benchmarkString, 'v') } } func BenchmarkIndex(b *testing.B) { if got := Index(benchmarkString, "v"); got != 17 { b.Fatalf("wrong index: expected 17, got=%d", got) } for i := 0; i < b.N; i++ { Index(benchmarkString, "v") } } func BenchmarkLastIndex(b *testing.B) { if got := Index(benchmarkString, "v"); got != 17 { b.Fatalf("wrong index: expected 17, got=%d", got) } for i := 0; i < b.N; i++ { LastIndex(benchmarkString, "v") } } func BenchmarkIndexByte(b *testing.B) { if got := IndexByte(benchmarkString, 'v'); got != 17 { b.Fatalf("wrong index: expected 17, got=%d", got) } for i := 0; i < b.N; i++ { IndexByte(benchmarkString, 'v') } } var explodetests = []struct { s string n int a []string }{ {"", -1, []string{}}, {abcd, 4, []string{"a", "b", "c", "d"}}, {faces, 3, []string{"☺", "☻", "☹"}}, {abcd, 2, []string{"a", "bcd"}}, } func TestExplode(t *testing.T) { for _, tt := range explodetests { a := SplitN(tt.s, "", tt.n) if !eq(a, tt.a) { t.Errorf("explode(%q, %d) = %v; want %v", tt.s, tt.n, a, tt.a) continue } s := Join(a, "") if s != tt.s { t.Errorf(`Join(explode(%q, %d), "") = %q`, tt.s, tt.n, s) } } } type SplitTest struct { s string sep string n int a []string } var splittests = []SplitTest{ {abcd, "a", 0, nil}, {abcd, "a", -1, []string{"", "bcd"}}, {abcd, "z", -1, []string{"abcd"}}, {abcd, "", -1, []string{"a", "b", "c", "d"}}, {commas, ",", -1, []string{"1", "2", "3", "4"}}, {dots, "...", -1, []string{"1", ".2", ".3", ".4"}}, {faces, "☹", -1, []string{"☺☻", ""}}, {faces, "~", -1, []string{faces}}, {faces, "", -1, []string{"☺", "☻", "☹"}}, {"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}}, {"1 2", " ", 3, []string{"1", "2"}}, {"123", "", 2, []string{"1", "23"}}, {"123", "", 17, []string{"1", "2", "3"}}, } func TestSplit(t *testing.T) { for _, tt := range splittests { a := SplitN(tt.s, tt.sep, tt.n) if !eq(a, tt.a) { t.Errorf("Split(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, a, tt.a) continue } if tt.n == 0 { continue } s := Join(a, tt.sep) if s != tt.s { t.Errorf("Join(Split(%q, %q, %d), %q) = %q", tt.s, tt.sep, tt.n, tt.sep, s) } if tt.n < 0 { b := Split(tt.s, tt.sep) if !reflect.DeepEqual(a, b) { t.Errorf("Split disagrees with SplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a) } } } } var splitaftertests = []SplitTest{ {abcd, "a", -1, []string{"a", "bcd"}}, {abcd, "z", -1, []string{"abcd"}}, {abcd, "", -1, []string{"a", "b", "c", "d"}}, {commas, ",", -1, []string{"1,", "2,", "3,", "4"}}, {dots, "...", -1, []string{"1...", ".2...", ".3...", ".4"}}, {faces, "☹", -1, []string{"☺☻☹", ""}}, {faces, "~", -1, []string{faces}}, {faces, "", -1, []string{"☺", "☻", "☹"}}, {"1 2 3 4", " ", 3, []string{"1 ", "2 ", "3 4"}}, {"1 2 3", " ", 3, []string{"1 ", "2 ", "3"}}, {"1 2", " ", 3, []string{"1 ", "2"}}, {"123", "", 2, []string{"1", "23"}}, {"123", "", 17, []string{"1", "2", "3"}}, } func TestSplitAfter(t *testing.T) { for _, tt := range splitaftertests { a := SplitAfterN(tt.s, tt.sep, tt.n) if !eq(a, tt.a) { t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, a, tt.a) continue } s := Join(a, "") if s != tt.s { t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s) } if tt.n < 0 { b := SplitAfter(tt.s, tt.sep) if !reflect.DeepEqual(a, b) { t.Errorf("SplitAfter disagrees with SplitAfterN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a) } } } } type FieldsTest struct { s string a []string } var fieldstests = []FieldsTest{ {"", []string{}}, {" ", []string{}}, {" \t ", []string{}}, {" abc ", []string{"abc"}}, {"1 2 3 4", []string{"1", "2", "3", "4"}}, {"1 2 3 4", []string{"1", "2", "3", "4"}}, {"1\t\t2\t\t3\t4", []string{"1", "2", "3", "4"}}, {"1\u20002\u20013\u20024", []string{"1", "2", "3", "4"}}, {"\u2000\u2001\u2002", []string{}}, {"\n™\t™\n", []string{"™", "™"}}, {faces, []string{faces}}, } func TestFields(t *testing.T) { for _, tt := range fieldstests { a := Fields(tt.s) if !eq(a, tt.a) { t.Errorf("Fields(%q) = %v; want %v", tt.s, a, tt.a) continue } } } var FieldsFuncTests = []FieldsTest{ {"", []string{}}, {"XX", []string{}}, {"XXhiXXX", []string{"hi"}}, {"aXXbXXXcX", []string{"a", "b", "c"}}, } func TestFieldsFunc(t *testing.T) { for _, tt := range fieldstests { a := FieldsFunc(tt.s, unicode.IsSpace) if !eq(a, tt.a) { t.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt.s, a, tt.a) continue } } pred := func(c rune) bool { return c == 'X' } for _, tt := range FieldsFuncTests { a := FieldsFunc(tt.s, pred) if !eq(a, tt.a) { t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a) } } } // Test case for any function which accepts and returns a single string. type StringTest struct { in, out string } // Execute f on each test case. funcName should be the name of f; it's used // in failure reports. func runStringTests(t *testing.T, f func(string) string, funcName string, testCases []StringTest) { for _, tc := range testCases { actual := f(tc.in) if actual != tc.out { t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out) } } } var upperTests = []StringTest{ {"", ""}, {"abc", "ABC"}, {"AbC123", "ABC123"}, {"azAZ09_", "AZAZ09_"}, {"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char } var lowerTests = []StringTest{ {"", ""}, {"abc", "abc"}, {"AbC123", "abc123"}, {"azAZ09_", "azaz09_"}, {"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char } const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000" var trimSpaceTests = []StringTest{ {"", ""}, {"abc", "abc"}, {space + "abc" + space, "abc"}, {" ", ""}, {" \t\r\n \t\t\r\r\n\n ", ""}, {" \t\r\n x\t\t\r\r\n\n ", "x"}, {" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"}, {"1 \t\r\n2", "1 \t\r\n2"}, {" x\x80", "x\x80"}, {" x\xc0", "x\xc0"}, {"x \xc0\xc0 ", "x \xc0\xc0"}, {"x \xc0", "x \xc0"}, {"x \xc0 ", "x \xc0"}, {"x \xc0\xc0 ", "x \xc0\xc0"}, {"x ☺\xc0\xc0 ", "x ☺\xc0\xc0"}, {"x ☺ ", "x ☺"}, } func tenRunes(ch rune) string { r := make([]rune, 10) for i := range r { r[i] = ch } return string(r) } // User-defined self-inverse mapping function func rot13(r rune) rune { step := rune(13) if r >= 'a' && r <= 'z' { return ((r - 'a' + step) % 26) + 'a' } if r >= 'A' && r <= 'Z' { return ((r - 'A' + step) % 26) + 'A' } return r } func TestMap(t *testing.T) { // Run a couple of awful growth/shrinkage tests a := tenRunes('a') // 1. Grow. This triggers two reallocations in Map. maxRune := func(rune) rune { return unicode.MaxRune } m := Map(maxRune, a) expect := tenRunes(unicode.MaxRune) if m != expect { t.Errorf("growing: expected %q got %q", expect, m)