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