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