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