1303 lines · 31.8 KB · Go
RawDownload
// 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.