github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/src/bytes/bytes_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 bytes_test 6 7 import ( 8 . "bytes" 9 "fmt" 10 "math/rand" 11 "reflect" 12 "testing" 13 "unicode" 14 "unicode/utf8" 15 ) 16 17 func eq(a, b []string) bool { 18 if len(a) != len(b) { 19 return false 20 } 21 for i := 0; i < len(a); i++ { 22 if a[i] != b[i] { 23 return false 24 } 25 } 26 return true 27 } 28 29 func sliceOfString(s [][]byte) []string { 30 result := make([]string, len(s)) 31 for i, v := range s { 32 result[i] = string(v) 33 } 34 return result 35 } 36 37 // For ease of reading, the test cases use strings that are converted to byte 38 // slices before invoking the functions. 39 40 var abcd = "abcd" 41 var faces = "☺☻☹" 42 var commas = "1,2,3,4" 43 var dots = "1....2....3....4" 44 45 type BinOpTest struct { 46 a string 47 b string 48 i int 49 } 50 51 func TestEqual(t *testing.T) { 52 for _, tt := range compareTests { 53 eql := Equal(tt.a, tt.b) 54 if eql != (tt.i == 0) { 55 t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql) 56 } 57 eql = EqualPortable(tt.a, tt.b) 58 if eql != (tt.i == 0) { 59 t.Errorf(`EqualPortable(%q, %q) = %v`, tt.a, tt.b, eql) 60 } 61 } 62 } 63 64 func TestEqualExhaustive(t *testing.T) { 65 var size = 128 66 if testing.Short() { 67 size = 32 68 } 69 a := make([]byte, size) 70 b := make([]byte, size) 71 b_init := make([]byte, size) 72 // randomish but deterministic data 73 for i := 0; i < size; i++ { 74 a[i] = byte(17 * i) 75 b_init[i] = byte(23*i + 100) 76 } 77 78 for len := 0; len <= size; len++ { 79 for x := 0; x <= size-len; x++ { 80 for y := 0; y <= size-len; y++ { 81 copy(b, b_init) 82 copy(b[y:y+len], a[x:x+len]) 83 if !Equal(a[x:x+len], b[y:y+len]) || !Equal(b[y:y+len], a[x:x+len]) { 84 t.Errorf("Equal(%d, %d, %d) = false", len, x, y) 85 } 86 } 87 } 88 } 89 } 90 91 // make sure Equal returns false for minimally different strings. The data 92 // is all zeros except for a single one in one location. 93 func TestNotEqual(t *testing.T) { 94 var size = 128 95 if testing.Short() { 96 size = 32 97 } 98 a := make([]byte, size) 99 b := make([]byte, size) 100 101 for len := 0; len <= size; len++ { 102 for x := 0; x <= size-len; x++ { 103 for y := 0; y <= size-len; y++ { 104 for diffpos := x; diffpos < x+len; diffpos++ { 105 a[diffpos] = 1 106 if Equal(a[x:x+len], b[y:y+len]) || Equal(b[y:y+len], a[x:x+len]) { 107 t.Errorf("NotEqual(%d, %d, %d, %d) = true", len, x, y, diffpos) 108 } 109 a[diffpos] = 0 110 } 111 } 112 } 113 } 114 } 115 116 var indexTests = []BinOpTest{ 117 {"", "", 0}, 118 {"", "a", -1}, 119 {"", "foo", -1}, 120 {"fo", "foo", -1}, 121 {"foo", "baz", -1}, 122 {"foo", "foo", 0}, 123 {"oofofoofooo", "f", 2}, 124 {"oofofoofooo", "foo", 4}, 125 {"barfoobarfoo", "foo", 3}, 126 {"foo", "", 0}, 127 {"foo", "o", 1}, 128 {"abcABCabc", "A", 3}, 129 // cases with one byte strings - test IndexByte and special case in Index() 130 {"", "a", -1}, 131 {"x", "a", -1}, 132 {"x", "x", 0}, 133 {"abc", "a", 0}, 134 {"abc", "b", 1}, 135 {"abc", "c", 2}, 136 {"abc", "x", -1}, 137 {"barfoobarfooyyyzzzyyyzzzyyyzzzyyyxxxzzzyyy", "x", 33}, 138 {"foofyfoobarfoobar", "y", 4}, 139 {"oooooooooooooooooooooo", "r", -1}, 140 } 141 142 var lastIndexTests = []BinOpTest{ 143 {"", "", 0}, 144 {"", "a", -1}, 145 {"", "foo", -1}, 146 {"fo", "foo", -1}, 147 {"foo", "foo", 0}, 148 {"foo", "f", 0}, 149 {"oofofoofooo", "f", 7}, 150 {"oofofoofooo", "foo", 7}, 151 {"barfoobarfoo", "foo", 9}, 152 {"foo", "", 3}, 153 {"foo", "o", 2}, 154 {"abcABCabc", "A", 3}, 155 {"abcABCabc", "a", 6}, 156 } 157 158 var indexAnyTests = []BinOpTest{ 159 {"", "", -1}, 160 {"", "a", -1}, 161 {"", "abc", -1}, 162 {"a", "", -1}, 163 {"a", "a", 0}, 164 {"aaa", "a", 0}, 165 {"abc", "xyz", -1}, 166 {"abc", "xcz", 2}, 167 {"ab☺c", "x☺yz", 2}, 168 {"aRegExp*", ".(|)*+?^$[]", 7}, 169 {dots + dots + dots, " ", -1}, 170 } 171 172 var lastIndexAnyTests = []BinOpTest{ 173 {"", "", -1}, 174 {"", "a", -1}, 175 {"", "abc", -1}, 176 {"a", "", -1}, 177 {"a", "a", 0}, 178 {"aaa", "a", 2}, 179 {"abc", "xyz", -1}, 180 {"abc", "ab", 1}, 181 {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")}, 182 {"a.RegExp*", ".(|)*+?^$[]", 8}, 183 {dots + dots + dots, " ", -1}, 184 } 185 186 var indexRuneTests = []BinOpTest{ 187 {"", "a", -1}, 188 {"", "☺", -1}, 189 {"foo", "☹", -1}, 190 {"foo", "o", 1}, 191 {"foo☺bar", "☺", 3}, 192 {"foo☺☻☹bar", "☹", 9}, 193 } 194 195 // Execute f on each test case. funcName should be the name of f; it's used 196 // in failure reports. 197 func runIndexTests(t *testing.T, f func(s, sep []byte) int, funcName string, testCases []BinOpTest) { 198 for _, test := range testCases { 199 a := []byte(test.a) 200 b := []byte(test.b) 201 actual := f(a, b) 202 if actual != test.i { 203 t.Errorf("%s(%q,%q) = %v; want %v", funcName, a, b, actual, test.i) 204 } 205 } 206 } 207 208 func runIndexAnyTests(t *testing.T, f func(s []byte, chars string) int, funcName string, testCases []BinOpTest) { 209 for _, test := range testCases { 210 a := []byte(test.a) 211 actual := f(a, test.b) 212 if actual != test.i { 213 t.Errorf("%s(%q,%q) = %v; want %v", funcName, a, test.b, actual, test.i) 214 } 215 } 216 } 217 218 func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) } 219 func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) } 220 func TestIndexAny(t *testing.T) { runIndexAnyTests(t, IndexAny, "IndexAny", indexAnyTests) } 221 func TestLastIndexAny(t *testing.T) { 222 runIndexAnyTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests) 223 } 224 225 func TestIndexByte(t *testing.T) { 226 for _, tt := range indexTests { 227 if len(tt.b) != 1 { 228 continue 229 } 230 a := []byte(tt.a) 231 b := tt.b[0] 232 pos := IndexByte(a, b) 233 if pos != tt.i { 234 t.Errorf(`IndexByte(%q, '%c') = %v`, tt.a, b, pos) 235 } 236 posp := IndexBytePortable(a, b) 237 if posp != tt.i { 238 t.Errorf(`indexBytePortable(%q, '%c') = %v`, tt.a, b, posp) 239 } 240 } 241 } 242 243 func TestLastIndexByte(t *testing.T) { 244 testCases := []BinOpTest{ 245 {"", "q", -1}, 246 {"abcdef", "q", -1}, 247 {"abcdefabcdef", "a", len("abcdef")}, // something in the middle 248 {"abcdefabcdef", "f", len("abcdefabcde")}, // last byte 249 {"zabcdefabcdef", "z", 0}, // first byte 250 {"a☺b☻c☹d", "b", len("a☺")}, // non-ascii 251 } 252 for _, test := range testCases { 253 actual := LastIndexByte([]byte(test.a), test.b[0]) 254 if actual != test.i { 255 t.Errorf("LastIndexByte(%q,%c) = %v; want %v", test.a, test.b[0], actual, test.i) 256 } 257 } 258 } 259 260 // test a larger buffer with different sizes and alignments 261 func TestIndexByteBig(t *testing.T) { 262 var n = 1024 263 if testing.Short() { 264 n = 128 265 } 266 b := make([]byte, n) 267 for i := 0; i < n; i++ { 268 // different start alignments 269 b1 := b[i:] 270 for j := 0; j < len(b1); j++ { 271 b1[j] = 'x' 272 pos := IndexByte(b1, 'x') 273 if pos != j { 274 t.Errorf("IndexByte(%q, 'x') = %v", b1, pos) 275 } 276 b1[j] = 0 277 pos = IndexByte(b1, 'x') 278 if pos != -1 { 279 t.Errorf("IndexByte(%q, 'x') = %v", b1, pos) 280 } 281 } 282 // different end alignments 283 b1 = b[:i] 284 for j := 0; j < len(b1); j++ { 285 b1[j] = 'x' 286 pos := IndexByte(b1, 'x') 287 if pos != j { 288 t.Errorf("IndexByte(%q, 'x') = %v", b1, pos) 289 } 290 b1[j] = 0 291 pos = IndexByte(b1, 'x') 292 if pos != -1 { 293 t.Errorf("IndexByte(%q, 'x') = %v", b1, pos) 294 } 295 } 296 // different start and end alignments 297 b1 = b[i/2 : n-(i+1)/2] 298 for j := 0; j < len(b1); j++ { 299 b1[j] = 'x' 300 pos := IndexByte(b1, 'x') 301 if pos != j { 302 t.Errorf("IndexByte(%q, 'x') = %v", b1, pos) 303 } 304 b1[j] = 0 305 pos = IndexByte(b1, 'x') 306 if pos != -1 { 307 t.Errorf("IndexByte(%q, 'x') = %v", b1, pos) 308 } 309 } 310 } 311 } 312 313 // test a small index across all page offsets 314 func TestIndexByteSmall(t *testing.T) { 315 b := make([]byte, 5015) // bigger than a page 316 // Make sure we find the correct byte even when straddling a page. 317 for i := 0; i <= len(b)-15; i++ { 318 for j := 0; j < 15; j++ { 319 b[i+j] = byte(100 + j) 320 } 321 for j := 0; j < 15; j++ { 322 p := IndexByte(b[i:i+15], byte(100+j)) 323 if p != j { 324 t.Errorf("IndexByte(%q, %d) = %d", b[i:i+15], 100+j, p) 325 } 326 } 327 for j := 0; j < 15; j++ { 328 b[i+j] = 0 329 } 330 } 331 // Make sure matches outside the slice never trigger. 332 for i := 0; i <= len(b)-15; i++ { 333 for j := 0; j < 15; j++ { 334 b[i+j] = 1 335 } 336 for j := 0; j < 15; j++ { 337 p := IndexByte(b[i:i+15], byte(0)) 338 if p != -1 { 339 t.Errorf("IndexByte(%q, %d) = %d", b[i:i+15], 0, p) 340 } 341 } 342 for j := 0; j < 15; j++ { 343 b[i+j] = 0 344 } 345 } 346 } 347 348 func TestIndexRune(t *testing.T) { 349 for _, tt := range indexRuneTests { 350 a := []byte(tt.a) 351 r, _ := utf8.DecodeRuneInString(tt.b) 352 pos := IndexRune(a, r) 353 if pos != tt.i { 354 t.Errorf(`IndexRune(%q, '%c') = %v`, tt.a, r, pos) 355 } 356 } 357 } 358 359 var bmbuf []byte 360 361 func valName(x int) string { 362 if s := x >> 20; s<<20 == x { 363 return fmt.Sprintf("%dM", s) 364 } 365 if s := x >> 10; s<<10 == x { 366 return fmt.Sprintf("%dK", s) 367 } 368 return fmt.Sprint(x) 369 } 370 371 func benchBytes(b *testing.B, sizes []int, f func(b *testing.B, n int)) { 372 for _, n := range sizes { 373 b.Run(valName(n), func(b *testing.B) { 374 if len(bmbuf) < n { 375 bmbuf = make([]byte, n) 376 } 377 b.SetBytes(int64(n)) 378 f(b, n) 379 }) 380 } 381 } 382 383 var indexSizes = []int{10, 32, 4 << 10, 4 << 20, 64 << 20} 384 385 func BenchmarkIndexByte(b *testing.B) { 386 benchBytes(b, indexSizes, bmIndexByte(IndexByte)) 387 } 388 389 func BenchmarkIndexBytePortable(b *testing.B) { 390 benchBytes(b, indexSizes, bmIndexByte(IndexBytePortable)) 391 } 392 393 func bmIndexByte(index func([]byte, byte) int) func(b *testing.B, n int) { 394 return func(b *testing.B, n int) { 395 buf := bmbuf[0:n] 396 buf[n-1] = 'x' 397 for i := 0; i < b.N; i++ { 398 j := index(buf, 'x') 399 if j != n-1 { 400 b.Fatal("bad index", j) 401 } 402 } 403 buf[n-1] = '\x00' 404 } 405 } 406 407 func BenchmarkEqual(b *testing.B) { 408 b.Run("0", func(b *testing.B) { 409 var buf [4]byte 410 buf1 := buf[0:0] 411 buf2 := buf[1:1] 412 for i := 0; i < b.N; i++ { 413 eq := Equal(buf1, buf2) 414 if !eq { 415 b.Fatal("bad equal") 416 } 417 } 418 }) 419 420 sizes := []int{1, 6, 9, 15, 16, 20, 32, 4 << 10, 4 << 20, 64 << 20} 421 benchBytes(b, sizes, bmEqual(Equal)) 422 } 423 424 func BenchmarkEqualPort(b *testing.B) { 425 sizes := []int{1, 6, 32, 4 << 10, 4 << 20, 64 << 20} 426 benchBytes(b, sizes, bmEqual(EqualPortable)) 427 } 428 429 func bmEqual(equal func([]byte, []byte) bool) func(b *testing.B, n int) { 430 return func(b *testing.B, n int) { 431 if len(bmbuf) < 2*n { 432 bmbuf = make([]byte, 2*n) 433 } 434 buf1 := bmbuf[0:n] 435 buf2 := bmbuf[n : 2*n] 436 buf1[n-1] = 'x' 437 buf2[n-1] = 'x' 438 for i := 0; i < b.N; i++ { 439 eq := equal(buf1, buf2) 440 if !eq { 441 b.Fatal("bad equal") 442 } 443 } 444 buf1[n-1] = '\x00' 445 buf2[n-1] = '\x00' 446 } 447 } 448 449 func BenchmarkIndex(b *testing.B) { 450 benchBytes(b, indexSizes, func(b *testing.B, n int) { 451 buf := bmbuf[0:n] 452 buf[n-1] = 'x' 453 for i := 0; i < b.N; i++ { 454 j := Index(buf, buf[n-7:]) 455 if j != n-7 { 456 b.Fatal("bad index", j) 457 } 458 } 459 buf[n-1] = '\x00' 460 }) 461 } 462 463 func BenchmarkIndexEasy(b *testing.B) { 464 benchBytes(b, indexSizes, func(b *testing.B, n int) { 465 buf := bmbuf[0:n] 466 buf[n-1] = 'x' 467 buf[n-7] = 'x' 468 for i := 0; i < b.N; i++ { 469 j := Index(buf, buf[n-7:]) 470 if j != n-7 { 471 b.Fatal("bad index", j) 472 } 473 } 474 buf[n-1] = '\x00' 475 buf[n-7] = '\x00' 476 }) 477 } 478 479 func BenchmarkCount(b *testing.B) { 480 benchBytes(b, indexSizes, func(b *testing.B, n int) { 481 buf := bmbuf[0:n] 482 buf[n-1] = 'x' 483 for i := 0; i < b.N; i++ { 484 j := Count(buf, buf[n-7:]) 485 if j != 1 { 486 b.Fatal("bad count", j) 487 } 488 } 489 buf[n-1] = '\x00' 490 }) 491 } 492 493 func BenchmarkCountEasy(b *testing.B) { 494 benchBytes(b, indexSizes, func(b *testing.B, n int) { 495 buf := bmbuf[0:n] 496 buf[n-1] = 'x' 497 buf[n-7] = 'x' 498 for i := 0; i < b.N; i++ { 499 j := Count(buf, buf[n-7:]) 500 if j != 1 { 501 b.Fatal("bad count", j) 502 } 503 } 504 buf[n-1] = '\x00' 505 buf[n-7] = '\x00' 506 }) 507 } 508 509 type ExplodeTest struct { 510 s string 511 n int 512 a []string 513 } 514 515 var explodetests = []ExplodeTest{ 516 {"", -1, []string{}}, 517 {abcd, -1, []string{"a", "b", "c", "d"}}, 518 {faces, -1, []string{"☺", "☻", "☹"}}, 519 {abcd, 2, []string{"a", "bcd"}}, 520 } 521 522 func TestExplode(t *testing.T) { 523 for _, tt := range explodetests { 524 a := SplitN([]byte(tt.s), nil, tt.n) 525 result := sliceOfString(a) 526 if !eq(result, tt.a) { 527 t.Errorf(`Explode("%s", %d) = %v; want %v`, tt.s, tt.n, result, tt.a) 528 continue 529 } 530 s := Join(a, []byte{}) 531 if string(s) != tt.s { 532 t.Errorf(`Join(Explode("%s", %d), "") = "%s"`, tt.s, tt.n, s) 533 } 534 } 535 } 536 537 type SplitTest struct { 538 s string 539 sep string 540 n int 541 a []string 542 } 543 544 var splittests = []SplitTest{ 545 {abcd, "a", 0, nil}, 546 {abcd, "a", -1, []string{"", "bcd"}}, 547 {abcd, "z", -1, []string{"abcd"}}, 548 {abcd, "", -1, []string{"a", "b", "c", "d"}}, 549 {commas, ",", -1, []string{"1", "2", "3", "4"}}, 550 {dots, "...", -1, []string{"1", ".2", ".3", ".4"}}, 551 {faces, "☹", -1, []string{"☺☻", ""}}, 552 {faces, "~", -1, []string{faces}}, 553 {faces, "", -1, []string{"☺", "☻", "☹"}}, 554 {"1 2 3 4", " ", 3, []string{"1", "2", "3 4"}}, 555 {"1 2", " ", 3, []string{"1", "2"}}, 556 {"123", "", 2, []string{"1", "23"}}, 557 {"123", "", 17, []string{"1", "2", "3"}}, 558 } 559 560 func TestSplit(t *testing.T) { 561 for _, tt := range splittests { 562 a := SplitN([]byte(tt.s), []byte(tt.sep), tt.n) 563 result := sliceOfString(a) 564 if !eq(result, tt.a) { 565 t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a) 566 continue 567 } 568 if tt.n == 0 { 569 continue 570 } 571 s := Join(a, []byte(tt.sep)) 572 if string(s) != tt.s { 573 t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s) 574 } 575 if tt.n < 0 { 576 b := Split([]byte(tt.s), []byte(tt.sep)) 577 if !reflect.DeepEqual(a, b) { 578 t.Errorf("Split disagrees withSplitN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a) 579 } 580 } 581 if len(a) > 0 { 582 in, out := a[0], s 583 if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] { 584 t.Errorf("Join(%#v, %q) didn't copy", a, tt.sep) 585 } 586 } 587 } 588 } 589 590 var splitaftertests = []SplitTest{ 591 {abcd, "a", -1, []string{"a", "bcd"}}, 592 {abcd, "z", -1, []string{"abcd"}}, 593 {abcd, "", -1, []string{"a", "b", "c", "d"}}, 594 {commas, ",", -1, []string{"1,", "2,", "3,", "4"}}, 595 {dots, "...", -1, []string{"1...", ".2...", ".3...", ".4"}}, 596 {faces, "☹", -1, []string{"☺☻☹", ""}}, 597 {faces, "~", -1, []string{faces}}, 598 {faces, "", -1, []string{"☺", "☻", "☹"}}, 599 {"1 2 3 4", " ", 3, []string{"1 ", "2 ", "3 4"}}, 600 {"1 2 3", " ", 3, []string{"1 ", "2 ", "3"}}, 601 {"1 2", " ", 3, []string{"1 ", "2"}}, 602 {"123", "", 2, []string{"1", "23"}}, 603 {"123", "", 17, []string{"1", "2", "3"}}, 604 } 605 606 func TestSplitAfter(t *testing.T) { 607 for _, tt := range splitaftertests { 608 a := SplitAfterN([]byte(tt.s), []byte(tt.sep), tt.n) 609 result := sliceOfString(a) 610 if !eq(result, tt.a) { 611 t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a) 612 continue 613 } 614 s := Join(a, nil) 615 if string(s) != tt.s { 616 t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s) 617 } 618 if tt.n < 0 { 619 b := SplitAfter([]byte(tt.s), []byte(tt.sep)) 620 if !reflect.DeepEqual(a, b) { 621 t.Errorf("SplitAfter disagrees withSplitAfterN(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, b, a) 622 } 623 } 624 } 625 } 626 627 type FieldsTest struct { 628 s string 629 a []string 630 } 631 632 var fieldstests = []FieldsTest{ 633 {"", []string{}}, 634 {" ", []string{}}, 635 {" \t ", []string{}}, 636 {" abc ", []string{"abc"}}, 637 {"1 2 3 4", []string{"1", "2", "3", "4"}}, 638 {"1 2 3 4", []string{"1", "2", "3", "4"}}, 639 {"1\t\t2\t\t3\t4", []string{"1", "2", "3", "4"}}, 640 {"1\u20002\u20013\u20024", []string{"1", "2", "3", "4"}}, 641 {"\u2000\u2001\u2002", []string{}}, 642 {"\n™\t™\n", []string{"™", "™"}}, 643 {faces, []string{faces}}, 644 } 645 646 func TestFields(t *testing.T) { 647 for _, tt := range fieldstests { 648 a := Fields([]byte(tt.s)) 649 result := sliceOfString(a) 650 if !eq(result, tt.a) { 651 t.Errorf("Fields(%q) = %v; want %v", tt.s, a, tt.a) 652 continue 653 } 654 } 655 } 656 657 func TestFieldsFunc(t *testing.T) { 658 for _, tt := range fieldstests { 659 a := FieldsFunc([]byte(tt.s), unicode.IsSpace) 660 result := sliceOfString(a) 661 if !eq(result, tt.a) { 662 t.Errorf("FieldsFunc(%q, unicode.IsSpace) = %v; want %v", tt.s, a, tt.a) 663 continue 664 } 665 } 666 pred := func(c rune) bool { return c == 'X' } 667 var fieldsFuncTests = []FieldsTest{ 668 {"", []string{}}, 669 {"XX", []string{}}, 670 {"XXhiXXX", []string{"hi"}}, 671 {"aXXbXXXcX", []string{"a", "b", "c"}}, 672 } 673 for _, tt := range fieldsFuncTests { 674 a := FieldsFunc([]byte(tt.s), pred) 675 result := sliceOfString(a) 676 if !eq(result, tt.a) { 677 t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a) 678 } 679 } 680 } 681 682 // Test case for any function which accepts and returns a byte slice. 683 // For ease of creation, we write the byte slices as strings. 684 type StringTest struct { 685 in, out string 686 } 687 688 var upperTests = []StringTest{ 689 {"", ""}, 690 {"abc", "ABC"}, 691 {"AbC123", "ABC123"}, 692 {"azAZ09_", "AZAZ09_"}, 693 {"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char 694 } 695 696 var lowerTests = []StringTest{ 697 {"", ""}, 698 {"abc", "abc"}, 699 {"AbC123", "abc123"}, 700 {"azAZ09_", "azaz09_"}, 701 {"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char 702 } 703 704 const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000" 705 706 var trimSpaceTests = []StringTest{ 707 {"", ""}, 708 {"abc", "abc"}, 709 {space + "abc" + space, "abc"}, 710 {" ", ""}, 711 {" \t\r\n \t\t\r\r\n\n ", ""}, 712 {" \t\r\n x\t\t\r\r\n\n ", "x"}, 713 {" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"}, 714 {"1 \t\r\n2", "1 \t\r\n2"}, 715 {" x\x80", "x\x80"}, 716 {" x\xc0", "x\xc0"}, 717 {"x \xc0\xc0 ", "x \xc0\xc0"}, 718 {"x \xc0", "x \xc0"}, 719 {"x \xc0 ", "x \xc0"}, 720 {"x \xc0\xc0 ", "x \xc0\xc0"}, 721 {"x ☺\xc0\xc0 ", "x ☺\xc0\xc0"}, 722 {"x ☺ ", "x ☺"}, 723 } 724 725 // Execute f on each test case. funcName should be the name of f; it's used 726 // in failure reports. 727 func runStringTests(t *testing.T, f func([]byte) []byte, funcName string, testCases []StringTest) { 728 for _, tc := range testCases { 729 actual := string(f([]byte(tc.in))) 730 if actual != tc.out { 731 t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out) 732 } 733 } 734 } 735 736 func tenRunes(r rune) string { 737 runes := make([]rune, 10) 738 for i := range runes { 739 runes[i] = r 740 } 741 return string(runes) 742 } 743 744 // User-defined self-inverse mapping function 745 func rot13(r rune) rune { 746 const step = 13 747 if r >= 'a' && r <= 'z' { 748 return ((r - 'a' + step) % 26) + 'a' 749 } 750 if r >= 'A' && r <= 'Z' { 751 return ((r - 'A' + step) % 26) + 'A' 752 } 753 return r 754 } 755 756 func TestMap(t *testing.T) { 757 // Run a couple of awful growth/shrinkage tests 758 a := tenRunes('a') 759 760 // 1. Grow. This triggers two reallocations in Map. 761 maxRune := func(r rune) rune { return unicode.MaxRune } 762 m := Map(maxRune, []byte(a)) 763 expect := tenRunes(unicode.MaxRune) 764 if string(m) != expect { 765 t.Errorf("growing: expected %q got %q", expect, m) 766 } 767 768 // 2. Shrink 769 minRune := func(r rune) rune { return 'a' } 770 m = Map(minRune, []byte(tenRunes(unicode.MaxRune))) 771 expect = a 772 if string(m) != expect { 773 t.Errorf("shrinking: expected %q got %q", expect, m) 774 } 775 776 // 3. Rot13 777 m = Map(rot13, []byte("a to zed")) 778 expect = "n gb mrq" 779 if string(m) != expect { 780 t.Errorf("rot13: expected %q got %q", expect, m) 781 } 782 783 // 4. Rot13^2 784 m = Map(rot13, Map(rot13, []byte("a to zed"))) 785 expect = "a to zed" 786 if string(m) != expect { 787 t.Errorf("rot13: expected %q got %q", expect, m) 788 } 789 790 // 5. Drop 791 dropNotLatin := func(r rune) rune { 792 if unicode.Is(unicode.Latin, r) { 793 return r 794 } 795 return -1 796 } 797 m = Map(dropNotLatin, []byte("Hello, 세계")) 798 expect = "Hello" 799 if string(m) != expect { 800 t.Errorf("drop: expected %q got %q", expect, m) 801 } 802 803 // 6. Invalid rune 804 invalidRune := func(r rune) rune { 805 return utf8.MaxRune + 1 806 } 807 m = Map(invalidRune, []byte("x")) 808 expect = "\uFFFD" 809 if string(m) != expect { 810 t.Errorf("invalidRune: expected %q got %q", expect, m) 811 } 812 } 813 814 func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) } 815 816 func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) } 817 818 func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) } 819 820 type RepeatTest struct { 821 in, out string 822 count int 823 } 824 825 var RepeatTests = []RepeatTest{ 826 {"", "", 0}, 827 {"", "", 1}, 828 {"", "", 2}, 829 {"-", "", 0}, 830 {"-", "-", 1}, 831 {"-", "----------", 10}, 832 {"abc ", "abc abc abc ", 3}, 833 } 834 835 func TestRepeat(t *testing.T) { 836 for _, tt := range RepeatTests { 837 tin := []byte(tt.in) 838 tout := []byte(tt.out) 839 a := Repeat(tin, tt.count) 840 if !Equal(a, tout) { 841 t.Errorf("Repeat(%q, %d) = %q; want %q", tin, tt.count, a, tout) 842 continue 843 } 844 } 845 } 846 847 func runesEqual(a, b []rune) bool { 848 if len(a) != len(b) { 849 return false 850 } 851 for i, r := range a { 852 if r != b[i] { 853 return false 854 } 855 } 856 return true 857 } 858 859 type RunesTest struct { 860 in string 861 out []rune 862 lossy bool 863 } 864 865 var RunesTests = []RunesTest{ 866 {"", []rune{}, false}, 867 {" ", []rune{32}, false}, 868 {"ABC", []rune{65, 66, 67}, false}, 869 {"abc", []rune{97, 98, 99}, false}, 870 {"\u65e5\u672c\u8a9e", []rune{26085, 26412, 35486}, false}, 871 {"ab\x80c", []rune{97, 98, 0xFFFD, 99}, true}, 872 {"ab\xc0c", []rune{97, 98, 0xFFFD, 99}, true}, 873 } 874 875 func TestRunes(t *testing.T) { 876 for _, tt := range RunesTests { 877 tin := []byte(tt.in) 878 a := Runes(tin) 879 if !runesEqual(a, tt.out) { 880 t.Errorf("Runes(%q) = %v; want %v", tin, a, tt.out) 881 continue 882 } 883 if !tt.lossy { 884 // can only test reassembly if we didn't lose information 885 s := string(a) 886 if s != tt.in { 887 t.Errorf("string(Runes(%q)) = %x; want %x", tin, s, tin) 888 } 889 } 890 } 891 } 892 893 type TrimTest struct { 894 f string 895 in, arg, out string 896 } 897 898 var trimTests = []TrimTest{ 899 {"Trim", "abba", "a", "bb"}, 900 {"Trim", "abba", "ab", ""}, 901 {"TrimLeft", "abba", "ab", ""}, 902 {"TrimRight", "abba", "ab", ""}, 903 {"TrimLeft", "abba", "a", "bba"}, 904 {"TrimRight", "abba", "a", "abb"}, 905 {"Trim", "<tag>", "<>", "tag"}, 906 {"Trim", "* listitem", " *", "listitem"}, 907 {"Trim", `"quote"`, `"`, "quote"}, 908 {"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"}, 909 //empty string tests 910 {"Trim", "abba", "", "abba"}, 911 {"Trim", "", "123", ""}, 912 {"Trim", "", "", ""}, 913 {"TrimLeft", "abba", "", "abba"}, 914 {"TrimLeft", "", "123", ""}, 915 {"TrimLeft", "", "", ""}, 916 {"TrimRight", "abba", "", "abba"}, 917 {"TrimRight", "", "123", ""}, 918 {"TrimRight", "", "", ""}, 919 {"TrimRight", "☺\xc0", "☺", "☺\xc0"}, 920 {"TrimPrefix", "aabb", "a", "abb"}, 921 {"TrimPrefix", "aabb", "b", "aabb"}, 922 {"TrimSuffix", "aabb", "a", "aabb"}, 923 {"TrimSuffix", "aabb", "b", "aab"}, 924 } 925 926 func TestTrim(t *testing.T) { 927 for _, tc := range trimTests { 928 name := tc.f 929 var f func([]byte, string) []byte 930 var fb func([]byte, []byte) []byte 931 switch name { 932 case "Trim": 933 f = Trim 934 case "TrimLeft": 935 f = TrimLeft 936 case "TrimRight": 937 f = TrimRight 938 case "TrimPrefix": 939 fb = TrimPrefix 940 case "TrimSuffix": 941 fb = TrimSuffix 942 default: 943 t.Errorf("Undefined trim function %s", name) 944 } 945 var actual string 946 if f != nil { 947 actual = string(f([]byte(tc.in), tc.arg)) 948 } else { 949 actual = string(fb([]byte(tc.in), []byte(tc.arg))) 950 } 951 if actual != tc.out { 952 t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out) 953 } 954 } 955 } 956 957 type predicate struct { 958 f func(r rune) bool 959 name string 960 } 961 962 var isSpace = predicate{unicode.IsSpace, "IsSpace"} 963 var isDigit = predicate{unicode.IsDigit, "IsDigit"} 964 var isUpper = predicate{unicode.IsUpper, "IsUpper"} 965 var isValidRune = predicate{ 966 func(r rune) bool { 967 return r != utf8.RuneError 968 }, 969 "IsValidRune", 970 } 971 972 type TrimFuncTest struct { 973 f predicate 974 in, out string 975 } 976 977 func not(p predicate) predicate { 978 return predicate{ 979 func(r rune) bool { 980 return !p.f(r) 981 }, 982 "not " + p.name, 983 } 984 } 985 986 var trimFuncTests = []TrimFuncTest{ 987 {isSpace, space + " hello " + space, "hello"}, 988 {isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"}, 989 {isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"}, 990 {not(isSpace), "hello" + space + "hello", space}, 991 {not(isDigit), "hello\u0e50\u0e521234\u0e50\u0e51helo", "\u0e50\u0e521234\u0e50\u0e51"}, 992 {isValidRune, "ab\xc0a\xc0cd", "\xc0a\xc0"}, 993 {not(isValidRune), "\xc0a\xc0", "a"}, 994 } 995 996 func TestTrimFunc(t *testing.T) { 997 for _, tc := range trimFuncTests { 998 actual := string(TrimFunc([]byte(tc.in), tc.f.f)) 999 if actual != tc.out { 1000 t.Errorf("TrimFunc(%q, %q) = %q; want %q", tc.in, tc.f.name, actual, tc.out) 1001 } 1002 } 1003 } 1004 1005 type IndexFuncTest struct { 1006 in string 1007 f predicate 1008 first, last int 1009 } 1010 1011 var indexFuncTests = []IndexFuncTest{ 1012 {"", isValidRune, -1, -1}, 1013 {"abc", isDigit, -1, -1}, 1014 {"0123", isDigit, 0, 3}, 1015 {"a1b", isDigit, 1, 1}, 1016 {space, isSpace, 0, len(space) - 3}, // last rune in space is 3 bytes 1017 {"\u0e50\u0e5212hello34\u0e50\u0e51", isDigit, 0, 18}, 1018 {"\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", isUpper, 0, 34}, 1019 {"12\u0e50\u0e52hello34\u0e50\u0e51", not(isDigit), 8, 12}, 1020 1021 // tests of invalid UTF-8 1022 {"\x801", isDigit, 1, 1}, 1023 {"\x80abc", isDigit, -1, -1}, 1024 {"\xc0a\xc0", isValidRune, 1, 1}, 1025 {"\xc0a\xc0", not(isValidRune), 0, 2}, 1026 {"\xc0☺\xc0", not(isValidRune), 0, 4}, 1027 {"\xc0☺\xc0\xc0", not(isValidRune), 0, 5}, 1028 {"ab\xc0a\xc0cd", not(isValidRune), 2, 4}, 1029 {"a\xe0\x80cd", not(isValidRune), 1, 2}, 1030 } 1031 1032 func TestIndexFunc(t *testing.T) { 1033 for _, tc := range indexFuncTests { 1034 first := IndexFunc([]byte(tc.in), tc.f.f) 1035 if first != tc.first { 1036 t.Errorf("IndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, first, tc.first) 1037 } 1038 last := LastIndexFunc([]byte(tc.in), tc.f.f) 1039 if last != tc.last { 1040 t.Errorf("LastIndexFunc(%q, %s) = %d; want %d", tc.in, tc.f.name, last, tc.last) 1041 } 1042 } 1043 } 1044 1045 type ReplaceTest struct { 1046 in string 1047 old, new string 1048 n int 1049 out string 1050 } 1051 1052 var ReplaceTests = []ReplaceTest{ 1053 {"hello", "l", "L", 0, "hello"}, 1054 {"hello", "l", "L", -1, "heLLo"}, 1055 {"hello", "x", "X", -1, "hello"}, 1056 {"", "x", "X", -1, ""}, 1057 {"radar", "r", "<r>", -1, "<r>ada<r>"}, 1058 {"", "", "<>", -1, "<>"}, 1059 {"banana", "a", "<>", -1, "b<>n<>n<>"}, 1060 {"banana", "a", "<>", 1, "b<>nana"}, 1061 {"banana", "a", "<>", 1000, "b<>n<>n<>"}, 1062 {"banana", "an", "<>", -1, "b<><>a"}, 1063 {"banana", "ana", "<>", -1, "b<>na"}, 1064 {"banana", "", "<>", -1, "<>b<>a<>n<>a<>n<>a<>"}, 1065 {"banana", "", "<>", 10, "<>b<>a<>n<>a<>n<>a<>"}, 1066 {"banana", "", "<>", 6, "<>b<>a<>n<>a<>n<>a"}, 1067 {"banana", "", "<>", 5, "<>b<>a<>n<>a<>na"}, 1068 {"banana", "", "<>", 1, "<>banana"}, 1069 {"banana", "a", "a", -1, "banana"}, 1070 {"banana", "a", "a", 1, "banana"}, 1071 {"☺☻☹", "", "<>", -1, "<>☺<>☻<>☹<>"}, 1072 } 1073 1074 func TestReplace(t *testing.T) { 1075 for _, tt := range ReplaceTests { 1076 in := append([]byte(tt.in), "<spare>"...) 1077 in = in[:len(tt.in)] 1078 out := Replace(in, []byte(tt.old), []byte(tt.new), tt.n) 1079 if s := string(out); s != tt.out { 1080 t.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt.in, tt.old, tt.new, tt.n, s, tt.out) 1081 } 1082 if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] { 1083 t.Errorf("Replace(%q, %q, %q, %d) didn't copy", tt.in, tt.old, tt.new, tt.n) 1084 } 1085 } 1086 } 1087 1088 type TitleTest struct { 1089 in, out string 1090 } 1091 1092 var TitleTests = []TitleTest{ 1093 {"", ""}, 1094 {"a", "A"}, 1095 {" aaa aaa aaa ", " Aaa Aaa Aaa "}, 1096 {" Aaa Aaa Aaa ", " Aaa Aaa Aaa "}, 1097 {"123a456", "123a456"}, 1098 {"double-blind", "Double-Blind"}, 1099 {"ÿøû", "Ÿøû"}, 1100 {"with_underscore", "With_underscore"}, 1101 {"unicode \xe2\x80\xa8 line separator", "Unicode \xe2\x80\xa8 Line Separator"}, 1102 } 1103 1104 func TestTitle(t *testing.T) { 1105 for _, tt := range TitleTests { 1106 if s := string(Title([]byte(tt.in))); s != tt.out { 1107 t.Errorf("Title(%q) = %q, want %q", tt.in, s, tt.out) 1108 } 1109 } 1110 } 1111 1112 var ToTitleTests = []TitleTest{ 1113 {"", ""}, 1114 {"a", "A"}, 1115 {" aaa aaa aaa ", " AAA AAA AAA "}, 1116 {" Aaa Aaa Aaa ", " AAA AAA AAA "}, 1117 {"123a456", "123A456"}, 1118 {"double-blind", "DOUBLE-BLIND"}, 1119 {"ÿøû", "ŸØÛ"}, 1120 } 1121 1122 func TestToTitle(t *testing.T) { 1123 for _, tt := range ToTitleTests { 1124 if s := string(ToTitle([]byte(tt.in))); s != tt.out { 1125 t.Errorf("ToTitle(%q) = %q, want %q", tt.in, s, tt.out) 1126 } 1127 } 1128 } 1129 1130 var EqualFoldTests = []struct { 1131 s, t string 1132 out bool 1133 }{ 1134 {"abc", "abc", true}, 1135 {"ABcd", "ABcd", true}, 1136 {"123abc", "123ABC", true}, 1137 {"αβδ", "ΑΒΔ", true}, 1138 {"abc", "xyz", false}, 1139 {"abc", "XYZ", false}, 1140 {"abcdefghijk", "abcdefghijX", false}, 1141 {"abcdefghijk", "abcdefghij\u212A", true}, 1142 {"abcdefghijK", "abcdefghij\u212A", true}, 1143 {"abcdefghijkz", "abcdefghij\u212Ay", false}, 1144 {"abcdefghijKz", "abcdefghij\u212Ay", false}, 1145 } 1146 1147 func TestEqualFold(t *testing.T) { 1148 for _, tt := range EqualFoldTests { 1149 if out := EqualFold([]byte(tt.s), []byte(tt.t)); out != tt.out { 1150 t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.s, tt.t, out, tt.out) 1151 } 1152 if out := EqualFold([]byte(tt.t), []byte(tt.s)); out != tt.out { 1153 t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.t, tt.s, out, tt.out) 1154 } 1155 } 1156 } 1157 1158 func TestBufferGrowNegative(t *testing.T) { 1159 defer func() { 1160 if err := recover(); err == nil { 1161 t.Fatal("Grow(-1) should have panicked") 1162 } 1163 }() 1164 var b Buffer 1165 b.Grow(-1) 1166 } 1167 1168 func TestBufferTruncateNegative(t *testing.T) { 1169 defer func() { 1170 if err := recover(); err == nil { 1171 t.Fatal("Truncate(-1) should have panicked") 1172 } 1173 }() 1174 var b Buffer 1175 b.Truncate(-1) 1176 } 1177 1178 func TestBufferTruncateOutOfRange(t *testing.T) { 1179 defer func() { 1180 if err := recover(); err == nil { 1181 t.Fatal("Truncate(20) should have panicked") 1182 } 1183 }() 1184 var b Buffer 1185 b.Write(make([]byte, 10)) 1186 b.Truncate(20) 1187 } 1188 1189 var containsTests = []struct { 1190 b, subslice []byte 1191 want bool 1192 }{ 1193 {[]byte("hello"), []byte("hel"), true}, 1194 {[]byte("日本語"), []byte("日本"), true}, 1195 {[]byte("hello"), []byte("Hello, world"), false}, 1196 {[]byte("東京"), []byte("京東"), false}, 1197 } 1198 1199 func TestContains(t *testing.T) { 1200 for _, tt := range containsTests { 1201 if got := Contains(tt.b, tt.subslice); got != tt.want { 1202 t.Errorf("Contains(%q, %q) = %v, want %v", tt.b, tt.subslice, got, tt.want) 1203 } 1204 } 1205 } 1206 1207 var ContainsAnyTests = []struct { 1208 b []byte 1209 substr string 1210 expected bool 1211 }{ 1212 {[]byte(""), "", false}, 1213 {[]byte(""), "a", false}, 1214 {[]byte(""), "abc", false}, 1215 {[]byte("a"), "", false}, 1216 {[]byte("a"), "a", true}, 1217 {[]byte("aaa"), "a", true}, 1218 {[]byte("abc"), "xyz", false}, 1219 {[]byte("abc"), "xcz", true}, 1220 {[]byte("a☺b☻c☹d"), "uvw☻xyz", true}, 1221 {[]byte("aRegExp*"), ".(|)*+?^$[]", true}, 1222 {[]byte(dots + dots + dots), " ", false}, 1223 } 1224 1225 func TestContainsAny(t *testing.T) { 1226 for _, ct := range ContainsAnyTests { 1227 if ContainsAny(ct.b, ct.substr) != ct.expected { 1228 t.Errorf("ContainsAny(%s, %s) = %v, want %v", 1229 ct.b, ct.substr, !ct.expected, ct.expected) 1230 } 1231 } 1232 } 1233 1234 var ContainsRuneTests = []struct { 1235 b []byte 1236 r rune 1237 expected bool 1238 }{ 1239 {[]byte(""), 'a', false}, 1240 {[]byte("a"), 'a', true}, 1241 {[]byte("aaa"), 'a', true}, 1242 {[]byte("abc"), 'y', false}, 1243 {[]byte("abc"), 'c', true}, 1244 {[]byte("a☺b☻c☹d"), 'x', false}, 1245 {[]byte("a☺b☻c☹d"), '☻', true}, 1246 {[]byte("aRegExp*"), '*', true}, 1247 } 1248 1249 func TestContainsRune(t *testing.T) { 1250 for _, ct := range ContainsRuneTests { 1251 if ContainsRune(ct.b, ct.r) != ct.expected { 1252 t.Errorf("ContainsRune(%q, %q) = %v, want %v", 1253 ct.b, ct.r, !ct.expected, ct.expected) 1254 } 1255 } 1256 } 1257 1258 var makeFieldsInput = func() []byte { 1259 x := make([]byte, 1<<20) 1260 // Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space. 1261 for i := range x { 1262 switch rand.Intn(10) { 1263 case 0: 1264 x[i] = ' ' 1265 case 1: 1266 if i > 0 && x[i-1] == 'x' { 1267 copy(x[i-1:], "χ") 1268 break 1269 } 1270 fallthrough 1271 default: 1272 x[i] = 'x' 1273 } 1274 } 1275 return x 1276 } 1277 1278 var fieldsInput = makeFieldsInput() 1279 1280 func BenchmarkFields(b *testing.B) { 1281 b.SetBytes(int64(len(fieldsInput))) 1282 for i := 0; i < b.N; i++ { 1283 Fields(fieldsInput) 1284 } 1285 } 1286 1287 func BenchmarkFieldsFunc(b *testing.B) { 1288 b.SetBytes(int64(len(fieldsInput))) 1289 for i := 0; i < b.N; i++ { 1290 FieldsFunc(fieldsInput, unicode.IsSpace) 1291 } 1292 } 1293 1294 func BenchmarkTrimSpace(b *testing.B) { 1295 s := []byte(" Some text. \n") 1296 for i := 0; i < b.N; i++ { 1297 TrimSpace(s) 1298 } 1299 } 1300 1301 func BenchmarkRepeat(b *testing.B) { 1302 for i := 0; i < b.N; i++ { 1303 Repeat([]byte("-"), 80) 1304 } 1305 } 1306 1307 func BenchmarkBytesCompare(b *testing.B) { 1308 for n := 1; n <= 2048; n <<= 1 { 1309 b.Run(fmt.Sprint(n), func(b *testing.B) { 1310 var x = make([]byte, n) 1311 var y = make([]byte, n) 1312 1313 for i := 0; i < n; i++ { 1314 x[i] = 'a' 1315 } 1316 1317 for i := 0; i < n; i++ { 1318 y[i] = 'a' 1319 } 1320 1321 b.ResetTimer() 1322 for i := 0; i < b.N; i++ { 1323 Compare(x, y) 1324 } 1325 }) 1326 } 1327 }