summaryrefslogtreecommitdiff
path: root/src/pkg/strings/strings_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/strings/strings_test.go')
-rw-r--r--src/pkg/strings/strings_test.go313
1 files changed, 186 insertions, 127 deletions
diff --git a/src/pkg/strings/strings_test.go b/src/pkg/strings/strings_test.go
index 409d4da0e..54046d68a 100644
--- a/src/pkg/strings/strings_test.go
+++ b/src/pkg/strings/strings_test.go
@@ -6,14 +6,13 @@ package strings_test
import (
"bytes"
- "os"
+ "io"
"reflect"
- "strconv"
. "strings"
"testing"
"unicode"
+ "unicode/utf8"
"unsafe"
- "utf8"
)
func eq(a, b []string) bool {
@@ -120,13 +119,11 @@ func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", l
func TestIndexAny(t *testing.T) { runIndexTests(t, IndexAny, "IndexAny", indexAnyTests) }
func TestLastIndexAny(t *testing.T) { runIndexTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests) }
-type IndexRuneTest struct {
+var indexRuneTests = []struct {
s string
- rune int
+ rune rune
out int
-}
-
-var indexRuneTests = []IndexRuneTest{
+}{
{"a A x", 'A', 2},
{"some_text=some_value", '=', 9},
{"☺a", 'a', 3},
@@ -145,7 +142,7 @@ const benchmarkString = "some_text=some☺value"
func BenchmarkIndexRune(b *testing.B) {
if got := IndexRune(benchmarkString, '☺'); got != 14 {
- panic("wrong index: got=" + strconv.Itoa(got))
+ b.Fatalf("wrong index: expected 14, got=%d", got)
}
for i := 0; i < b.N; i++ {
IndexRune(benchmarkString, '☺')
@@ -154,7 +151,7 @@ func BenchmarkIndexRune(b *testing.B) {
func BenchmarkIndexRuneFastPath(b *testing.B) {
if got := IndexRune(benchmarkString, 'v'); got != 17 {
- panic("wrong index: got=" + strconv.Itoa(got))
+ b.Fatalf("wrong index: expected 17, got=%d", got)
}
for i := 0; i < b.N; i++ {
IndexRune(benchmarkString, 'v')
@@ -163,20 +160,18 @@ func BenchmarkIndexRuneFastPath(b *testing.B) {
func BenchmarkIndex(b *testing.B) {
if got := Index(benchmarkString, "v"); got != 17 {
- panic("wrong index: got=" + strconv.Itoa(got))
+ b.Fatalf("wrong index: expected 17, got=%d", got)
}
for i := 0; i < b.N; i++ {
Index(benchmarkString, "v")
}
}
-type ExplodeTest struct {
+var explodetests = []struct {
s string
n int
a []string
-}
-
-var explodetests = []ExplodeTest{
+}{
{"", -1, []string{}},
{abcd, 4, []string{"a", "b", "c", "d"}},
{faces, 3, []string{"☺", "☻", "☹"}},
@@ -308,15 +303,16 @@ func TestFields(t *testing.T) {
}
}
+var FieldsFuncTests = []FieldsTest{
+ {"", []string{}},
+ {"XX", []string{}},
+ {"XXhiXXX", []string{"hi"}},
+ {"aXXbXXXcX", []string{"a", "b", "c"}},
+}
+
func TestFieldsFunc(t *testing.T) {
- pred := func(c int) bool { return c == 'X' }
- var fieldsFuncTests = []FieldsTest{
- {"", []string{}},
- {"XX", []string{}},
- {"XXhiXXX", []string{"hi"}},
- {"aXXbXXXcX", []string{"a", "b", "c"}},
- }
- for _, tt := range fieldsFuncTests {
+ 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)
@@ -377,31 +373,31 @@ var trimSpaceTests = []StringTest{
{"x ☺ ", "x ☺"},
}
-func tenRunes(rune int) string {
- r := make([]int, 10)
+func tenRunes(ch rune) string {
+ r := make([]rune, 10)
for i := range r {
- r[i] = rune
+ r[i] = ch
}
return string(r)
}
// User-defined self-inverse mapping function
-func rot13(rune int) int {
- step := 13
- if rune >= 'a' && rune <= 'z' {
- return ((rune - 'a' + step) % 26) + 'a'
+func rot13(r rune) rune {
+ step := rune(13)
+ if r >= 'a' && r <= 'z' {
+ return ((r - 'a' + step) % 26) + 'a'
}
- if rune >= 'A' && rune <= 'Z' {
- return ((rune - 'A' + step) % 26) + 'A'
+ if r >= 'A' && r <= 'Z' {
+ return ((r - 'A' + step) % 26) + 'A'
}
- return rune
+ 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 int) int { return unicode.MaxRune }
+ maxRune := func(rune) rune { return unicode.MaxRune }
m := Map(maxRune, a)
expect := tenRunes(unicode.MaxRune)
if m != expect {
@@ -409,7 +405,7 @@ func TestMap(t *testing.T) {
}
// 2. Shrink
- minRune := func(rune int) int { return 'a' }
+ minRune := func(rune) rune { return 'a' }
m = Map(minRune, tenRunes(unicode.MaxRune))
expect = a
if m != expect {
@@ -431,9 +427,9 @@ func TestMap(t *testing.T) {
}
// 5. Drop
- dropNotLatin := func(rune int) int {
- if unicode.Is(unicode.Latin, rune) {
- return rune
+ dropNotLatin := func(r rune) rune {
+ if unicode.Is(unicode.Latin, r) {
+ return r
}
return -1
}
@@ -444,8 +440,8 @@ func TestMap(t *testing.T) {
}
// 6. Identity
- identity := func(rune int) int {
- return rune
+ identity := func(r rune) rune {
+ return r
}
orig := "Input string that we expect not to be copied."
m = Map(identity, orig)
@@ -460,8 +456,8 @@ func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTest
func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) }
func BenchmarkMapNoChanges(b *testing.B) {
- identity := func(rune int) int {
- return rune
+ identity := func(r rune) rune {
+ return r
}
for i := 0; i < b.N; i++ {
Map(identity, "Some string that won't be modified.")
@@ -491,49 +487,48 @@ func TestSpecialCase(t *testing.T) {
func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
-type TrimTest struct {
- f func(string, string) string
+var trimTests = []struct {
+ f string
in, cutset, out string
-}
-
-var trimTests = []TrimTest{
- {Trim, "abba", "a", "bb"},
- {Trim, "abba", "ab", ""},
- {TrimLeft, "abba", "ab", ""},
- {TrimRight, "abba", "ab", ""},
- {TrimLeft, "abba", "a", "bba"},
- {TrimRight, "abba", "a", "abb"},
- {Trim, "<tag>", "<>", "tag"},
- {Trim, "* listitem", " *", "listitem"},
- {Trim, `"quote"`, `"`, "quote"},
- {Trim, "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
+}{
+ {"Trim", "abba", "a", "bb"},
+ {"Trim", "abba", "ab", ""},
+ {"TrimLeft", "abba", "ab", ""},
+ {"TrimRight", "abba", "ab", ""},
+ {"TrimLeft", "abba", "a", "bba"},
+ {"TrimRight", "abba", "a", "abb"},
+ {"Trim", "<tag>", "<>", "tag"},
+ {"Trim", "* listitem", " *", "listitem"},
+ {"Trim", `"quote"`, `"`, "quote"},
+ {"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
//empty string tests
- {Trim, "abba", "", "abba"},
- {Trim, "", "123", ""},
- {Trim, "", "", ""},
- {TrimLeft, "abba", "", "abba"},
- {TrimLeft, "", "123", ""},
- {TrimLeft, "", "", ""},
- {TrimRight, "abba", "", "abba"},
- {TrimRight, "", "123", ""},
- {TrimRight, "", "", ""},
- {TrimRight, "☺\xc0", "☺", "☺\xc0"},
+ {"Trim", "abba", "", "abba"},
+ {"Trim", "", "123", ""},
+ {"Trim", "", "", ""},
+ {"TrimLeft", "abba", "", "abba"},
+ {"TrimLeft", "", "123", ""},
+ {"TrimLeft", "", "", ""},
+ {"TrimRight", "abba", "", "abba"},
+ {"TrimRight", "", "123", ""},
+ {"TrimRight", "", "", ""},
+ {"TrimRight", "☺\xc0", "☺", "☺\xc0"},
}
func TestTrim(t *testing.T) {
for _, tc := range trimTests {
- actual := tc.f(tc.in, tc.cutset)
- var name string
- switch tc.f {
- case Trim:
- name = "Trim"
- case TrimLeft:
- name = "TrimLeft"
- case TrimRight:
- name = "TrimRight"
+ name := tc.f
+ var f func(string, string) string
+ switch name {
+ case "Trim":
+ f = Trim
+ case "TrimLeft":
+ f = TrimLeft
+ case "TrimRight":
+ f = TrimRight
default:
- t.Error("Undefined trim function")
+ t.Errorf("Undefined trim function %s", name)
}
+ actual := f(tc.in, tc.cutset)
if actual != tc.out {
t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
}
@@ -541,7 +536,7 @@ func TestTrim(t *testing.T) {
}
type predicate struct {
- f func(r int) bool
+ f func(rune) bool
name string
}
@@ -549,27 +544,25 @@ var isSpace = predicate{unicode.IsSpace, "IsSpace"}
var isDigit = predicate{unicode.IsDigit, "IsDigit"}
var isUpper = predicate{unicode.IsUpper, "IsUpper"}
var isValidRune = predicate{
- func(r int) bool {
+ func(r rune) bool {
return r != utf8.RuneError
},
"IsValidRune",
}
-type TrimFuncTest struct {
- f predicate
- in, out string
-}
-
func not(p predicate) predicate {
return predicate{
- func(r int) bool {
+ func(r rune) bool {
return !p.f(r)
},
"not " + p.name,
}
}
-var trimFuncTests = []TrimFuncTest{
+var trimFuncTests = []struct {
+ f predicate
+ in, out string
+}{
{isSpace, space + " hello " + space, "hello"},
{isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"},
{isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"},
@@ -588,13 +581,11 @@ func TestTrimFunc(t *testing.T) {
}
}
-type IndexFuncTest struct {
+var indexFuncTests = []struct {
in string
f predicate
first, last int
-}
-
-var indexFuncTests = []IndexFuncTest{
+}{
{"", isValidRune, -1, -1},
{"abc", isDigit, -1, -1},
{"0123", isDigit, 0, 3},
@@ -650,13 +641,13 @@ func equal(m string, s1, s2 string, t *testing.T) bool {
func TestCaseConsistency(t *testing.T) {
// Make a string of all the runes.
- numRunes := unicode.MaxRune + 1
+ numRunes := int(unicode.MaxRune + 1)
if testing.Short() {
numRunes = 1000
}
- a := make([]int, numRunes)
+ a := make([]rune, numRunes)
for i := range a {
- a[i] = i
+ a[i] = rune(i)
}
s := string(a)
// convert the cases.
@@ -692,12 +683,10 @@ func TestCaseConsistency(t *testing.T) {
*/
}
-type RepeatTest struct {
+var RepeatTests = []struct {
in, out string
count int
-}
-
-var RepeatTests = []RepeatTest{
+}{
{"", "", 0},
{"", "", 1},
{"", "", 2},
@@ -717,7 +706,7 @@ func TestRepeat(t *testing.T) {
}
}
-func runesEqual(a, b []int) bool {
+func runesEqual(a, b []rune) bool {
if len(a) != len(b) {
return false
}
@@ -729,34 +718,32 @@ func runesEqual(a, b []int) bool {
return true
}
-type RunesTest struct {
+var RunesTests = []struct {
in string
- out []int
+ out []rune
lossy bool
-}
-
-var RunesTests = []RunesTest{
- {"", []int{}, false},
- {" ", []int{32}, false},
- {"ABC", []int{65, 66, 67}, false},
- {"abc", []int{97, 98, 99}, false},
- {"\u65e5\u672c\u8a9e", []int{26085, 26412, 35486}, false},
- {"ab\x80c", []int{97, 98, 0xFFFD, 99}, true},
- {"ab\xc0c", []int{97, 98, 0xFFFD, 99}, true},
+}{
+ {"", []rune{}, false},
+ {" ", []rune{32}, false},
+ {"ABC", []rune{65, 66, 67}, false},
+ {"abc", []rune{97, 98, 99}, false},
+ {"\u65e5\u672c\u8a9e", []rune{26085, 26412, 35486}, false},
+ {"ab\x80c", []rune{97, 98, 0xFFFD, 99}, true},
+ {"ab\xc0c", []rune{97, 98, 0xFFFD, 99}, true},
}
func TestRunes(t *testing.T) {
for _, tt := range RunesTests {
- a := []int(tt.in)
+ a := []rune(tt.in)
if !runesEqual(a, tt.out) {
- t.Errorf("[]int(%q) = %v; want %v", tt.in, a, tt.out)
+ t.Errorf("[]rune(%q) = %v; want %v", tt.in, a, tt.out)
continue
}
if !tt.lossy {
// can only test reassembly if we didn't lose information
s := string(a)
if s != tt.in {
- t.Errorf("string([]int(%q)) = %x; want %x", tt.in, s, tt.in)
+ t.Errorf("string([]rune(%q)) = %x; want %x", tt.in, s, tt.in)
}
}
}
@@ -772,7 +759,7 @@ func TestReadByte(t *testing.T) {
var res bytes.Buffer
for {
b, e := reader.ReadByte()
- if e == os.EOF {
+ if e == io.EOF {
break
}
if e != nil {
@@ -812,7 +799,7 @@ func TestReadRune(t *testing.T) {
res := ""
for {
r, z, e := reader.ReadRune()
- if e == os.EOF {
+ if e == io.EOF {
break
}
if e != nil {
@@ -846,14 +833,12 @@ func TestReadRune(t *testing.T) {
}
}
-type ReplaceTest struct {
+var ReplaceTests = []struct {
in string
old, new string
n int
out string
-}
-
-var ReplaceTests = []ReplaceTest{
+}{
{"hello", "l", "L", 0, "hello"},
{"hello", "l", "L", -1, "heLLo"},
{"hello", "x", "X", -1, "hello"},
@@ -883,11 +868,9 @@ func TestReplace(t *testing.T) {
}
}
-type TitleTest struct {
+var TitleTests = []struct {
in, out string
-}
-
-var TitleTests = []TitleTest{
+}{
{"", ""},
{"a", "A"},
{" aaa aaa aaa ", " Aaa Aaa Aaa "},
@@ -905,12 +888,10 @@ func TestTitle(t *testing.T) {
}
}
-type ContainsTest struct {
+var ContainsTests = []struct {
str, substr string
expected bool
-}
-
-var ContainsTests = []ContainsTest{
+}{
{"abc", "bc", true},
{"abc", "bcd", false},
{"abc", "", true},
@@ -925,3 +906,81 @@ func TestContains(t *testing.T) {
}
}
}
+
+var ContainsAnyTests = []struct {
+ str, substr string
+ expected bool
+}{
+ {"", "", false},
+ {"", "a", false},
+ {"", "abc", false},
+ {"a", "", false},
+ {"a", "a", true},
+ {"aaa", "a", true},
+ {"abc", "xyz", false},
+ {"abc", "xcz", true},
+ {"a☺b☻c☹d", "uvw☻xyz", true},
+ {"aRegExp*", ".(|)*+?^$[]", true},
+ {dots + dots + dots, " ", false},
+}
+
+func TestContainsAny(t *testing.T) {
+ for _, ct := range ContainsAnyTests {
+ if ContainsAny(ct.str, ct.substr) != ct.expected {
+ t.Errorf("ContainsAny(%s, %s) = %v, want %v",
+ ct.str, ct.substr, !ct.expected, ct.expected)
+ }
+ }
+}
+
+var ContainsRuneTests = []struct {
+ str string
+ r rune
+ expected bool
+}{
+ {"", 'a', false},
+ {"a", 'a', true},
+ {"aaa", 'a', true},
+ {"abc", 'y', false},
+ {"abc", 'c', true},
+ {"a☺b☻c☹d", 'x', false},
+ {"a☺b☻c☹d", '☻', true},
+ {"aRegExp*", '*', true},
+}
+
+func TestContainsRune(t *testing.T) {
+ for _, ct := range ContainsRuneTests {
+ if ContainsRune(ct.str, ct.r) != ct.expected {
+ t.Errorf("ContainsRune(%s, %s) = %v, want %v",
+ ct.str, ct.r, !ct.expected, ct.expected)
+ }
+ }
+}
+
+var EqualFoldTests = []struct {
+ s, t string
+ out bool
+}{
+ {"abc", "abc", true},
+ {"ABcd", "ABcd", true},
+ {"123abc", "123ABC", true},
+ {"αβδ", "ΑΒΔ", true},
+ {"abc", "xyz", false},
+ {"abc", "XYZ", false},
+ {"abcdefghijk", "abcdefghijX", false},
+ {"abcdefghijk", "abcdefghij\u212A", true},
+ {"abcdefghijK", "abcdefghij\u212A", true},
+ {"abcdefghijkz", "abcdefghij\u212Ay", false},
+ {"abcdefghijKz", "abcdefghij\u212Ay", false},
+}
+
+func TestEqualFold(t *testing.T) {
+ for _, tt := range EqualFoldTests {
+ if out := EqualFold(tt.s, tt.t); out != tt.out {
+ t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.s, tt.t, out, tt.out)
+ }
+ if out := EqualFold(tt.t, tt.s); out != tt.out {
+ t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.t, tt.s, out, tt.out)
+ }
+ }
+}