github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/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 "io" 10 "math/rand" 11 "reflect" 12 . "strings" 13 "testing" 14 "unicode" 15 "unicode/utf8" 16 "unsafe" 17 ) 18 19 func eq(a, b []string) bool { 20 if len(a) != len(b) { 21 return false 22 } 23 for i := 0; i < len(a); i++ { 24 if a[i] != b[i] { 25 return false 26 } 27 } 28 return true 29 } 30 31 var abcd = "abcd" 32 var faces = "☺☻☹" 33 var commas = "1,2,3,4" 34 var dots = "1....2....3....4" 35 36 type IndexTest struct { 37 s string 38 sep string 39 out int 40 } 41 42 var indexTests = []IndexTest{ 43 {"", "", 0}, 44 {"", "a", -1}, 45 {"", "foo", -1}, 46 {"fo", "foo", -1}, 47 {"foo", "foo", 0}, 48 {"oofofoofooo", "f", 2}, 49 {"oofofoofooo", "foo", 4}, 50 {"barfoobarfoo", "foo", 3}, 51 {"foo", "", 0}, 52 {"foo", "o", 1}, 53 {"abcABCabc", "A", 3}, 54 // cases with one byte strings - test special case in Index() 55 {"", "a", -1}, 56 {"x", "a", -1}, 57 {"x", "x", 0}, 58 {"abc", "a", 0}, 59 {"abc", "b", 1}, 60 {"abc", "c", 2}, 61 {"abc", "x", -1}, 62 } 63 64 var lastIndexTests = []IndexTest{ 65 {"", "", 0}, 66 {"", "a", -1}, 67 {"", "foo", -1}, 68 {"fo", "foo", -1}, 69 {"foo", "foo", 0}, 70 {"foo", "f", 0}, 71 {"oofofoofooo", "f", 7}, 72 {"oofofoofooo", "foo", 7}, 73 {"barfoobarfoo", "foo", 9}, 74 {"foo", "", 3}, 75 {"foo", "o", 2}, 76 {"abcABCabc", "A", 3}, 77 {"abcABCabc", "a", 6}, 78 } 79 80 var indexAnyTests = []IndexTest{ 81 {"", "", -1}, 82 {"", "a", -1}, 83 {"", "abc", -1}, 84 {"a", "", -1}, 85 {"a", "a", 0}, 86 {"aaa", "a", 0}, 87 {"abc", "xyz", -1}, 88 {"abc", "xcz", 2}, 89 {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")}, 90 {"aRegExp*", ".(|)*+?^$[]", 7}, 91 {dots + dots + dots, " ", -1}, 92 } 93 var lastIndexAnyTests = []IndexTest{ 94 {"", "", -1}, 95 {"", "a", -1}, 96 {"", "abc", -1}, 97 {"a", "", -1}, 98 {"a", "a", 0}, 99 {"aaa", "a", 2}, 100 {"abc", "xyz", -1}, 101 {"abc", "ab", 1}, 102 {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")}, 103 {"a.RegExp*", ".(|)*+?^$[]", 8}, 104 {dots + dots + dots, " ", -1}, 105 } 106 107 // Execute f on each test case. funcName should be the name of f; it's used 108 // in failure reports. 109 func runIndexTests(t *testing.T, f func(s, sep string) int, funcName string, testCases []IndexTest) { 110 for _, test := range testCases { 111 actual := f(test.s, test.sep) 112 if actual != test.out { 113 t.Errorf("%s(%q,%q) = %v; want %v", funcName, test.s, test.sep, actual, test.out) 114 } 115 } 116 } 117 118 func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) } 119 func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) } 120 func TestIndexAny(t *testing.T) { runIndexTests(t, IndexAny, "IndexAny", indexAnyTests) } 121 func TestLastIndexAny(t *testing.T) { runIndexTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests) } 122 123 var indexRuneTests = []struct { 124 s string 125 rune rune 126 out int 127 }{ 128 {"a A x", 'A', 2}, 129 {"some_text=some_value", '=', 9}, 130 {"☺a", 'a', 3}, 131 {"a☻☺b", '☺', 4}, 132 } 133 134 func TestIndexRune(t *testing.T) { 135 for _, test := range indexRuneTests { 136 if actual := IndexRune(test.s, test.rune); actual != test.out { 137 t.Errorf("IndexRune(%q,%d)= %v; want %v", test.s, test.rune, actual, test.out) 138 } 139 } 140 } 141 142 const benchmarkString = "some_text=some☺value" 143 144 func BenchmarkIndexRune(b *testing.B) { 145 if got := IndexRune(benchmarkString, '☺'); got != 14 { 146 b.Fatalf("wrong index: expected 14, got=%d", got) 147 } 148 for i := 0; i < b.N; i++ { 149 IndexRune(benchmarkString, '☺') 150 } 151 } 152 153 func BenchmarkIndexRuneFastPath(b *testing.B) { 154 if got := IndexRune(benchmarkString, 'v'); got != 17 { 155 b.Fatalf("wrong index: expected 17, got=%d", got) 156 } 157 for i := 0; i < b.N; i++ { 158 IndexRune(benchmarkString, 'v') 159 } 160 } 161 162 func BenchmarkIndex(b *testing.B) { 163 if got := Index(benchmarkString, "v"); got != 17 { 164 b.Fatalf("wrong index: expected 17, got=%d", got) 165 } 166 for i := 0; i < b.N; i++ { 167 Index(benchmarkString, "v") 168 } 169 } 170 171 func BenchmarkLastIndex(b *testing.B) { 172 if got := Index(benchmarkString, "v"); got != 17 { 173 b.Fatalf("wrong index: expected 17, got=%d", got) 174 } 175 for i := 0; i < b.N; i++ { 176 LastIndex(benchmarkString, "v") 177 } 178 } 179 180 func BenchmarkIndexByte(b *testing.B) { 181 if got := IndexByte(benchmarkString, 'v'); got != 17 { 182 b.Fatalf("wrong index: expected 17, got=%d", got) 183 } 184 for i := 0; i < b.N; i++ { 185 IndexByte(benchmarkString, 'v') 186 } 187 } 188 189 var explodetests = []struct { 190 s string 191 n int 192 a []string 193 }{ 194 {"", -1, []string{}}, 195 {abcd, 4, []string{"a", "b", "c", "d"}}, 196 {faces, 3, []string{"☺", "☻", "☹"}}, 197 {abcd, 2, []string{"a", "bcd"}}, 198 } 199 200 func TestExplode(t *testing.T) { 201 for _, tt := range explodetests { 202 a := SplitN(tt.s, "", tt.n) 203 if !eq(a, tt.a) { 204 t.Errorf("explode(%q, %d) = %v; want %v", tt.s, tt.n, a, tt.a) 205 continue 206 } 207 s := Join(a, "") 208 if s != tt.s { 209 t.Errorf(`Join(explode(%q, %d), "") = %q`, tt.s, tt.n, s) 210 } 211 } 212 } 213 214 type SplitTest struct { 215 s string 216 sep string 217 n int 218 a []string 219 } 220 221 var splittests = []SplitTest{ 222 {abcd, "a", 0, nil}, 223 {abcd, "a", -1, []string{"", "bcd"}}, 224 {abcd, "z", -1, []string{"abcd"}}, 225 {abcd, "", -1, []string{"a", "b", "c", "d"}}, 226 {commas, ",", -1, []string{"1", "2", "3", "4"}}, 227 {dots, "...", -1, []string{"1", ".2", ".3", ".4"}}, 228 {faces, "☹", -1, []string{"☺☻", ""}}, 229 {faces, "~", -1, []string{faces}}, 230 {faces, "", -1, []string{"☺", "☻", "☹"}}, 231 {"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}}, 232 {"1 2", " ", 3, []string{"1", "2"}}, 233 {"123", "", 2, []string{"1", "23"}}, 234 {"123", "", 17, []string{"1", "2", "3"}}, 235 } 236 237 func TestSplit(t *testing.T) { 238 for _, tt := range splittests { 239 a := SplitN(tt.s, tt.sep, tt.n) 240 if !eq(a, tt.a) { 241 t.Errorf("Split(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, a, tt.a) 242 continue 243 } 244 if tt.n == 0 { 245 continue 246 } 247 s := Join(a, tt.sep) 248 if s != tt.s { 249 t.Errorf("Join(Split(%q, %q, %d), %q) = %q", tt.s, tt.sep, tt.n, tt.sep, s) 250 } 251 if tt.n < 0 { 252 b := Split(tt.s, tt.sep) 253 if !reflect.DeepEqual(a, b) { 254 t.Errorf("Split disagrees with SplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a) 255 } 256 } 257 } 258 } 259 260 var splitaftertests = []SplitTest{ 261 {abcd, "a", -1, []string{"a", "bcd"}}, 262 {abcd, "z", -1, []string{"abcd"}}, 263 {abcd, "", -1, []string{"a", "b", "c", "d"}}, 264 {commas, ",", -1, []string{"1,", "2,", "3,", "4"}}, 265 {dots, "...", -1, []string{"1...", ".2...", ".3...", ".4"}}, 266 {faces, "☹", -1, []string{"☺☻☹", ""}}, 267 {faces, "~", -1, []string{faces}}, 268 {faces, "", -1, []string{"☺", "☻", "☹"}}, 269 {"1 2 3 4", " ", 3, []string{"1 ", "2 ", "3 4"}}, 270 {"1 2 3", " ", 3, []string{"1 ", "2 ", "3"}}, 271 {"1 2", " ", 3, []string{"1 ", "2"}}, 272 {"123", "", 2, []string{"1", "23"}}, 273 {"123", "", 17, []string{"1", "2", "3"}}, 274 } 275 276 func TestSplitAfter(t *testing.T) { 277 for _, tt := range splitaftertests { 278 a := SplitAfterN(tt.s, tt.sep, tt.n) 279 if !eq(a, tt.a) { 280 t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, a, tt.a) 281 continue 282 } 283 s := Join(a, "") 284 if s != tt.s { 285 t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s) 286 } 287 if tt.n < 0 { 288 b := SplitAfter(tt.s, tt.sep) 289 if !reflect.DeepEqual(a, b) { 290 t.Errorf("SplitAfter disagrees with SplitAfterN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a) 291 } 292 } 293 } 294 } 295 296 type FieldsTest struct { 297 s string 298 a []string 299 } 300 301 var fieldstests = []FieldsTest{ 302 {"", []string{}}, 303 {" ", []string{}}, 304 {" \t ", []string{}}, 305 {" abc ", []string{"abc"}}, 306 {"1 2 3 4", []string{"1", "2", "3", "4"}}, 307 {"1 2 3 4", []string{"1", "2", "3", "4"}}, 308 {"1\t\t2\t\t3\t4", []string{"1", "2", "3", "4"}}, 309 {"1\u20002\u20013\u20024", []string{"1", "2", "3", "4"}}, 310 {"\u2000\u2001\u2002", []string{}}, 311 {"\n™\t™\n", []string{"™", "™"}}, 312 {faces, []string{faces}}, 313 } 314 315 func TestFields(t *testing.T) { 316 for _, tt := range fieldstests { 317 a := Fields(tt.s) 318 if !eq(a, tt.a) { 319 t.Errorf("Fields(%q) = %v; want %v", tt.s, a, tt.a) 320 continue 321 } 322 } 323 } 324 325 var FieldsFuncTests = []FieldsTest{ 326 {"", []string{}}, 327 {"XX", []string{}}, 328 {"XXhiXXX", []string{"hi"}}, 329 {"aXXbXXXcX", []string{"a", "b", "c"}}, 330 } 331 332 func TestFieldsFunc(t *testing.T) { 333 for _, tt := range fieldstests { 334 a := FieldsFunc(tt.s, unicode.IsSpace) 335 if !eq(a, tt.a) { 336 t.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt.s, a, tt.a) 337 continue 338 } 339 } 340 pred := func(c rune) bool { return c == 'X' } 341 for _, tt := range FieldsFuncTests { 342 a := FieldsFunc(tt.s, pred) 343 if !eq(a, tt.a) { 344 t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a) 345 } 346 } 347 } 348 349 // Test case for any function which accepts and returns a single string. 350 type StringTest struct { 351 in, out string 352 } 353 354 // Execute f on each test case. funcName should be the name of f; it's used 355 // in failure reports. 356 func runStringTests(t *testing.T, f func(string) string, funcName string, testCases []StringTest) { 357 for _, tc := range testCases { 358 actual := f(tc.in) 359 if actual != tc.out { 360 t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out) 361 } 362 } 363 } 364 365 var upperTests = []StringTest{ 366 {"", ""}, 367 {"abc", "ABC"}, 368 {"AbC123", "ABC123"}, 369 {"azAZ09_", "AZAZ09_"}, 370 {"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char 371 } 372 373 var lowerTests = []StringTest{ 374 {"", ""}, 375 {"abc", "abc"}, 376 {"AbC123", "abc123"}, 377 {"azAZ09_", "azaz09_"}, 378 {"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char 379 } 380 381 const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000" 382 383 var trimSpaceTests = []StringTest{ 384 {"", ""}, 385 {"abc", "abc"}, 386 {space + "abc" + space, "abc"}, 387 {" ", ""}, 388 {" \t\r\n \t\t\r\r\n\n ", ""}, 389 {" \t\r\n x\t\t\r\r\n\n ", "x"}, 390 {" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"}, 391 {"1 \t\r\n2", "1 \t\r\n2"}, 392 {" x\x80", "x\x80"}, 393 {" x\xc0", "x\xc0"}, 394 {"x \xc0\xc0 ", "x \xc0\xc0"}, 395 {"x \xc0", "x \xc0"}, 396 {"x \xc0 ", "x \xc0"}, 397 {"x \xc0\xc0 ", "x \xc0\xc0"}, 398 {"x ☺\xc0\xc0 ", "x ☺\xc0\xc0"}, 399 {"x ☺ ", "x ☺"}, 400 } 401 402 func tenRunes(ch rune) string { 403 r := make([]rune, 10) 404 for i := range r { 405 r[i] = ch 406 } 407 return string(r) 408 } 409 410 // User-defined self-inverse mapping function 411 func rot13(r rune) rune { 412 step := rune(13) 413 if r >= 'a' && r <= 'z' { 414 return ((r - 'a' + step) % 26) + 'a' 415 } 416 if r >= 'A' && r <= 'Z' { 417 return ((r - 'A' + step) % 26) + 'A' 418 } 419 return r 420 } 421 422 func TestMap(t *testing.T) { 423 // Run a couple of awful growth/shrinkage tests 424 a := tenRunes('a') 425 // 1. Grow. This triggers two reallocations in Map. 426 maxRune := func(rune) rune { return unicode.MaxRune } 427 m := Map(maxRune, a) 428 expect := tenRunes(unicode.MaxRune) 429 if m != expect { 430 t.Errorf("growing: expected %q got %q", expect, m) 431 } 432 433 // 2. Shrink 434 minRune := func(rune) rune { return 'a' } 435 m = Map(minRune, tenRunes(unicode.MaxRune)) 436 expect = a 437 if m != expect { 438 t.Errorf("shrinking: expected %q got %q", expect, m) 439 } 440 441 // 3. Rot13 442 m = Map(rot13, "a to zed") 443 expect = "n gb mrq" 444 if m != expect { 445 t.Errorf("rot13: expected %q got %q", expect, m) 446 } 447 448 // 4. Rot13^2 449 m = Map(rot13, Map(rot13, "a to zed")) 450 expect = "a to zed" 451 if m != expect { 452 t.Errorf("rot13: expected %q got %q", expect, m) 453 } 454 455 // 5. Drop 456 dropNotLatin := func(r rune) rune { 457 if unicode.Is(unicode.Latin, r) { 458 return r 459 } 460 return -1 461 } 462 m = Map(dropNotLatin, "Hello, 세계") 463 expect = "Hello" 464 if m != expect { 465 t.Errorf("drop: expected %q got %q", expect, m) 466 } 467 468 // 6. Identity 469 identity := func(r rune) rune { 470 return r 471 } 472 orig := "Input string that we expect not to be copied." 473 m = Map(identity, orig) 474 if (*reflect.StringHeader)(unsafe.Pointer(&orig)).Data != 475 (*reflect.StringHeader)(unsafe.Pointer(&m)).Data { 476 t.Error("unexpected copy during identity map") 477 } 478 } 479 480 func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) } 481 482 func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) } 483 484 func BenchmarkMapNoChanges(b *testing.B) { 485 identity := func(r rune) rune { 486 return r 487 } 488 for i := 0; i < b.N; i++ { 489 Map(identity, "Some string that won't be modified.") 490 } 491 } 492 493 func TestSpecialCase(t *testing.T) { 494 lower := "abcçdefgğhıijklmnoöprsştuüvyz" 495 upper := "ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZ" 496 u := ToUpperSpecial(unicode.TurkishCase, upper) 497 if u != upper { 498 t.Errorf("Upper(upper) is %s not %s", u, upper) 499 } 500 u = ToUpperSpecial(unicode.TurkishCase, lower) 501 if u != upper { 502 t.Errorf("Upper(lower) is %s not %s", u, upper) 503 } 504 l := ToLowerSpecial(unicode.TurkishCase, lower) 505 if l != lower { 506 t.Errorf("Lower(lower) is %s not %s", l, lower) 507 } 508 l = ToLowerSpecial(unicode.TurkishCase, upper) 509 if l != lower { 510 t.Errorf("Lower(upper) is %s not %s", l, lower) 511 } 512 } 513 514 func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) } 515 516 var trimTests = []struct { 517 f string 518 in, arg, out string 519 }{ 520 {"Trim", "abba", "a", "bb"}, 521 {"Trim", "abba", "ab", ""}, 522 {"TrimLeft", "abba", "ab", ""}, 523 {"TrimRight", "abba", "ab", ""}, 524 {"TrimLeft", "abba", "a", "bba"}, 525 {"TrimRight", "abba", "a", "abb"}, 526 {"Trim", "<tag>", "<>", "tag"}, 527 {"Trim", "* listitem", " *", "listitem"}, 528 {"Trim", `"quote"`, `"`, "quote"}, 529 {"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"}, 530 //empty string tests 531 {"Trim", "abba", "", "abba"}, 532 {"Trim", "", "123", ""}, 533 {"Trim", "", "", ""}, 534 {"TrimLeft", "abba", "", "abba"}, 535 {"TrimLeft", "", "123", ""}, 536 {"TrimLeft", "", "", ""}, 537 {"TrimRight", "abba", "", "abba"}, 538 {"TrimRight", "", "123", ""}, 539 {"TrimRight", "", "", ""}, 540 {"TrimRight", "☺\xc0", "☺", "☺\xc0"}, 541 {"TrimPrefix", "aabb", "a", "abb"}, 542 {"TrimPrefix", "aabb", "b", "aabb"}, 543 {"TrimSuffix", "aabb", "a", "aabb"}, 544 {"TrimSuffix", "aabb", "b", "aab"}, 545 } 546 547 func TestTrim(t *testing.T) { 548 for _, tc := range trimTests { 549 name := tc.f 550 var f func(string, string) string 551 switch name { 552 case "Trim": 553 f = Trim 554 case "TrimLeft": 555 f = TrimLeft 556 case "TrimRight": 557 f = TrimRight 558 case "TrimPrefix": 559 f = TrimPrefix 560 case "TrimSuffix": 561 f = TrimSuffix 562 default: 563 t.Errorf("Undefined trim function %s", name) 564 } 565 actual := f(tc.in, tc.arg) 566 if actual != tc.out { 567 t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out) 568 } 569 } 570 } 571 572 type predicate struct { 573 f func(rune) bool 574 name string 575 } 576 577 var isSpace = predicate{unicode.IsSpace, "IsSpace"} 578 var isDigit = predicate{unicode.IsDigit, "IsDigit"} 579 var isUpper = predicate{unicode.IsUpper, "IsUpper"} 580 var isValidRune = predicate{ 581 func(r rune) bool { 582 return r != utf8.RuneError 583 }, 584 "IsValidRune", 585 } 586 587 func not(p predicate) predicate { 588 return predicate{ 589 func(r rune) bool { 590 return !p.f(r) 591 }, 592 "not " + p.name, 593 } 594 } 595 596 var trimFuncTests = []struct { 597 f predicate 598 in, out string 599 }{ 600 {isSpace, space + " hello " + space, "hello"}, 601 {isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"}, 602 {isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"}, 603 {not(isSpace), "hello" + space + "hello", space}, 604 {not(isDigit), "hello\u0e50\u0e521234\u0e50\u0e51helo", "\u0e50\u0e521234\u0e50\u0e51"}, 605 {isValidRune, "ab\xc0a\xc0cd", "\xc0a\xc0"}, 606 {not(isValidRune), "\xc0a\xc0", "a"}, 607 } 608 609 func TestTrimFunc(t *testing.T) { 610 for _, tc := range trimFuncTests { 611 actual := TrimFunc(tc.in, tc.f.f) 612 if actual != tc.out { 613 t.Errorf("TrimFunc(%q, %q) = %q; want %q", tc.in, tc.f.name, actual, tc.out) 614 } 615 } 616 } 617 618 var indexFuncTests = []struct { 619 in string 620 f predicate 621 first, last int 622 }{ 623 {"", isValidRune, -1, -1}, 624 {"abc", isDigit, -1, -1}, 625 {"0123", isDigit, 0, 3}, 626 {"a1b", isDigit, 1, 1}, 627 {space, isSpace, 0, len(space) - 3}, // last rune in space is 3 bytes 628 {"\u0e50\u0e5212hello34\u0e50\u0e51", isDigit, 0, 18}, 629 {"\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", isUpper, 0, 34}, 630 {"12\u0e50\u0e52hello34\u0e50\u0e51", not(isDigit), 8, 12}, 631 632 // tests of invalid UTF-8 633 {"\x801", isDigit, 1, 1}, 634 {"\x80abc", isDigit, -1, -1}, 635 {"\xc0a\xc0", isValidRune, 1, 1}, 636 {"\xc0a\xc0", not(isValidRune), 0, 2}, 637 {"\xc0☺\xc0", not(isValidRune), 0, 4}, 638 {"\xc0☺\xc0\xc0", not(isValidRune), 0, 5}, 639 {"ab\xc0a\xc0cd", not(isValidRune), 2, 4}, 640 {"a\xe0\x80cd", not(isValidRune), 1, 2}, 641 {"\x80\x80\x80\x80", not(isValidRune), 0, 3}, 642 } 643 644 func TestIndexFunc(t *testing.T) { 645 for _, tc := range indexFuncTests { 646 first := IndexFunc(tc.in, tc.f.f) 647 if first != tc.first { 648 t.Errorf("IndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, first, tc.first) 649 } 650 last := LastIndexFunc(tc.in, tc.f.f) 651 if last != tc.last { 652 t.Errorf("LastIndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, last, tc.last) 653 } 654 } 655 } 656 657 func equal(m string, s1, s2 string, t *testing.T) bool { 658 if s1 == s2 { 659 return true 660 } 661 e1 := Split(s1, "") 662 e2 := Split(s2, "") 663 for i, c1 := range e1 { 664 if i >= len(e2) { 665 break 666 } 667 r1, _ := utf8.DecodeRuneInString(c1) 668 r2, _ := utf8.DecodeRuneInString(e2[i]) 669 if r1 != r2 { 670 t.Errorf("%s diff at %d: U+%04X U+%04X", m, i, r1, r2) 671 } 672 } 673 return false 674 } 675 676 func TestCaseConsistency(t *testing.T) { 677 // Make a string of all the runes. 678 numRunes := int(unicode.MaxRune + 1) 679 if testing.Short() { 680 numRunes = 1000 681 } 682 a := make([]rune, numRunes) 683 for i := range a { 684 a[i] = rune(i) 685 } 686 s := string(a) 687 // convert the cases. 688 upper := ToUpper(s) 689 lower := ToLower(s) 690 691 // Consistency checks 692 if n := utf8.RuneCountInString(upper); n != numRunes { 693 t.Error("rune count wrong in upper:", n) 694 } 695 if n := utf8.RuneCountInString(lower); n != numRunes { 696 t.Error("rune count wrong in lower:", n) 697 } 698 if !equal("ToUpper(upper)", ToUpper(upper), upper, t) { 699 t.Error("ToUpper(upper) consistency fail") 700 } 701 if !equal("ToLower(lower)", ToLower(lower), lower, t) { 702 t.Error("ToLower(lower) consistency fail") 703 } 704 /* 705 These fail because of non-one-to-oneness of the data, such as multiple 706 upper case 'I' mapping to 'i'. We comment them out but keep them for 707 interest. 708 For instance: CAPITAL LETTER I WITH DOT ABOVE: 709 unicode.ToUpper(unicode.ToLower('\u0130')) != '\u0130' 710 711 if !equal("ToUpper(lower)", ToUpper(lower), upper, t) { 712 t.Error("ToUpper(lower) consistency fail"); 713 } 714 if !equal("ToLower(upper)", ToLower(upper), lower, t) { 715 t.Error("ToLower(upper) consistency fail"); 716 } 717 */ 718 } 719 720 var RepeatTests = []struct { 721 in, out string 722 count int 723 }{ 724 {"", "", 0}, 725 {"", "", 1}, 726 {"", "", 2}, 727 {"-", "", 0}, 728 {"-", "-", 1}, 729 {"-", "----------", 10}, 730 {"abc ", "abc abc abc ", 3}, 731 } 732 733 func TestRepeat(t *testing.T) { 734 for _, tt := range RepeatTests { 735 a := Repeat(tt.in, tt.count) 736 if !equal("Repeat(s)", a, tt.out, t) { 737 t.Errorf("Repeat(%v, %d) = %v; want %v", tt.in, tt.count, a, tt.out) 738 continue 739 } 740 } 741 } 742 743 func runesEqual(a, b []rune) bool { 744 if len(a) != len(b) { 745 return false 746 } 747 for i, r := range a { 748 if r != b[i] { 749 return false 750 } 751 } 752 return true 753 } 754 755 var RunesTests = []struct { 756 in string 757 out []rune 758 lossy bool 759 }{ 760 {"", []rune{}, false}, 761 {" ", []rune{32}, false}, 762 {"ABC", []rune{65, 66, 67}, false}, 763 {"abc", []rune{97, 98, 99}, false}, 764 {"\u65e5\u672c\u8a9e", []rune{26085, 26412, 35486}, false}, 765 {"ab\x80c", []rune{97, 98, 0xFFFD, 99}, true}, 766 {"ab\xc0c", []rune{97, 98, 0xFFFD, 99}, true}, 767 } 768 769 func TestRunes(t *testing.T) { 770 for _, tt := range RunesTests { 771 a := []rune(tt.in) 772 if !runesEqual(a, tt.out) { 773 t.Errorf("[]rune(%q) = %v; want %v", tt.in, a, tt.out) 774 continue 775 } 776 if !tt.lossy { 777 // can only test reassembly if we didn't lose information 778 s := string(a) 779 if s != tt.in { 780 t.Errorf("string([]rune(%q)) = %x; want %x", tt.in, s, tt.in) 781 } 782 } 783 } 784 } 785 786 func TestReadByte(t *testing.T) { 787 testStrings := []string{"", abcd, faces, commas} 788 for _, s := range testStrings { 789 reader := NewReader(s) 790 if e := reader.UnreadByte(); e == nil { 791 t.Errorf("Unreading %q at beginning: expected error", s) 792 } 793 var res bytes.Buffer 794 for { 795 b, e := reader.ReadByte() 796 if e == io.EOF { 797 break 798 } 799 if e != nil { 800 t.Errorf("Reading %q: %s", s, e) 801 break 802 } 803 res.WriteByte(b) 804 // unread and read again 805 e = reader.UnreadByte() 806 if e != nil { 807 t.Errorf("Unreading %q: %s", s, e) 808 break 809 } 810 b1, e := reader.ReadByte() 811 if e != nil { 812 t.Errorf("Reading %q after unreading: %s", s, e) 813 break 814 } 815 if b1 != b { 816 t.Errorf("Reading %q after unreading: want byte %q, got %q", s, b, b1) 817 break 818 } 819 } 820 if res.String() != s { 821 t.Errorf("Reader(%q).ReadByte() produced %q", s, res.String()) 822 } 823 } 824 } 825 826 func TestReadRune(t *testing.T) { 827 testStrings := []string{"", abcd, faces, commas} 828 for _, s := range testStrings { 829 reader := NewReader(s) 830 if e := reader.UnreadRune(); e == nil { 831 t.Errorf("Unreading %q at beginning: expected error", s) 832 } 833 res := "" 834 for { 835 r, z, e := reader.ReadRune() 836 if e == io.EOF { 837 break 838 } 839 if e != nil { 840 t.Errorf("Reading %q: %s", s, e) 841 break 842 } 843 res += string(r) 844 // unread and read again 845 e = reader.UnreadRune() 846 if e != nil { 847 t.Errorf("Unreading %q: %s", s, e) 848 break 849 } 850 r1, z1, e := reader.ReadRune() 851 if e != nil { 852 t.Errorf("Reading %q after unreading: %s", s, e) 853 break 854 } 855 if r1 != r { 856 t.Errorf("Reading %q after unreading: want rune %q, got %q", s, r, r1) 857 break 858 } 859 if z1 != z { 860 t.Errorf("Reading %q after unreading: want size %d, got %d", s, z, z1) 861 break 862 } 863 } 864 if res != s { 865 t.Errorf("Reader(%q).ReadRune() produced %q", s, res) 866 } 867 } 868 } 869 870 var UnreadRuneErrorTests = []struct { 871 name string 872 f func(*Reader) 873 }{ 874 {"Read", func(r *Reader) { r.Read([]byte{0}) }}, 875 {"ReadByte", func(r *Reader) { r.ReadByte() }}, 876 {"UnreadRune", func(r *Reader) { r.UnreadRune() }}, 877 {"Seek", func(r *Reader) { r.Seek(0, 1) }}, 878 {"WriteTo", func(r *Reader) { r.WriteTo(&bytes.Buffer{}) }}, 879 } 880 881 func TestUnreadRuneError(t *testing.T) { 882 for _, tt := range UnreadRuneErrorTests { 883 reader := NewReader("0123456789") 884 if _, _, err := reader.ReadRune(); err != nil { 885 // should not happen 886 t.Fatal(err) 887 } 888 tt.f(reader) 889 err := reader.UnreadRune() 890 if err == nil { 891 t.Errorf("Unreading after %s: expected error", tt.name) 892 } 893 } 894 } 895 896 var ReplaceTests = []struct { 897 in string 898 old, new string 899 n int 900 out string 901 }{ 902 {"hello", "l", "L", 0, "hello"}, 903 {"hello", "l", "L", -1, "heLLo"}, 904 {"hello", "x", "X", -1, "hello"}, 905 {"", "x", "X", -1, ""}, 906 {"radar", "r", "<r>", -1, "<r>ada<r>"}, 907 {"", "", "<>", -1, "<>"}, 908 {"banana", "a", "<>", -1, "b<>n<>n<>"}, 909 {"banana", "a", "<>", 1, "b<>nana"}, 910 {"banana", "a", "<>", 1000, "b<>n<>n<>"}, 911 {"banana", "an", "<>", -1, "b<><>a"}, 912 {"banana", "ana", "<>", -1, "b<>na"}, 913 {"banana", "", "<>", -1, "<>b<>a<>n<>a<>n<>a<>"}, 914 {"banana", "", "<>", 10, "<>b<>a<>n<>a<>n<>a<>"}, 915 {"banana", "", "<>", 6, "<>b<>a<>n<>a<>n<>a"}, 916 {"banana", "", "<>", 5, "<>b<>a<>n<>a<>na"}, 917 {"banana", "", "<>", 1, "<>banana"}, 918 {"banana", "a", "a", -1, "banana"}, 919 {"banana", "a", "a", 1, "banana"}, 920 {"☺☻☹", "", "<>", -1, "<>☺<>☻<>☹<>"}, 921 } 922 923 func TestReplace(t *testing.T) { 924 for _, tt := range ReplaceTests { 925 if s := Replace(tt.in, tt.old, tt.new, tt.n); s != tt.out { 926 t.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt.in, tt.old, tt.new, tt.n, s, tt.out) 927 } 928 } 929 } 930 931 var TitleTests = []struct { 932 in, out string 933 }{ 934 {"", ""}, 935 {"a", "A"}, 936 {" aaa aaa aaa ", " Aaa Aaa Aaa "}, 937 {" Aaa Aaa Aaa ", " Aaa Aaa Aaa "}, 938 {"123a456", "123a456"}, 939 {"double-blind", "Double-Blind"}, 940 {"ÿøû", "Ÿøû"}, 941 {"with_underscore", "With_underscore"}, 942 {"unicode \xe2\x80\xa8 line separator", "Unicode \xe2\x80\xa8 Line Separator"}, 943 } 944 945 func TestTitle(t *testing.T) { 946 for _, tt := range TitleTests { 947 if s := Title(tt.in); s != tt.out { 948 t.Errorf("Title(%q) = %q, want %q", tt.in, s, tt.out) 949 } 950 } 951 } 952 953 var ContainsTests = []struct { 954 str, substr string 955 expected bool 956 }{ 957 {"abc", "bc", true}, 958 {"abc", "bcd", false}, 959 {"abc", "", true}, 960 {"", "a", false}, 961 } 962 963 func TestContains(t *testing.T) { 964 for _, ct := range ContainsTests { 965 if Contains(ct.str, ct.substr) != ct.expected { 966 t.Errorf("Contains(%s, %s) = %v, want %v", 967 ct.str, ct.substr, !ct.expected, ct.expected) 968 } 969 } 970 } 971 972 var ContainsAnyTests = []struct { 973 str, substr string 974 expected bool 975 }{ 976 {"", "", false}, 977 {"", "a", false}, 978 {"", "abc", false}, 979 {"a", "", false}, 980 {"a", "a", true}, 981 {"aaa", "a", true}, 982 {"abc", "xyz", false}, 983 {"abc", "xcz", true}, 984 {"a☺b☻c☹d", "uvw☻xyz", true}, 985 {"aRegExp*", ".(|)*+?^$[]", true}, 986 {dots + dots + dots, " ", false}, 987 } 988 989 func TestContainsAny(t *testing.T) { 990 for _, ct := range ContainsAnyTests { 991 if ContainsAny(ct.str, ct.substr) != ct.expected { 992 t.Errorf("ContainsAny(%s, %s) = %v, want %v", 993 ct.str, ct.substr, !ct.expected, ct.expected) 994 } 995 } 996 } 997 998 var ContainsRuneTests = []struct { 999 str string 1000 r rune 1001 expected bool 1002 }{ 1003 {"", 'a', false}, 1004 {"a", 'a', true}, 1005 {"aaa", 'a', true}, 1006 {"abc", 'y', false}, 1007 {"abc", 'c', true}, 1008 {"a☺b☻c☹d", 'x', false}, 1009 {"a☺b☻c☹d", '☻', true}, 1010 {"aRegExp*", '*', true}, 1011 } 1012 1013 func TestContainsRune(t *testing.T) { 1014 for _, ct := range ContainsRuneTests { 1015 if ContainsRune(ct.str, ct.r) != ct.expected { 1016 t.Errorf("ContainsRune(%q, %q) = %v, want %v", 1017 ct.str, ct.r, !ct.expected, ct.expected) 1018 } 1019 } 1020 } 1021 1022 var EqualFoldTests = []struct { 1023 s, t string 1024 out bool 1025 }{ 1026 {"abc", "abc", true}, 1027 {"ABcd", "ABcd", true}, 1028 {"123abc", "123ABC", true}, 1029 {"αβδ", "ΑΒΔ", true}, 1030 {"abc", "xyz", false}, 1031 {"abc", "XYZ", false}, 1032 {"abcdefghijk", "abcdefghijX", false}, 1033 {"abcdefghijk", "abcdefghij\u212A", true}, 1034 {"abcdefghijK", "abcdefghij\u212A", true}, 1035 {"abcdefghijkz", "abcdefghij\u212Ay", false}, 1036 {"abcdefghijKz", "abcdefghij\u212Ay", false}, 1037 } 1038 1039 func TestEqualFold(t *testing.T) { 1040 for _, tt := range EqualFoldTests { 1041 if out := EqualFold(tt.s, tt.t); out != tt.out { 1042 t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.s, tt.t, out, tt.out) 1043 } 1044 if out := EqualFold(tt.t, tt.s); out != tt.out { 1045 t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.t, tt.s, out, tt.out) 1046 } 1047 } 1048 } 1049 1050 var CountTests = []struct { 1051 s, sep string 1052 num int 1053 }{ 1054 {"", "", 1}, 1055 {"", "notempty", 0}, 1056 {"notempty", "", 9}, 1057 {"smaller", "not smaller", 0}, 1058 {"12345678987654321", "6", 2}, 1059 {"611161116", "6", 3}, 1060 {"notequal", "NotEqual", 0}, 1061 {"equal", "equal", 1}, 1062 {"abc1231231123q", "123", 3}, 1063 {"11111", "11", 2}, 1064 } 1065 1066 func TestCount(t *testing.T) { 1067 for _, tt := range CountTests { 1068 if num := Count(tt.s, tt.sep); num != tt.num { 1069 t.Errorf("Count(\"%s\", \"%s\") = %d, want %d", tt.s, tt.sep, num, tt.num) 1070 } 1071 } 1072 } 1073 1074 func makeBenchInputHard() string { 1075 tokens := [...]string{ 1076 "<a>", "<p>", "<b>", "<strong>", 1077 "</a>", "</p>", "</b>", "</strong>", 1078 "hello", "world", 1079 } 1080 x := make([]byte, 0, 1<<20) 1081 for { 1082 i := rand.Intn(len(tokens)) 1083 if len(x)+len(tokens[i]) >= 1<<20 { 1084 break 1085 } 1086 x = append(x, tokens[i]...) 1087 } 1088 return string(x) 1089 } 1090 1091 var benchInputHard = makeBenchInputHard() 1092 1093 func benchmarkIndexHard(b *testing.B, sep string) { 1094 for i := 0; i < b.N; i++ { 1095 Index(benchInputHard, sep) 1096 } 1097 } 1098 1099 func benchmarkLastIndexHard(b *testing.B, sep string) { 1100 for i := 0; i < b.N; i++ { 1101 LastIndex(benchInputHard, sep) 1102 } 1103 } 1104 1105 func benchmarkCountHard(b *testing.B, sep string) { 1106 for i := 0; i < b.N; i++ { 1107 Count(benchInputHard, sep) 1108 } 1109 } 1110 1111 func BenchmarkIndexHard1(b *testing.B) { benchmarkIndexHard(b, "<>") } 1112 func BenchmarkIndexHard2(b *testing.B) { benchmarkIndexHard(b, "</pre>") } 1113 func BenchmarkIndexHard3(b *testing.B) { benchmarkIndexHard(b, "<b>hello world</b>") } 1114 1115 func BenchmarkLastIndexHard1(b *testing.B) { benchmarkLastIndexHard(b, "<>") } 1116 func BenchmarkLastIndexHard2(b *testing.B) { benchmarkLastIndexHard(b, "</pre>") } 1117 func BenchmarkLastIndexHard3(b *testing.B) { benchmarkLastIndexHard(b, "<b>hello world</b>") } 1118 1119 func BenchmarkCountHard1(b *testing.B) { benchmarkCountHard(b, "<>") } 1120 func BenchmarkCountHard2(b *testing.B) { benchmarkCountHard(b, "</pre>") } 1121 func BenchmarkCountHard3(b *testing.B) { benchmarkCountHard(b, "<b>hello world</b>") } 1122 1123 var benchInputTorture = Repeat("ABC", 1<<10) + "123" + Repeat("ABC", 1<<10) 1124 var benchNeedleTorture = Repeat("ABC", 1<<10+1) 1125 1126 func BenchmarkIndexTorture(b *testing.B) { 1127 for i := 0; i < b.N; i++ { 1128 Index(benchInputTorture, benchNeedleTorture) 1129 } 1130 } 1131 1132 func BenchmarkCountTorture(b *testing.B) { 1133 for i := 0; i < b.N; i++ { 1134 Count(benchInputTorture, benchNeedleTorture) 1135 } 1136 } 1137 1138 func BenchmarkCountTortureOverlapping(b *testing.B) { 1139 A := Repeat("ABC", 1<<20) 1140 B := Repeat("ABC", 1<<10) 1141 for i := 0; i < b.N; i++ { 1142 Count(A, B) 1143 } 1144 } 1145 1146 var makeFieldsInput = func() string { 1147 x := make([]byte, 1<<20) 1148 // Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space. 1149 for i := range x { 1150 switch rand.Intn(10) { 1151 case 0: 1152 x[i] = ' ' 1153 case 1: 1154 if i > 0 && x[i-1] == 'x' { 1155 copy(x[i-1:], "χ") 1156 break 1157 } 1158 fallthrough 1159 default: 1160 x[i] = 'x' 1161 } 1162 } 1163 return string(x) 1164 } 1165 1166 var fieldsInput = makeFieldsInput() 1167 1168 func BenchmarkFields(b *testing.B) { 1169 b.SetBytes(int64(len(fieldsInput))) 1170 for i := 0; i < b.N; i++ { 1171 Fields(fieldsInput) 1172 } 1173 } 1174 1175 func BenchmarkFieldsFunc(b *testing.B) { 1176 b.SetBytes(int64(len(fieldsInput))) 1177 for i := 0; i < b.N; i++ { 1178 FieldsFunc(fieldsInput, unicode.IsSpace) 1179 } 1180 } 1181 1182 func BenchmarkSplit1(b *testing.B) { 1183 for i := 0; i < b.N; i++ { 1184 Split(benchInputHard, "") 1185 } 1186 } 1187 1188 func BenchmarkSplit2(b *testing.B) { 1189 for i := 0; i < b.N; i++ { 1190 Split(benchInputHard, "/") 1191 } 1192 } 1193 1194 func BenchmarkSplit3(b *testing.B) { 1195 for i := 0; i < b.N; i++ { 1196 Split(benchInputHard, "hello") 1197 } 1198 } 1199 1200 func BenchmarkRepeat(b *testing.B) { 1201 for i := 0; i < b.N; i++ { 1202 Repeat("-", 80) 1203 } 1204 }