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