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. 4 5 package strings_test 6 7 import ( 8 "bytes" 9 "fmt" 10 "io" 11 "math/rand" 12 "reflect" 13 . "strings" 14 "testing" 15 "unicode" 16 "unicode/utf8" 17 "unsafe" 18 ) 19 20 func eq(a, b []string) bool { 21 if len(a) != len(b) { 22 return false 23 } 24 for i := 0; i < len(a); i++ { 25 if a[i] != b[i] { 26 return false 27 } 28 } 29 return true 30 } 31 32 var abcd = "abcd" 33 var faces = "" 34 var commas = "1,2,3,4" 35 var dots = "1....2....3....4" 36 37 type IndexTest struct { 38 s string 39 sep string 40 out int 41 } 42 43 var indexTests = []IndexTest{ 44 {"", "", 0}, 45 {"", "a", -1}, 46 {"", "foo", -1}, 47 {"fo", "foo", -1}, 48 {"foo", "foo", 0}, 49 {"oofofoofooo", "f", 2}, 50 {"oofofoofooo", "foo", 4}, 51 {"barfoobarfoo", "foo", 3}, 52 {"foo", "", 0}, 53 {"foo", "o", 1}, 54 {"abcABCabc", "A", 3}, 55 // cases with one byte strings - test special case in Index() 56 {"", "a", -1}, 57 {"x", "a", -1}, 58 {"x", "x", 0}, 59 {"abc", "a", 0}, 60 {"abc", "b", 1}, 61 {"abc", "c", 2}, 62 {"abc", "x", -1}, 63 // test special cases in Index() for short strings 64 {"", "ab", -1}, 65 {"bc", "ab", -1}, 66 {"ab", "ab", 0}, 67 {"xab", "ab", 1}, 68 {"xab"[:2], "ab", -1}, 69 {"", "abc", -1}, 70 {"xbc", "abc", -1}, 71 {"abc", "abc", 0}, 72 {"xabc", "abc", 1}, 73 {"xabc"[:3], "abc", -1}, 74 {"xabxc", "abc", -1}, 75 {"", "abcd", -1}, 76 {"xbcd", "abcd", -1}, 77 {"abcd", "abcd", 0}, 78 {"xabcd", "abcd", 1}, 79 {"xyabcd"[:5], "abcd", -1}, 80 {"xbcqq", "abcqq", -1}, 81 {"abcqq", "abcqq", 0}, 82 {"xabcqq", "abcqq", 1}, 83 {"xyabcqq"[:6], "abcqq", -1}, 84 {"xabxcqq", "abcqq", -1}, 85 {"xabcqxq", "abcqq", -1}, 86 {"", "01234567", -1}, 87 {"32145678", "01234567", -1}, 88 {"01234567", "01234567", 0}, 89 {"x01234567", "01234567", 1}, 90 {"x0123456x01234567", "01234567", 9}, 91 {"xx01234567"[:9], "01234567", -1}, 92 {"", "0123456789", -1}, 93 {"3214567844", "0123456789", -1}, 94 {"0123456789", "0123456789", 0}, 95 {"x0123456789", "0123456789", 1}, 96 {"x012345678x0123456789", "0123456789", 11}, 97 {"xyz0123456789"[:12], "0123456789", -1}, 98 {"x01234567x89", "0123456789", -1}, 99 {"", "0123456789012345", -1}, 100 {"3214567889012345", "0123456789012345", -1}, 101 {"0123456789012345", "0123456789012345", 0}, 102 {"x0123456789012345", "0123456789012345", 1}, 103 {"x012345678901234x0123456789012345", "0123456789012345", 17}, 104 {"", "01234567890123456789", -1}, 105 {"32145678890123456789", "01234567890123456789", -1}, 106 {"01234567890123456789", "01234567890123456789", 0}, 107 {"x01234567890123456789", "01234567890123456789", 1}, 108 {"x0123456789012345678x01234567890123456789", "01234567890123456789", 21}, 109 {"xyz01234567890123456789"[:22], "01234567890123456789", -1}, 110 {"", "0123456789012345678901234567890", -1}, 111 {"321456788901234567890123456789012345678911", "0123456789012345678901234567890", -1}, 112 {"0123456789012345678901234567890", "0123456789012345678901234567890", 0}, 113 {"x0123456789012345678901234567890", "0123456789012345678901234567890", 1}, 114 {"x012345678901234567890123456789x0123456789012345678901234567890", "0123456789012345678901234567890", 32}, 115 {"xyz0123456789012345678901234567890"[:33], "0123456789012345678901234567890", -1}, 116 {"", "01234567890123456789012345678901", -1}, 117 {"32145678890123456789012345678901234567890211", "01234567890123456789012345678901", -1}, 118 {"01234567890123456789012345678901", "01234567890123456789012345678901", 0}, 119 {"x01234567890123456789012345678901", "01234567890123456789012345678901", 1}, 120 {"x0123456789012345678901234567890x01234567890123456789012345678901", "01234567890123456789012345678901", 33}, 121 {"xyz01234567890123456789012345678901"[:34], "01234567890123456789012345678901", -1}, 122 {"xxxxxx012345678901234567890123456789012345678901234567890123456789012", "012345678901234567890123456789012345678901234567890123456789012", 6}, 123 {"", "0123456789012345678901234567890123456789", -1}, 124 {"xx012345678901234567890123456789012345678901234567890123456789012", "0123456789012345678901234567890123456789", 2}, 125 {"xx012345678901234567890123456789012345678901234567890123456789012"[:41], "0123456789012345678901234567890123456789", -1}, 126 {"xx012345678901234567890123456789012345678901234567890123456789012", "0123456789012345678901234567890123456xxx", -1}, 127 {"xx0123456789012345678901234567890123456789012345678901234567890120123456789012345678901234567890123456xxx", "0123456789012345678901234567890123456xxx", 65}, 128 // test fallback to Rabin-Karp. 129 {"oxoxoxoxoxoxoxoxoxoxoxoy", "oy", 22}, 130 {"oxoxoxoxoxoxoxoxoxoxoxox", "oy", -1}, 131 } 132 133 var lastIndexTests = []IndexTest{ 134 {"", "", 0}, 135 {"", "a", -1}, 136 {"", "foo", -1}, 137 {"fo", "foo", -1}, 138 {"foo", "foo", 0}, 139 {"foo", "f", 0}, 140 {"oofofoofooo", "f", 7}, 141 {"oofofoofooo", "foo", 7}, 142 {"barfoobarfoo", "foo", 9}, 143 {"foo", "", 3}, 144 {"foo", "o", 2}, 145 {"abcABCabc", "A", 3}, 146 {"abcABCabc", "a", 6}, 147 } 148 149 var indexAnyTests = []IndexTest{ 150 {"", "", -1}, 151 {"", "a", -1}, 152 {"", "abc", -1}, 153 {"a", "", -1}, 154 {"a", "a", 0}, 155 {"aaa", "a", 0}, 156 {"abc", "xyz", -1}, 157 {"abc", "xcz", 2}, 158 {"abc", "xyz", 2}, 159 {"abcd", "cx", len("ab")}, 160 {"abcd", "uvwxyz", len("ab")}, 161 {"aRegExp*", ".(|)*+?^$[]", 7}, 162 {dots + dots + dots, " ", -1}, 163 {"012abcba210", "\xffb", 4}, 164 {"012\x80bcb\x80210", "\xffb", 3}, 165 } 166 167 var lastIndexAnyTests = []IndexTest{ 168 {"", "", -1}, 169 {"", "a", -1}, 170 {"", "abc", -1}, 171 {"a", "", -1}, 172 {"a", "a", 0}, 173 {"aaa", "a", 2}, 174 {"abc", "xyz", -1}, 175 {"abc", "ab", 1}, 176 {"abc", "xyz", 2}, 177 {"abcd", "cx", len("ab")}, 178 {"abcd", "uvwxyz", len("ab")}, 179 {"a.RegExp*", ".(|)*+?^$[]", 8}, 180 {dots + dots + dots, " ", -1}, 181 {"012abcba210", "\xffb", 6}, 182 {"012\x80bcb\x80210", "\xffb", 7}, 183 } 184 185 // Execute f on each test case. funcName should be the name of f; it's used 186 // in failure reports. 187 func runIndexTests(t *testing.T, f func(s, sep string) int, funcName string, testCases []IndexTest) { 188 for _, test := range testCases { 189 actual := f(test.s, test.sep) 190 if actual != test.out { 191 t.Errorf("%s(%q,%q) = %v; want %v", funcName, test.s, test.sep, actual, test.out) 192 } 193 } 194 } 195 196 func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) } 197 func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) } 198 func TestIndexAny(t *testing.T) { runIndexTests(t, IndexAny, "IndexAny", indexAnyTests) } 199 func TestLastIndexAny(t *testing.T) { runIndexTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests) } 200 201 func TestLastIndexByte(t *testing.T) { 202 testCases := []IndexTest{ 203 {"", "q", -1}, 204 {"abcdef", "q", -1}, 205 {"abcdefabcdef", "a", len("abcdef")}, // something in the middle 206 {"abcdefabcdef", "f", len("abcdefabcde")}, // last byte 207 {"zabcdefabcdef", "z", 0}, // first byte 208 {"abcd", "b", len("a")}, // non-ascii 209 } 210 for _, test := range testCases { 211 actual := LastIndexByte(test.s, test.sep[0]) 212 if actual != test.out { 213 t.Errorf("LastIndexByte(%q,%c) = %v; want %v", test.s, test.sep[0], actual, test.out) 214 } 215 } 216 } 217 218 func simpleIndex(s, sep string) int { 219 n := len(sep) 220 for i := n; i <= len(s); i++ { 221 if s[i-n:i] == sep { 222 return i - n 223 } 224 } 225 return -1 226 } 227 228 func TestIndexRandom(t *testing.T) { 229 const chars = "abcdefghijklmnopqrstuvwxyz0123456789" 230 for times := 0; times < 10; times++ { 231 for strLen := 5 + rand.Intn(5); strLen < 140; strLen += 10 { // Arbitrary 232 s1 := make([]byte, strLen) 233 for i := range s1 { 234 s1[i] = chars[rand.Intn(len(chars))] 235 } 236 s := string(s1) 237 for i := 0; i < 50; i++ { 238 begin := rand.Intn(len(s) + 1) 239 end := begin + rand.Intn(len(s)+1-begin) 240 sep := s[begin:end] 241 if i%4 == 0 { 242 pos := rand.Intn(len(sep) + 1) 243 sep = sep[:pos] + "A" + sep[pos:] 244 } 245 want := simpleIndex(s, sep) 246 res := Index(s, sep) 247 if res != want { 248 t.Errorf("Index(%s,%s) = %d; want %d", s, sep, res, want) 249 } 250 } 251 } 252 } 253 } 254 255 func TestIndexRune(t *testing.T) { 256 tests := []struct { 257 in string 258 rune rune 259 want int 260 }{ 261 {"", 'a', -1}, 262 {"", '', -1}, 263 {"foo", '', -1}, 264 {"foo", 'o', 1}, 265 {"foobar", '', 3}, 266 {"foobar", '', 9}, 267 {"a A x", 'A', 2}, 268 {"some_text=some_value", '=', 9}, 269 {"a", 'a', 3}, 270 {"ab", '', 4}, 271 272 // RuneError should match any invalid UTF-8 byte sequence. 273 {"", '', 0}, 274 {"\xff", '', 0}, 275 {"x", '', len("x")}, 276 {"x\xe2\x98", '', len("x")}, 277 {"x\xe2\x98", '', len("x")}, 278 {"x\xe2\x98x", '', len("x")}, 279 280 // Invalid rune values should never match. 281 {"abcd\xe2\x98\xff\xed\xa0\x80", -1, -1}, 282 {"abcd\xe2\x98\xff\xed\xa0\x80", 0xD800, -1}, // Surrogate pair 283 {"abcd\xe2\x98\xff\xed\xa0\x80", utf8.MaxRune + 1, -1}, 284 } 285 for _, tt := range tests { 286 if got := IndexRune(tt.in, tt.rune); got != tt.want { 287 t.Errorf("IndexRune(%q, %d) = %v; want %v", tt.in, tt.rune, got, tt.want) 288 } 289 } 290 291 haystack := "test" 292 allocs := testing.AllocsPerRun(1000, func() { 293 if i := IndexRune(haystack, 's'); i != 2 { 294 t.Fatalf("'s' at %d; want 2", i) 295 } 296 if i := IndexRune(haystack, ''); i != 4 { 297 t.Fatalf("'' at %d; want 4", i) 298 } 299 }) 300 if allocs != 0 && testing.CoverMode() == "" { 301 t.Errorf("expected no allocations, got %f", allocs) 302 } 303 } 304 305 const benchmarkString = "some_text=somevalue" 306 307 func BenchmarkIndexRune(b *testing.B) { 308 if got := IndexRune(benchmarkString, ''); got != 14 { 309 b.Fatalf("wrong index: expected 14, got=%d", got) 310 } 311 for i := 0; i < b.N; i++ { 312 IndexRune(benchmarkString, '') 313 } 314 } 315 316 var benchmarkLongString = Repeat(" ", 100) + benchmarkString 317 318 func BenchmarkIndexRuneLongString(b *testing.B) { 319 if got := IndexRune(benchmarkLongString, ''); got != 114 { 320 b.Fatalf("wrong index: expected 114, got=%d", got) 321 } 322 for i := 0; i < b.N; i++ { 323 IndexRune(benchmarkLongString, '') 324 } 325 } 326 327 func BenchmarkIndexRuneFastPath(b *testing.B) { 328 if got := IndexRune(benchmarkString, 'v'); got != 17 { 329 b.Fatalf("wrong index: expected 17, got=%d", got) 330 } 331 for i := 0; i < b.N; i++ { 332 IndexRune(benchmarkString, 'v') 333 } 334 } 335 336 func BenchmarkIndex(b *testing.B) { 337 if got := Index(benchmarkString, "v"); got != 17 { 338 b.Fatalf("wrong index: expected 17, got=%d", got) 339 } 340 for i := 0; i < b.N; i++ { 341 Index(benchmarkString, "v") 342 } 343 } 344 345 func BenchmarkLastIndex(b *testing.B) { 346 if got := Index(benchmarkString, "v"); got != 17 { 347 b.Fatalf("wrong index: expected 17, got=%d", got) 348 } 349 for i := 0; i < b.N; i++ { 350 LastIndex(benchmarkString, "v") 351 } 352 } 353 354 func BenchmarkIndexByte(b *testing.B) { 355 if got := IndexByte(benchmarkString, 'v'); got != 17 { 356 b.Fatalf("wrong index: expected 17, got=%d", got) 357 } 358 for i := 0; i < b.N; i++ { 359 IndexByte(benchmarkString, 'v') 360 } 361 } 362 363 type SplitTest struct { 364 s string 365 sep string 366 n int 367 a []string 368 } 369 370 var splittests = []SplitTest{ 371 {"", "", -1, []string{}}, 372 {abcd, "", 2, []string{"a", "bcd"}}, 373 {abcd, "", 4, []string{"a", "b", "c", "d"}}, 374 {abcd, "", -1, []string{"a", "b", "c", "d"}}, 375 {faces, "", -1, []string{"", "", ""}}, 376 {faces, "", 3, []string{"", "", ""}}, 377 {faces, "", 17, []string{"", "", ""}}, 378 {"", "", -1, []string{"", "", ""}}, 379 {abcd, "a", 0, nil}, 380 {abcd, "a", -1, []string{"", "bcd"}}, 381 {abcd, "z", -1, []string{"abcd"}}, 382 {commas, ",", -1, []string{"1", "2", "3", "4"}}, 383 {dots, "...", -1, []string{"1", ".2", ".3", ".4"}}, 384 {faces, "", -1, []string{"", ""}}, 385 {faces, "~", -1, []string{faces}}, 386 {"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}}, 387 {"1 2", " ", 3, []string{"1", "2"}}, 388 } 389 390 func TestSplit(t *testing.T) { 391 for _, tt := range splittests { 392 a := SplitN(tt.s, tt.sep, tt.n) 393 if !eq(a, tt.a) { 394 t.Errorf("Split(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, a, tt.a) 395 continue 396 } 397 if tt.n == 0 { 398 continue 399 } 400 s := Join(a, tt.sep) 401 if s != tt.s { 402 t.Errorf("Join(Split(%q, %q, %d), %q) = %q", tt.s, tt.sep, tt.n, tt.sep, s) 403 } 404 if tt.n < 0 { 405 b := Split(tt.s, tt.sep) 406 if !reflect.DeepEqual(a, b) { 407 t.Errorf("Split disagrees with SplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a) 408 } 409 } 410 } 411 } 412 413 var splitaftertests = []SplitTest{ 414 {abcd, "a", -1, []string{"a", "bcd"}}, 415 {abcd, "z", -1, []string{"abcd"}}, 416 {abcd, "", -1, []string{"a", "b", "c", "d"}}, 417 {commas, ",", -1, []string{"1,", "2,", "3,", "4"}}, 418 {dots, "...", -1, []string{"1...", ".2...", ".3...", ".4"}}, 419 {faces, "", -1, []string{"", ""}}, 420 {faces, "~", -1, []string{faces}}, 421 {faces, "", -1, []string{"", "", ""}}, 422 {"1 2 3 4", " ", 3, []string{"1 ", "2 ", "3 4"}}, 423 {"1 2 3", " ", 3, []string{"1 ", "2 ", "3"}}, 424 {"1 2", " ", 3, []string{"1 ", "2"}}, 425 {"123", "", 2, []string{"1", "23"}}, 426 {"123", "", 17, []string{"1", "2", "3"}}, 427 } 428 429 func TestSplitAfter(t *testing.T) { 430 for _, tt := range splitaftertests { 431 a := SplitAfterN(tt.s, tt.sep, tt.n) 432 if !eq(a, tt.a) { 433 t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, a, tt.a) 434 continue 435 } 436 s := Join(a, "") 437 if s != tt.s { 438 t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s) 439 } 440 if tt.n < 0 { 441 b := SplitAfter(tt.s, tt.sep) 442 if !reflect.DeepEqual(a, b) { 443 t.Errorf("SplitAfter disagrees with SplitAfterN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a) 444 } 445 } 446 } 447 } 448 449 type FieldsTest struct { 450 s string 451 a []string 452 } 453 454 var fieldstests = []FieldsTest{ 455 {"", []string{}}, 456 {" ", []string{}}, 457 {" \t ", []string{}}, 458 {"\u2000", []string{}}, 459 {" abc ", []string{"abc"}}, 460 {"1 2 3 4", []string{"1", "2", "3", "4"}}, 461 {"1 2 3 4", []string{"1", "2", "3", "4"}}, 462 {"1\t\t2\t\t3\t4", []string{"1", "2", "3", "4"}}, 463 {"1\u20002\u20013\u20024", []string{"1", "2", "3", "4"}}, 464 {"\u2000\u2001\u2002", []string{}}, 465 {"\n\t\n", []string{"", ""}}, 466 {"\n\u200012\u2000 \u2001 ", []string{"12", ""}}, 467 {"\n1\uFFFD \uFFFD2\u20003\uFFFD4", []string{"1\uFFFD", "\uFFFD2", "3\uFFFD4"}}, 468 {"1\xFF\u2000\xFF2\xFF \xFF", []string{"1\xFF", "\xFF2\xFF", "\xFF"}}, 469 {faces, []string{faces}}, 470 } 471 472 func TestFields(t *testing.T) { 473 for _, tt := range fieldstests { 474 a := Fields(tt.s) 475 if !eq(a, tt.a) { 476 t.Errorf("Fields(%q) = %v; want %v", tt.s, a, tt.a) 477 continue 478 } 479 } 480 } 481 482 var FieldsFuncTests = []FieldsTest{ 483 {"", []string{}}, 484 {"XX", []string{}}, 485 {"XXhiXXX", []string{"hi"}}, 486 {"aXXbXXXcX", []string{"a", "b", "c"}}, 487 } 488 489 func TestFieldsFunc(t *testing.T) { 490 for _, tt := range fieldstests { 491 a := FieldsFunc(tt.s, unicode.IsSpace) 492 if !eq(a, tt.a) { 493 t.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt.s, a, tt.a) 494 continue 495 } 496 } 497 pred := func(c rune) bool { return c == 'X' } 498 for _, tt := range FieldsFuncTests { 499 a := FieldsFunc(tt.s, pred) 500 if !eq(a, tt.a) { 501 t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a) 502 } 503 } 504 } 505 506 // Test case for any function which accepts and returns a single string. 507 type StringTest struct { 508 in, out string 509 } 510 511 // Execute f on each test case. funcName should be the name of f; it's used 512 // in failure reports. 513 func runStringTests(t *testing.T, f func(string) string, funcName string, testCases []StringTest) { 514 for _, tc := range testCases { 515 actual := f(tc.in) 516 if actual != tc.out { 517 t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out) 518 } 519 } 520 } 521 522 var upperTests = []StringTest{ 523 {"", ""}, 524 {"ONLYUPPER", "ONLYUPPER"}, 525 {"abc", "ABC"}, 526 {"AbC123", "ABC123"}, 527 {"azAZ09_", "AZAZ09_"}, 528 {"longStrinGwitHmixofsmaLLandcAps", "LONGSTRINGWITHMIXOFSMALLANDCAPS"}, 529 {"long\u0250string\u0250with\u0250nonascii\u2C6Fchars", "LONG\u2C6FSTRING\u2C6FWITH\u2C6FNONASCII\u2C6FCHARS"}, 530 {"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char 531 } 532 533 var lowerTests = []StringTest{ 534 {"", ""}, 535 {"abc", "abc"}, 536 {"AbC123", "abc123"}, 537 {"azAZ09_", "azaz09_"}, 538 {"longStrinGwitHmixofsmaLLandcAps", "longstringwithmixofsmallandcaps"}, 539 {"LONG\u2C6FSTRING\u2C6FWITH\u2C6FNONASCII\u2C6FCHARS", "long\u0250string\u0250with\u0250nonascii\u0250chars"}, 540 {"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char 541 } 542 543 const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000" 544 545 var trimSpaceTests = []StringTest{ 546 {"", ""}, 547 {"abc", "abc"}, 548 {space + "abc" + space, "abc"}, 549 {" ", ""}, 550 {" \t\r\n \t\t\r\r\n\n ", ""}, 551 {" \t\r\n x\t\t\r\r\n\n ", "x"}, 552 {" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"}, 553 {"1 \t\r\n2", "1 \t\r\n2"}, 554 {" x\x80", "x\x80"}, 555 {" x\xc0", "x\xc0"}, 556 {"x \xc0\xc0 ", "x \xc0\xc0"}, 557 {"x \xc0", "x \xc0"}, 558 {"x \xc0 ", "x \xc0"}, 559 {"x \xc0\xc0 ", "x \xc0\xc0"}, 560 {"x \xc0\xc0 ", "x \xc0\xc0"}, 561 {"x ", "x "}, 562 } 563 564 func tenRunes(ch rune) string { 565 r := make([]rune, 10) 566 for i := range r { 567 r[i] = ch 568 } 569 return string(r) 570 } 571 572 // User-defined self-inverse mapping function 573 func rot13(r rune) rune { 574 step := rune(13) 575 if r >= 'a' && r <= 'z' { 576 return ((r - 'a' + step) % 26) + 'a' 577 } 578 if r >= 'A' && r <= 'Z' { 579 return ((r - 'A' + step) % 26) + 'A' 580 } 581 return r 582 } 583 584 func TestMap(t *testing.T) { 585 // Run a couple of awful growth/shrinkage tests 586 a := tenRunes('a') 587 // 1. Grow. This triggers two reallocations in Map. 588 maxRune := func(rune) rune { return unicode.MaxRune } 589 m := Map(maxRune, a) 590 expect := tenRunes(unicode.MaxRune) 591 if m != expect { 592 t.Errorf("growing: expected %q got %q", expect, m) 593 } 594 595 // 2. Shrink 596 minRune := func(rune) rune { return 'a' } 597 m = Map(minRune, tenRunes(unicode.MaxRune)) 598 expect = a 599 if m != expect { 600 t.Errorf("shrinking: expected %q got %q", expect, m) 601 } 602 603 // 3. Rot13 604 m = Map(rot13, "a to zed") 605 expect = "n gb mrq" 606 if m != expect { 607 t.Errorf("rot13: expected %q got %q", expect, m) 608 } 609 610 // 4. Rot13^2 611 m = Map(rot13, Map(rot13, "a to zed")) 612 expect = "a to zed" 613 if m != expect { 614 t.Errorf("rot13: expected %q got %q", expect, m) 615 } 616 617 // 5. Drop 618 dropNotLatin := func(r rune) rune { 619 if unicode.Is(unicode.Latin, r) { 620 return r 621 } 622 return -1 623 } 624 m = Map(dropNotLatin, "Hello, ") 625 expect = "Hello" 626 if m != expect { 627 t.Errorf("drop: expected %q got %q", expect, m) 628 } 629 630 // 6. Identity 631 identity := func(r rune) rune { 632 return r 633 } 634 orig := "Input string that we expect not to be copied." 635 m = Map(identity, orig) 636 if (*reflect.StringHeader)(unsafe.Pointer(&orig)).Data != 637 (*reflect.StringHeader)(unsafe.Pointer(&m)).Data { 638 t.Error("unexpected copy during identity map") 639 } 640 641 // 7. Handle invalid UTF-8 sequence 642 replaceNotLatin := func(r rune) rune { 643 if unicode.Is(unicode.Latin, r) { 644 return r 645 } 646 return '?' 647 } 648 m = Map(replaceNotLatin, "Hello\255World") 649 expect = "Hello?World" 650 if m != expect { 651 t.Errorf("replace invalid sequence: expected %q got %q", expect, m) 652 } 653 } 654 655 func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) } 656 657 func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) } 658 659 func BenchmarkToUpper(b *testing.B) { 660 for _, tc := range upperTests { 661 b.Run(tc.in, func(b *testing.B) { 662 for i := 0; i < b.N; i++ { 663 actual := ToUpper(tc.in) 664 if actual != tc.out { 665 b.Errorf("ToUpper(%q) = %q; want %q", tc.in, actual, tc.out) 666 } 667 } 668 }) 669 } 670 } 671 672 func BenchmarkToLower(b *testing.B) { 673 for _, tc := range lowerTests { 674 b.Run(tc.in, func(b *testing.B) { 675 for i := 0; i < b.N; i++ { 676 actual := ToLower(tc.in) 677 if actual != tc.out { 678 b.Errorf("ToLower(%q) = %q; want %q", tc.in, actual, tc.out) 679 } 680 } 681 }) 682 } 683 } 684 685 func BenchmarkMapNoChanges(b *testing.B) { 686 identity := func(r rune) rune { 687 return r 688 } 689 for i := 0; i < b.N; i++ { 690 Map(identity, "Some string that won't be modified.") 691 } 692 } 693 694 func TestSpecialCase(t *testing.T) { 695 lower := "abcdefghijklmnoprstuvyz" 696 upper := "ABCDEFGHIJKLMNOPRSTUVYZ" 697 u := ToUpperSpecial(unicode.TurkishCase, upper) 698 if u != upper { 699 t.Errorf("Upper(upper) is %s not %s", u, upper) 700 } 701 u = ToUpperSpecial(unicode.TurkishCase, lower) 702 if u != upper { 703 t.Errorf("Upper(lower) is %s not %s", u, upper) 704 } 705 l := ToLowerSpecial(unicode.TurkishCase, lower) 706 if l != lower { 707 t.Errorf("Lower(lower) is %s not %s", l, lower) 708 } 709 l = ToLowerSpecial(unicode.TurkishCase, upper) 710 if l != lower { 711 t.Errorf("Lower(upper) is %s not %s", l, lower) 712 } 713 } 714 715 func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) } 716 717 var trimTests = []struct { 718 f string 719 in, arg, out string 720 }{ 721 {"Trim", "abba", "a", "bb"}, 722 {"Trim", "abba", "ab", ""}, 723 {"TrimLeft", "abba", "ab", ""}, 724 {"TrimRight", "abba", "ab", ""}, 725 {"TrimLeft", "abba", "a", "bba"}, 726 {"TrimRight", "abba", "a", "abb"}, 727 {"Trim", "<tag>", "<>", "tag"}, 728 {"Trim", "* listitem", " *", "listitem"}, 729 {"Trim", `"quote"`, `"`, "quote"}, 730 {"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"}, 731 {"Trim", "\x80test\xff", "\xff", "test"}, 732 {"Trim", " ", " ", ""}, 733 {"Trim", " 0", "0 ", ""}, 734 //empty string tests 735 {"Trim", "abba", "", "abba"}, 736 {"Trim", "", "123", ""}, 737 {"Trim", "", "", ""}, 738 {"TrimLeft", "abba", "", "abba"}, 739 {"TrimLeft", "", "123", ""}, 740 {"TrimLeft", "", "", ""}, 741 {"TrimRight", "abba", "", "abba"}, 742 {"TrimRight", "", "123", ""}, 743 {"TrimRight", "", "", ""}, 744 {"TrimRight", "\xc0", "", "\xc0"}, 745 {"TrimPrefix", "aabb", "a", "abb"}, 746 {"TrimPrefix", "aabb", "b", "aabb"}, 747 {"TrimSuffix", "aabb", "a", "aabb"}, 748 {"TrimSuffix", "aabb", "b", "aab"}, 749 } 750 751 func TestTrim(t *testing.T) { 752 for _, tc := range trimTests { 753 name := tc.f 754 var f func(string, string) string 755 switch name { 756 case "Trim": 757 f = Trim 758 case "TrimLeft": 759 f = TrimLeft 760 case "TrimRight": 761 f = TrimRight 762 case "TrimPrefix": 763 f = TrimPrefix 764 case "TrimSuffix": 765 f = TrimSuffix 766 default: 767 t.Errorf("Undefined trim function %s", name) 768 } 769 actual := f(tc.in, tc.arg) 770 if actual != tc.out { 771 t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out) 772 } 773 } 774 } 775 776 func BenchmarkTrim(b *testing.B) { 777 b.ReportAllocs() 778 779 for i := 0; i < b.N; i++ { 780 for _, tc := range trimTests { 781 name := tc.f 782 var f func(string, string) string 783 switch name { 784 case "Trim": 785 f = Trim 786 case "TrimLeft": 787 f = TrimLeft 788 case "TrimRight": 789 f = TrimRight 790 case "TrimPrefix": 791 f = TrimPrefix 792 case "TrimSuffix": 793 f = TrimSuffix 794 default: 795 b.Errorf("Undefined trim function %s", name) 796 } 797 actual := f(tc.in, tc.arg) 798 if actual != tc.out { 799 b.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out) 800 } 801 } 802 } 803 } 804 805 type predicate struct { 806 f func(rune) bool 807 name string 808 } 809 810 var isSpace = predicate{unicode.IsSpace, "IsSpace"} 811 var isDigit = predicate{unicode.IsDigit, "IsDigit"} 812 var isUpper = predicate{unicode.IsUpper, "IsUpper"} 813 var isValidRune = predicate{ 814 func(r rune) bool { 815 return r != utf8.RuneError 816 }, 817 "IsValidRune", 818 } 819 820 func not(p predicate) predicate { 821 return predicate{ 822 func(r rune) bool { 823 return !p.f(r) 824 }, 825 "not " + p.name, 826 } 827 } 828 829 var trimFuncTests = []struct { 830 f predicate 831 in, out string 832 }{ 833 {isSpace, space + " hello " + space, "hello"}, 834 {isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"}, 835 {isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"}, 836 {not(isSpace), "hello" + space + "hello", space}, 837 {not(isDigit), "hello\u0e50\u0e521234\u0e50\u0e51helo", "\u0e50\u0e521234\u0e50\u0e51"}, 838 {isValidRune, "ab\xc0a\xc0cd", "\xc0a\xc0"}, 839 {not(isValidRune), "\xc0a\xc0", "a"}, 840 } 841 842 func TestTrimFunc(t *testing.T) { 843 for _, tc := range trimFuncTests { 844 actual := TrimFunc(tc.in, tc.f.f) 845 if actual != tc.out { 846 t.Errorf("TrimFunc(%q, %q) = %q; want %q", tc.in, tc.f.name, actual, tc.out) 847 } 848 } 849 } 850 851 var indexFuncTests = []struct { 852 in string 853 f predicate 854 first, last int 855 }{ 856 {"", isValidRune, -1, -1}, 857 {"abc", isDigit, -1, -1}, 858 {"0123", isDigit, 0, 3}, 859 {"a1b", isDigit, 1, 1}, 860 {space, isSpace, 0, len(space) - 3}, // last rune in space is 3 bytes 861 {"\u0e50\u0e5212hello34\u0e50\u0e51", isDigit, 0, 18}, 862 {"\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", isUpper, 0, 34}, 863 {"12\u0e50\u0e52hello34\u0e50\u0e51", not(isDigit), 8, 12}, 864 865 // tests of invalid UTF-8 866 {"\x801", isDigit, 1, 1}, 867 {"\x80abc", isDigit, -1, -1}, 868 {"\xc0a\xc0", isValidRune, 1, 1}, 869 {"\xc0a\xc0", not(isValidRune), 0, 2}, 870 {"\xc0\xc0", not(isValidRune), 0, 4}, 871 {"\xc0\xc0\xc0", not(isValidRune), 0, 5}, 872 {"ab\xc0a\xc0cd", not(isValidRune), 2, 4}, 873 {"a\xe0\x80cd", not(isValidRune), 1, 2}, 874 {"\x80\x80\x80\x80", not(isValidRune), 0, 3}, 875 } 876 877 func TestIndexFunc(t *testing.T) { 878 for _, tc := range indexFuncTests { 879 first := IndexFunc(tc.in, tc.f.f) 880 if first != tc.first { 881 t.Errorf("IndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, first, tc.first) 882 } 883 last := LastIndexFunc(tc.in, tc.f.f) 884 if last != tc.last { 885 t.Errorf("LastIndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, last, tc.last) 886 } 887 } 888 } 889 890 func equal(m string, s1, s2 string, t *testing.T) bool { 891 if s1 == s2 { 892 return true 893 } 894 e1 := Split(s1, "") 895 e2 := Split(s2, "") 896 for i, c1 := range e1 { 897 if i >= len(e2) { 898 break 899 } 900 r1, _ := utf8.DecodeRuneInString(c1) 901 r2, _ := utf8.DecodeRuneInString(e2[i]) 902 if r1 != r2 { 903 t.Errorf("%s diff at %d: U+%04X U+%04X", m, i, r1, r2) 904 } 905 } 906 return false 907 } 908 909 func TestCaseConsistency(t *testing.T) { 910 // Make a string of all the runes. 911 numRunes := int(unicode.MaxRune + 1) 912 if testing.Short() { 913 numRunes = 1000 914 } 915 a := make([]rune, numRunes) 916 for i := range a { 917 a[i] = rune(i) 918 } 919 s := string(a) 920 // convert the cases. 921 upper := ToUpper(s) 922 lower := ToLower(s) 923 924 // Consistency checks 925 if n := utf8.RuneCountInString(upper); n != numRunes { 926 t.Error("rune count wrong in upper:", n) 927 } 928 if n := utf8.RuneCountInString(lower); n != numRunes { 929 t.Error("rune count wrong in lower:", n) 930 } 931 if !equal("ToUpper(upper)", ToUpper(upper), upper, t) { 932 t.Error("ToUpper(upper) consistency fail") 933 } 934 if !equal("ToLower(lower)", ToLower(lower), lower, t) { 935 t.Error("ToLower(lower) consistency fail") 936 } 937 /* 938 These fail because of non-one-to-oneness of the data, such as multiple 939 upper case 'I' mapping to 'i'. We comment them out but keep them for 940 interest. 941 For instance: CAPITAL LETTER I WITH DOT ABOVE: 942 unicode.ToUpper(unicode.ToLower('\u0130')) != '\u0130' 943 944 if !equal("ToUpper(lower)", ToUpper(lower), upper, t) { 945 t.Error("ToUpper(lower) consistency fail"); 946 } 947 if !equal("ToLower(upper)", ToLower(upper), lower, t) { 948 t.Error("ToLower(upper) consistency fail"); 949 } 950 */ 951 } 952 953 var RepeatTests = []struct { 954 in, out string 955 count int 956 }{ 957 {"", "", 0}, 958 {"", "", 1}, 959 {"", "", 2}, 960 {"-", "", 0}, 961 {"-", "-", 1}, 962 {"-", "----------", 10}, 963 {"abc ", "abc abc abc ", 3}, 964 } 965 966 func TestRepeat(t *testing.T) { 967 for _, tt := range RepeatTests { 968 a := Repeat(tt.in, tt.count) 969 if !equal("Repeat(s)", a, tt.out, t) { 970 t.Errorf("Repeat(%v, %d) = %v; want %v", tt.in, tt.count, a, tt.out) 971 continue 972 } 973 } 974 } 975 976 func repeat(s string, count int) (err error) { 977 defer func() { 978 if r := recover(); r != nil { 979 switch v := r.(type) { 980 case error: 981 err = v 982 default: 983 err = fmt.Errorf("%s", v) 984 } 985 } 986 }() 987 988 Repeat(s, count) 989 990 return 991 } 992 993 // See Issue golang.org/issue/16237 994 func TestRepeatCatchesOverflow(t *testing.T) { 995 tests := [...]struct { 996 s string 997 count int 998 errStr string 999 }{ 1000 0: {"--", -2147483647, "negative"}, 1001 1: {"", int(^uint(0) >> 1), ""}, 1002 2: {"-", 10, ""}, 1003 3: {"gopher", 0, ""}, 1004 4: {"-", -1, "negative"}, 1005 5: {"--", -102, "negative"}, 1006 6: {string(make([]byte, 255)), int((^uint(0))/255 + 1), "overflow"}, 1007 } 1008 1009 for i, tt := range tests { 1010 err := repeat(tt.s, tt.count) 1011 if tt.errStr == "" { 1012 if err != nil { 1013 t.Errorf("#%d panicked %v", i, err) 1014 } 1015 continue 1016 } 1017 1018 if err == nil || !Contains(err.Error(), tt.errStr) { 1019 t.Errorf("#%d expected %q got %q", i, tt.errStr, err) 1020 } 1021 } 1022 } 1023 1024 func runesEqual(a, b []rune) bool { 1025 if len(a) != len(b) { 1026 return false 1027 } 1028 for i, r := range a { 1029 if r != b[i] { 1030 return false 1031 } 1032 } 1033 return true 1034 } 1035 1036 var RunesTests = []struct { 1037 in string 1038 out []rune 1039 lossy bool 1040 }{ 1041 {"", []rune{}, false}, 1042 {" ", []rune{32}, false}, 1043 {"ABC", []rune{65, 66, 67}, false}, 1044 {"abc", []rune{97, 98, 99}, false}, 1045 {"\u65e5\u672c\u8a9e", []rune{26085, 26412, 35486}, false}, 1046 {"ab\x80c", []rune{97, 98, 0xFFFD, 99}, true}, 1047 {"ab\xc0c", []rune{97, 98, 0xFFFD, 99}, true}, 1048 } 1049 1050 func TestRunes(t *testing.T) { 1051 for _, tt := range RunesTests { 1052 a := []rune(tt.in) 1053 if !runesEqual(a, tt.out) { 1054 t.Errorf("[]rune(%q) = %v; want %v", tt.in, a, tt.out) 1055 continue 1056 } 1057 if !tt.lossy { 1058 // can only test reassembly if we didn't lose information 1059 s := string(a) 1060 if s != tt.in { 1061 t.Errorf("string([]rune(%q)) = %x; want %x", tt.in, s, tt.in) 1062 } 1063 } 1064 } 1065 } 1066 1067 func TestReadByte(t *testing.T) { 1068 testStrings := []string{"", abcd, faces, commas} 1069 for _, s := range testStrings { 1070 reader := NewReader(s) 1071 if e := reader.UnreadByte(); e == nil { 1072 t.Errorf("Unreading %q at beginning: expected error", s) 1073 } 1074 var res bytes.Buffer 1075 for { 1076 b, e := reader.ReadByte() 1077 if e == io.EOF { 1078 break 1079 } 1080 if e != nil { 1081 t.Errorf("Reading %q: %s", s, e) 1082 break 1083 } 1084 res.WriteByte(b) 1085 // unread and read again 1086 e = reader.UnreadByte() 1087 if e != nil { 1088 t.Errorf("Unreading %q: %s", s, e) 1089 break 1090 } 1091 b1, e := reader.ReadByte() 1092 if e != nil { 1093 t.Errorf("Reading %q after unreading: %s", s, e) 1094 break 1095 } 1096 if b1 != b { 1097 t.Errorf("Reading %q after unreading: want byte %q, got %q", s, b, b1) 1098 break 1099 } 1100 } 1101 if res.String() != s { 1102 t.Errorf("Reader(%q).ReadByte() produced %q", s, res.String()) 1103 } 1104 } 1105 } 1106 1107 func TestReadRune(t *testing.T) { 1108 testStrings := []string{"", abcd, faces, commas} 1109 for _, s := range testStrings { 1110 reader := NewReader(s) 1111 if e := reader.UnreadRune(); e == nil { 1112 t.Errorf("Unreading %q at beginning: expected error", s) 1113 } 1114 res := "" 1115 for { 1116 r, z, e := reader.ReadRune() 1117 if e == io.EOF { 1118 break 1119 } 1120 if e != nil { 1121 t.Errorf("Reading %q: %s", s, e) 1122 break 1123 } 1124 res += string(r) 1125 // unread and read again 1126 e = reader.UnreadRune() 1127 if e != nil { 1128 t.Errorf("Unreading %q: %s", s, e) 1129 break 1130 } 1131 r1, z1, e := reader.ReadRune() 1132 if e != nil { 1133 t.Errorf("Reading %q after unreading: %s", s, e) 1134 break 1135 } 1136 if r1 != r { 1137 t.Errorf("Reading %q after unreading: want rune %q, got %q", s, r, r1) 1138 break 1139 } 1140 if z1 != z { 1141 t.Errorf("Reading %q after unreading: want size %d, got %d", s, z, z1) 1142 break 1143 } 1144 } 1145 if res != s { 1146 t.Errorf("Reader(%q).ReadRune() produced %q", s, res) 1147 } 1148 } 1149 } 1150 1151 var UnreadRuneErrorTests = []struct { 1152 name string 1153 f func(*Reader) 1154 }{ 1155 {"Read", func(r *Reader) { r.Read([]byte{0}) }}, 1156 {"ReadByte", func(r *Reader) { r.ReadByte() }}, 1157 {"UnreadRune", func(r *Reader) { r.UnreadRune() }}, 1158 {"Seek", func(r *Reader) { r.Seek(0, io.SeekCurrent) }}, 1159 {"WriteTo", func(r *Reader) { r.WriteTo(&bytes.Buffer{}) }}, 1160 } 1161 1162 func TestUnreadRuneError(t *testing.T) { 1163 for _, tt := range UnreadRuneErrorTests { 1164 reader := NewReader("0123456789") 1165 if _, _, err := reader.ReadRune(); err != nil { 1166 // should not happen 1167 t.Fatal(err) 1168 } 1169 tt.f(reader) 1170 err := reader.UnreadRune() 1171 if err == nil { 1172 t.Errorf("Unreading after %s: expected error", tt.name) 1173 } 1174 } 1175 } 1176 1177 var ReplaceTests = []struct { 1178 in string 1179 old, new string 1180 n int 1181 out string 1182 }{ 1183 {"hello", "l", "L", 0, "hello"}, 1184 {"hello", "l", "L", -1, "heLLo"}, 1185 {"hello", "x", "X", -1, "hello"}, 1186 {"", "x", "X", -1, ""}, 1187 {"radar", "r", "<r>", -1, "<r>ada<r>"}, 1188 {"", "", "<>", -1, "<>"}, 1189 {"banana", "a", "<>", -1, "b<>n<>n<>"}, 1190 {"banana", "a", "<>", 1, "b<>nana"}, 1191 {"banana", "a", "<>", 1000, "b<>n<>n<>"}, 1192 {"banana", "an", "<>", -1, "b<><>a"}, 1193 {"banana", "ana", "<>", -1, "b<>na"}, 1194 {"banana", "", "<>", -1, "<>b<>a<>n<>a<>n<>a<>"}, 1195 {"banana", "", "<>", 10, "<>b<>a<>n<>a<>n<>a<>"}, 1196 {"banana", "", "<>", 6, "<>b<>a<>n<>a<>n<>a"}, 1197 {"banana", "", "<>", 5, "<>b<>a<>n<>a<>na"}, 1198 {"banana", "", "<>", 1, "<>banana"}, 1199 {"banana", "a", "a", -1, "banana"}, 1200 {"banana", "a", "a", 1, "banana"}, 1201 {"", "", "<>", -1, "<><><><>"}, 1202 } 1203 1204 func TestReplace(t *testing.T) { 1205 for _, tt := range ReplaceTests { 1206 if s := Replace(tt.in, tt.old, tt.new, tt.n); s != tt.out { 1207 t.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt.in, tt.old, tt.new, tt.n, s, tt.out) 1208 } 1209 } 1210 } 1211 1212 var TitleTests = []struct { 1213 in, out string 1214 }{ 1215 {"", ""}, 1216 {"a", "A"}, 1217 {" aaa aaa aaa ", " Aaa Aaa Aaa "}, 1218 {" Aaa Aaa Aaa ", " Aaa Aaa Aaa "}, 1219 {"123a456", "123a456"}, 1220 {"double-blind", "Double-Blind"}, 1221 {"", ""}, 1222 {"with_underscore", "With_underscore"}, 1223 {"unicode \xe2\x80\xa8 line separator", "Unicode \xe2\x80\xa8 Line Separator"}, 1224 } 1225 1226 func TestTitle(t *testing.T) { 1227 for _, tt := range TitleTests { 1228 if s := Title(tt.in); s != tt.out { 1229 t.Errorf("Title(%q) = %q, want %q", tt.in, s, tt.out) 1230 } 1231 } 1232 } 1233 1234 var ContainsTests = []struct { 1235 str, substr string 1236 expected bool 1237 }{ 1238 {"abc", "bc", true}, 1239 {"abc", "bcd", false}, 1240 {"abc", "", true}, 1241 {"", "a", false}, 1242 1243 // cases to cover code in runtime/asm_amd64.s:indexShortStr 1244 // 2-byte needle 1245 {"xxxxxx", "01", false}, 1246 {"01xxxx", "01", true}, 1247 {"xx01xx", "01", true}, 1248 {"xxxx01", "01", true}, 1249 {"01xxxxx"[1:], "01", false}, 1250 {"xxxxx01"[:6], "01", false}, 1251 // 3-byte needle 1252 {"xxxxxxx", "012", false}, 1253 {"012xxxx", "012", true}, 1254 {"xx012xx", "012", true}, 1255 {"xxxx012", "012", true}, 1256 {"012xxxxx"[1:], "012", false}, 1257 {"xxxxx012"[:7], "012", false}, 1258 // 4-byte needle 1259 {"xxxxxxxx", "0123", false}, 1260 {"0123xxxx", "0123", true}, 1261 {"xx0123xx", "0123", true}, 1262 {"xxxx0123", "0123", true}, 1263 {"0123xxxxx"[1:], "0123", false}, 1264 {"xxxxx0123"[:8], "0123", false}, 1265 // 5-7-byte needle 1266 {"xxxxxxxxx", "01234", false}, 1267 {"01234xxxx", "01234", true}, 1268 {"xx01234xx", "01234", true}, 1269 {"xxxx01234", "01234", true}, 1270 {"01234xxxxx"[1:], "01234", false}, 1271 {"xxxxx01234"[:9], "01234", false}, 1272 // 8-byte needle 1273 {"xxxxxxxxxxxx", "01234567", false}, 1274 {"01234567xxxx", "01234567", true}, 1275 {"xx01234567xx", "01234567", true}, 1276 {"xxxx01234567", "01234567", true}, 1277 {"01234567xxxxx"[1:], "01234567", false}, 1278 {"xxxxx01234567"[:12], "01234567", false}, 1279 // 9-15-byte needle 1280 {"xxxxxxxxxxxxx", "012345678", false}, 1281 {"012345678xxxx", "012345678", true}, 1282 {"xx012345678xx", "012345678", true}, 1283 {"xxxx012345678", "012345678", true}, 1284 {"012345678xxxxx"[1:], "012345678", false}, 1285 {"xxxxx012345678"[:13], "012345678", false}, 1286 // 16-byte needle 1287 {"xxxxxxxxxxxxxxxxxxxx", "0123456789ABCDEF", false}, 1288 {"0123456789ABCDEFxxxx", "0123456789ABCDEF", true}, 1289 {"xx0123456789ABCDEFxx", "0123456789ABCDEF", true}, 1290 {"xxxx0123456789ABCDEF", "0123456789ABCDEF", true}, 1291 {"0123456789ABCDEFxxxxx"[1:], "0123456789ABCDEF", false}, 1292 {"xxxxx0123456789ABCDEF"[:20], "0123456789ABCDEF", false}, 1293 // 17-31-byte needle 1294 {"xxxxxxxxxxxxxxxxxxxxx", "0123456789ABCDEFG", false}, 1295 {"0123456789ABCDEFGxxxx", "0123456789ABCDEFG", true}, 1296 {"xx0123456789ABCDEFGxx", "0123456789ABCDEFG", true}, 1297 {"xxxx0123456789ABCDEFG", "0123456789ABCDEFG", true}, 1298 {"0123456789ABCDEFGxxxxx"[1:], "0123456789ABCDEFG", false}, 1299 {"xxxxx0123456789ABCDEFG"[:21], "0123456789ABCDEFG", false}, 1300 1301 // partial match cases 1302 {"xx01x", "012", false}, // 3 1303 {"xx0123x", "01234", false}, // 5-7 1304 {"xx01234567x", "012345678", false}, // 9-15 1305 {"xx0123456789ABCDEFx", "0123456789ABCDEFG", false}, // 17-31, issue 15679 1306 } 1307 1308 func TestContains(t *testing.T) { 1309 for _, ct := range ContainsTests { 1310 if Contains(ct.str, ct.substr) != ct.expected { 1311 t.Errorf("Contains(%s, %s) = %v, want %v", 1312 ct.str, ct.substr, !ct.expected, ct.expected) 1313 } 1314 } 1315 } 1316 1317 var ContainsAnyTests = []struct { 1318 str, substr string 1319 expected bool 1320 }{ 1321 {"", "", false}, 1322 {"", "a", false}, 1323 {"", "abc", false}, 1324 {"a", "", false}, 1325 {"a", "a", true}, 1326 {"aaa", "a", true}, 1327 {"abc", "xyz", false}, 1328 {"abc", "xcz", true}, 1329 {"abcd", "uvwxyz", true}, 1330 {"aRegExp*", ".(|)*+?^$[]", true}, 1331 {dots + dots + dots, " ", false}, 1332 } 1333 1334 func TestContainsAny(t *testing.T) { 1335 for _, ct := range ContainsAnyTests { 1336 if ContainsAny(ct.str, ct.substr) != ct.expected { 1337 t.Errorf("ContainsAny(%s, %s) = %v, want %v", 1338 ct.str, ct.substr, !ct.expected, ct.expected) 1339 } 1340 } 1341 } 1342 1343 var ContainsRuneTests = []struct { 1344 str string 1345 r rune 1346 expected bool 1347 }{ 1348 {"", 'a', false}, 1349 {"a", 'a', true}, 1350 {"aaa", 'a', true}, 1351 {"abc", 'y', false}, 1352 {"abc", 'c', true}, 1353 {"abcd", 'x', false}, 1354 {"abcd", '', true}, 1355 {"aRegExp*", '*', true}, 1356 } 1357 1358 func TestContainsRune(t *testing.T) { 1359 for _, ct := range ContainsRuneTests { 1360 if ContainsRune(ct.str, ct.r) != ct.expected { 1361 t.Errorf("ContainsRune(%q, %q) = %v, want %v", 1362 ct.str, ct.r, !ct.expected, ct.expected) 1363 } 1364 } 1365 } 1366 1367 var EqualFoldTests = []struct { 1368 s, t string 1369 out bool 1370 }{ 1371 {"abc", "abc", true}, 1372 {"ABcd", "ABcd", true}, 1373 {"123abc", "123ABC", true}, 1374 {"", "", true}, 1375 {"abc", "xyz", false}, 1376 {"abc", "XYZ", false}, 1377 {"abcdefghijk", "abcdefghijX", false}, 1378 {"abcdefghijk", "abcdefghij\u212A", true}, 1379 {"abcdefghijK", "abcdefghij\u212A", true}, 1380 {"abcdefghijkz", "abcdefghij\u212Ay", false}, 1381 {"abcdefghijKz", "abcdefghij\u212Ay", false}, 1382 } 1383 1384 func TestEqualFold(t *testing.T) { 1385 for _, tt := range EqualFoldTests { 1386 if out := EqualFold(tt.s, tt.t); out != tt.out { 1387 t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.s, tt.t, out, tt.out) 1388 } 1389 if out := EqualFold(tt.t, tt.s); out != tt.out { 1390 t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.t, tt.s, out, tt.out) 1391 } 1392 } 1393 } 1394 1395 var CountTests = []struct { 1396 s, sep string 1397 num int 1398 }{ 1399 {"", "", 1}, 1400 {"", "notempty", 0}, 1401 {"notempty", "", 9}, 1402 {"smaller", "not smaller", 0}, 1403 {"12345678987654321", "6", 2}, 1404 {"611161116", "6", 3}, 1405 {"notequal", "NotEqual", 0}, 1406 {"equal", "equal", 1}, 1407 {"abc1231231123q", "123", 3}, 1408 {"11111", "11", 2}, 1409 } 1410 1411 func TestCount(t *testing.T) { 1412 for _, tt := range CountTests { 1413 if num := Count(tt.s, tt.sep); num != tt.num { 1414 t.Errorf("Count(\"%s\", \"%s\") = %d, want %d", tt.s, tt.sep, num, tt.num) 1415 } 1416 } 1417 } 1418 1419 func makeBenchInputHard() string { 1420 tokens := [...]string{ 1421 "<a>", "<p>", "<b>", "<strong>", 1422 "</a>", "</p>", "</b>", "</strong>", 1423 "hello", "world", 1424 } 1425 x := make([]byte, 0, 1<<20) 1426 for { 1427 i := rand.Intn(len(tokens)) 1428 if len(x)+len(tokens[i]) >= 1<<20 { 1429 break 1430 } 1431 x = append(x, tokens[i]...) 1432 } 1433 return string(x) 1434 } 1435 1436 var benchInputHard = makeBenchInputHard() 1437 1438 func benchmarkIndexHard(b *testing.B, sep string) { 1439 for i := 0; i < b.N; i++ { 1440 Index(benchInputHard, sep) 1441 } 1442 } 1443 1444 func benchmarkLastIndexHard(b *testing.B, sep string) { 1445 for i := 0; i < b.N; i++ { 1446 LastIndex(benchInputHard, sep) 1447 } 1448 } 1449 1450 func benchmarkCountHard(b *testing.B, sep string) { 1451 for i := 0; i < b.N; i++ { 1452 Count(benchInputHard, sep) 1453 } 1454 } 1455 1456 func BenchmarkIndexHard1(b *testing.B) { benchmarkIndexHard(b, "<>") } 1457 func BenchmarkIndexHard2(b *testing.B) { benchmarkIndexHard(b, "</pre>") } 1458 func BenchmarkIndexHard3(b *testing.B) { benchmarkIndexHard(b, "<b>hello world</b>") } 1459 func BenchmarkIndexHard4(b *testing.B) { 1460 benchmarkIndexHard(b, "<pre><b>hello</b><strong>world</strong></pre>") 1461 } 1462 1463 func BenchmarkLastIndexHard1(b *testing.B) { benchmarkLastIndexHard(b, "<>") } 1464 func BenchmarkLastIndexHard2(b *testing.B) { benchmarkLastIndexHard(b, "</pre>") } 1465 func BenchmarkLastIndexHard3(b *testing.B) { benchmarkLastIndexHard(b, "<b>hello world</b>") } 1466 1467 func BenchmarkCountHard1(b *testing.B) { benchmarkCountHard(b, "<>") } 1468 func BenchmarkCountHard2(b *testing.B) { benchmarkCountHard(b, "</pre>") } 1469 func BenchmarkCountHard3(b *testing.B) { benchmarkCountHard(b, "<b>hello world</b>") } 1470 1471 var benchInputTorture = Repeat("ABC", 1<<10) + "123" + Repeat("ABC", 1<<10) 1472 var benchNeedleTorture = Repeat("ABC", 1<<10+1) 1473 1474 func BenchmarkIndexTorture(b *testing.B) { 1475 for i := 0; i < b.N; i++ { 1476 Index(benchInputTorture, benchNeedleTorture) 1477 } 1478 } 1479 1480 func BenchmarkCountTorture(b *testing.B) { 1481 for i := 0; i < b.N; i++ { 1482 Count(benchInputTorture, benchNeedleTorture) 1483 } 1484 } 1485 1486 func BenchmarkCountTortureOverlapping(b *testing.B) { 1487 A := Repeat("ABC", 1<<20) 1488 B := Repeat("ABC", 1<<10) 1489 for i := 0; i < b.N; i++ { 1490 Count(A, B) 1491 } 1492 } 1493 1494 func BenchmarkCountByte(b *testing.B) { 1495 indexSizes := []int{10, 32, 4 << 10, 4 << 20, 64 << 20} 1496 benchStr := Repeat(benchmarkString, 1497 (indexSizes[len(indexSizes)-1]+len(benchmarkString)-1)/len(benchmarkString)) 1498 benchFunc := func(b *testing.B, benchStr string) { 1499 b.SetBytes(int64(len(benchStr))) 1500 for i := 0; i < b.N; i++ { 1501 Count(benchStr, "=") 1502 } 1503 } 1504 for _, size := range indexSizes { 1505 b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { 1506 benchFunc(b, benchStr[:size]) 1507 }) 1508 } 1509 1510 } 1511 1512 var makeFieldsInput = func() string { 1513 x := make([]byte, 1<<20) 1514 // Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space. 1515 for i := range x { 1516 switch rand.Intn(10) { 1517 case 0: 1518 x[i] = ' ' 1519 case 1: 1520 if i > 0 && x[i-1] == 'x' { 1521 copy(x[i-1:], "") 1522 break 1523 } 1524 fallthrough 1525 default: 1526 x[i] = 'x' 1527 } 1528 } 1529 return string(x) 1530 } 1531 1532 var makeFieldsInputASCII = func() string { 1533 x := make([]byte, 1<<20) 1534 // Input is ~10% space, rest ASCII non-space. 1535 for i := range x { 1536 if rand.Intn(10) == 0 { 1537 x[i] = ' ' 1538 } else { 1539 x[i] = 'x' 1540 } 1541 } 1542 return string(x) 1543 } 1544 1545 var stringdata = []struct{ name, data string }{ 1546 {"ASCII", makeFieldsInputASCII()}, 1547 {"Mixed", makeFieldsInput()}, 1548 } 1549 1550 func BenchmarkFields(b *testing.B) { 1551 for _, sd := range stringdata { 1552 b.Run(sd.name, func(b *testing.B) { 1553 for j := 1 << 4; j <= 1<<20; j <<= 4 { 1554 b.Run(fmt.Sprintf("%d", j), func(b *testing.B) { 1555 b.ReportAllocs() 1556 b.SetBytes(int64(j)) 1557 data := sd.data[:j] 1558 for i := 0; i < b.N; i++ { 1559 Fields(data) 1560 } 1561 }) 1562 } 1563 }) 1564 } 1565 } 1566 1567 func BenchmarkFieldsFunc(b *testing.B) { 1568 for _, sd := range stringdata { 1569 b.Run(sd.name, func(b *testing.B) { 1570 for j := 1 << 4; j <= 1<<20; j <<= 4 { 1571 b.Run(fmt.Sprintf("%d", j), func(b *testing.B) { 1572 b.ReportAllocs() 1573 b.SetBytes(int64(j)) 1574 data := sd.data[:j] 1575 for i := 0; i < b.N; i++ { 1576 FieldsFunc(data, unicode.IsSpace) 1577 } 1578 }) 1579 } 1580 }) 1581 } 1582 } 1583 1584 func BenchmarkSplitEmptySeparator(b *testing.B) { 1585 for i := 0; i < b.N; i++ { 1586 Split(benchInputHard, "") 1587 } 1588 } 1589 1590 func BenchmarkSplitSingleByteSeparator(b *testing.B) { 1591 for i := 0; i < b.N; i++ { 1592 Split(benchInputHard, "/") 1593 } 1594 } 1595 1596 func BenchmarkSplitMultiByteSeparator(b *testing.B) { 1597 for i := 0; i < b.N; i++ { 1598 Split(benchInputHard, "hello") 1599 } 1600 } 1601 1602 func BenchmarkSplitNSingleByteSeparator(b *testing.B) { 1603 for i := 0; i < b.N; i++ { 1604 SplitN(benchInputHard, "/", 10) 1605 } 1606 } 1607 1608 func BenchmarkSplitNMultiByteSeparator(b *testing.B) { 1609 for i := 0; i < b.N; i++ { 1610 SplitN(benchInputHard, "hello", 10) 1611 } 1612 } 1613 1614 func BenchmarkRepeat(b *testing.B) { 1615 for i := 0; i < b.N; i++ { 1616 Repeat("-", 80) 1617 } 1618 } 1619 1620 func BenchmarkIndexAnyASCII(b *testing.B) { 1621 x := Repeat("#", 4096) // Never matches set 1622 cs := "0123456789abcdef" 1623 for k := 1; k <= 4096; k <<= 4 { 1624 for j := 1; j <= 16; j <<= 1 { 1625 b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) { 1626 for i := 0; i < b.N; i++ { 1627 IndexAny(x[:k], cs[:j]) 1628 } 1629 }) 1630 } 1631 } 1632 } 1633 1634 func BenchmarkTrimASCII(b *testing.B) { 1635 cs := "0123456789abcdef" 1636 for k := 1; k <= 4096; k <<= 4 { 1637 for j := 1; j <= 16; j <<= 1 { 1638 b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) { 1639 x := Repeat(cs[:j], k) // Always matches set 1640 for i := 0; i < b.N; i++ { 1641 Trim(x[:k], cs[:j]) 1642 } 1643 }) 1644 } 1645 } 1646 } 1647 1648 func BenchmarkIndexPeriodic(b *testing.B) { 1649 key := "aa" 1650 for _, skip := range [...]int{2, 4, 8, 16, 32, 64} { 1651 b.Run(fmt.Sprintf("IndexPeriodic%d", skip), func(b *testing.B) { 1652 s := Repeat("a"+Repeat(" ", skip-1), 1<<16/skip) 1653 for i := 0; i < b.N; i++ { 1654 Index(s, key) 1655 } 1656 }) 1657 } 1658 } 1659