github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/src/bytes/buffer_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 "internal/testenv" 10 "io" 11 "math/rand" 12 "os/exec" 13 "runtime" 14 "testing" 15 "unicode/utf8" 16 ) 17 18 const N = 10000 // make this bigger for a larger (and slower) test 19 var data string // test data for write tests 20 var testBytes []byte // test data; same as data but as a slice. 21 22 func init() { 23 testBytes = make([]byte, N) 24 for i := 0; i < N; i++ { 25 testBytes[i] = 'a' + byte(i%26) 26 } 27 data = string(testBytes) 28 } 29 30 // Verify that contents of buf match the string s. 31 func check(t *testing.T, testname string, buf *Buffer, s string) { 32 bytes := buf.Bytes() 33 str := buf.String() 34 if buf.Len() != len(bytes) { 35 t.Errorf("%s: buf.Len() == %d, len(buf.Bytes()) == %d", testname, buf.Len(), len(bytes)) 36 } 37 38 if buf.Len() != len(str) { 39 t.Errorf("%s: buf.Len() == %d, len(buf.String()) == %d", testname, buf.Len(), len(str)) 40 } 41 42 if buf.Len() != len(s) { 43 t.Errorf("%s: buf.Len() == %d, len(s) == %d", testname, buf.Len(), len(s)) 44 } 45 46 if string(bytes) != s { 47 t.Errorf("%s: string(buf.Bytes()) == %q, s == %q", testname, string(bytes), s) 48 } 49 } 50 51 // Fill buf through n writes of string fus. 52 // The initial contents of buf corresponds to the string s; 53 // the result is the final contents of buf returned as a string. 54 func fillString(t *testing.T, testname string, buf *Buffer, s string, n int, fus string) string { 55 check(t, testname+" (fill 1)", buf, s) 56 for ; n > 0; n-- { 57 m, err := buf.WriteString(fus) 58 if m != len(fus) { 59 t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fus)) 60 } 61 if err != nil { 62 t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err) 63 } 64 s += fus 65 check(t, testname+" (fill 4)", buf, s) 66 } 67 return s 68 } 69 70 // Fill buf through n writes of byte slice fub. 71 // The initial contents of buf corresponds to the string s; 72 // the result is the final contents of buf returned as a string. 73 func fillBytes(t *testing.T, testname string, buf *Buffer, s string, n int, fub []byte) string { 74 check(t, testname+" (fill 1)", buf, s) 75 for ; n > 0; n-- { 76 m, err := buf.Write(fub) 77 if m != len(fub) { 78 t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fub)) 79 } 80 if err != nil { 81 t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err) 82 } 83 s += string(fub) 84 check(t, testname+" (fill 4)", buf, s) 85 } 86 return s 87 } 88 89 func TestNewBuffer(t *testing.T) { 90 buf := NewBuffer(testBytes) 91 check(t, "NewBuffer", buf, data) 92 } 93 94 func TestNewBufferString(t *testing.T) { 95 buf := NewBufferString(data) 96 check(t, "NewBufferString", buf, data) 97 } 98 99 // Empty buf through repeated reads into fub. 100 // The initial contents of buf corresponds to the string s. 101 func empty(t *testing.T, testname string, buf *Buffer, s string, fub []byte) { 102 check(t, testname+" (empty 1)", buf, s) 103 104 for { 105 n, err := buf.Read(fub) 106 if n == 0 { 107 break 108 } 109 if err != nil { 110 t.Errorf(testname+" (empty 2): err should always be nil, found err == %s", err) 111 } 112 s = s[n:] 113 check(t, testname+" (empty 3)", buf, s) 114 } 115 116 check(t, testname+" (empty 4)", buf, "") 117 } 118 119 func TestBasicOperations(t *testing.T) { 120 var buf Buffer 121 122 for i := 0; i < 5; i++ { 123 check(t, "TestBasicOperations (1)", &buf, "") 124 125 buf.Reset() 126 check(t, "TestBasicOperations (2)", &buf, "") 127 128 buf.Truncate(0) 129 check(t, "TestBasicOperations (3)", &buf, "") 130 131 n, err := buf.Write([]byte(data[0:1])) 132 if n != 1 { 133 t.Errorf("wrote 1 byte, but n == %d", n) 134 } 135 if err != nil { 136 t.Errorf("err should always be nil, but err == %s", err) 137 } 138 check(t, "TestBasicOperations (4)", &buf, "a") 139 140 buf.WriteByte(data[1]) 141 check(t, "TestBasicOperations (5)", &buf, "ab") 142 143 n, err = buf.Write([]byte(data[2:26])) 144 if n != 24 { 145 t.Errorf("wrote 25 bytes, but n == %d", n) 146 } 147 check(t, "TestBasicOperations (6)", &buf, string(data[0:26])) 148 149 buf.Truncate(26) 150 check(t, "TestBasicOperations (7)", &buf, string(data[0:26])) 151 152 buf.Truncate(20) 153 check(t, "TestBasicOperations (8)", &buf, string(data[0:20])) 154 155 empty(t, "TestBasicOperations (9)", &buf, string(data[0:20]), make([]byte, 5)) 156 empty(t, "TestBasicOperations (10)", &buf, "", make([]byte, 100)) 157 158 buf.WriteByte(data[1]) 159 c, err := buf.ReadByte() 160 if err != nil { 161 t.Error("ReadByte unexpected eof") 162 } 163 if c != data[1] { 164 t.Errorf("ReadByte wrong value c=%v", c) 165 } 166 c, err = buf.ReadByte() 167 if err == nil { 168 t.Error("ReadByte unexpected not eof") 169 } 170 } 171 } 172 173 func TestLargeStringWrites(t *testing.T) { 174 var buf Buffer 175 limit := 30 176 if testing.Short() { 177 limit = 9 178 } 179 for i := 3; i < limit; i += 3 { 180 s := fillString(t, "TestLargeWrites (1)", &buf, "", 5, data) 181 empty(t, "TestLargeStringWrites (2)", &buf, s, make([]byte, len(data)/i)) 182 } 183 check(t, "TestLargeStringWrites (3)", &buf, "") 184 } 185 186 func TestLargeByteWrites(t *testing.T) { 187 var buf Buffer 188 limit := 30 189 if testing.Short() { 190 limit = 9 191 } 192 for i := 3; i < limit; i += 3 { 193 s := fillBytes(t, "TestLargeWrites (1)", &buf, "", 5, testBytes) 194 empty(t, "TestLargeByteWrites (2)", &buf, s, make([]byte, len(data)/i)) 195 } 196 check(t, "TestLargeByteWrites (3)", &buf, "") 197 } 198 199 func TestLargeStringReads(t *testing.T) { 200 var buf Buffer 201 for i := 3; i < 30; i += 3 { 202 s := fillString(t, "TestLargeReads (1)", &buf, "", 5, data[0:len(data)/i]) 203 empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data))) 204 } 205 check(t, "TestLargeStringReads (3)", &buf, "") 206 } 207 208 func TestLargeByteReads(t *testing.T) { 209 var buf Buffer 210 for i := 3; i < 30; i += 3 { 211 s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, testBytes[0:len(testBytes)/i]) 212 empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data))) 213 } 214 check(t, "TestLargeByteReads (3)", &buf, "") 215 } 216 217 func TestMixedReadsAndWrites(t *testing.T) { 218 var buf Buffer 219 s := "" 220 for i := 0; i < 50; i++ { 221 wlen := rand.Intn(len(data)) 222 if i%2 == 0 { 223 s = fillString(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, data[0:wlen]) 224 } else { 225 s = fillBytes(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, testBytes[0:wlen]) 226 } 227 228 rlen := rand.Intn(len(data)) 229 fub := make([]byte, rlen) 230 n, _ := buf.Read(fub) 231 s = s[n:] 232 } 233 empty(t, "TestMixedReadsAndWrites (2)", &buf, s, make([]byte, buf.Len())) 234 } 235 236 func TestCapWithPreallocatedSlice(t *testing.T) { 237 buf := NewBuffer(make([]byte, 10)) 238 n := buf.Cap() 239 if n != 10 { 240 t.Errorf("expected 10, got %d", n) 241 } 242 } 243 244 func TestCapWithSliceAndWrittenData(t *testing.T) { 245 buf := NewBuffer(make([]byte, 0, 10)) 246 buf.Write([]byte("test")) 247 n := buf.Cap() 248 if n != 10 { 249 t.Errorf("expected 10, got %d", n) 250 } 251 } 252 253 func TestNil(t *testing.T) { 254 var b *Buffer 255 if b.String() != "<nil>" { 256 t.Errorf("expected <nil>; got %q", b.String()) 257 } 258 } 259 260 func TestReadFrom(t *testing.T) { 261 var buf Buffer 262 for i := 3; i < 30; i += 3 { 263 s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, testBytes[0:len(testBytes)/i]) 264 var b Buffer 265 b.ReadFrom(&buf) 266 empty(t, "TestReadFrom (2)", &b, s, make([]byte, len(data))) 267 } 268 } 269 270 func TestWriteTo(t *testing.T) { 271 var buf Buffer 272 for i := 3; i < 30; i += 3 { 273 s := fillBytes(t, "TestWriteTo (1)", &buf, "", 5, testBytes[0:len(testBytes)/i]) 274 var b Buffer 275 buf.WriteTo(&b) 276 empty(t, "TestWriteTo (2)", &b, s, make([]byte, len(data))) 277 } 278 } 279 280 func TestRuneIO(t *testing.T) { 281 const NRune = 1000 282 // Built a test slice while we write the data 283 b := make([]byte, utf8.UTFMax*NRune) 284 var buf Buffer 285 n := 0 286 for r := rune(0); r < NRune; r++ { 287 size := utf8.EncodeRune(b[n:], r) 288 nbytes, err := buf.WriteRune(r) 289 if err != nil { 290 t.Fatalf("WriteRune(%U) error: %s", r, err) 291 } 292 if nbytes != size { 293 t.Fatalf("WriteRune(%U) expected %d, got %d", r, size, nbytes) 294 } 295 n += size 296 } 297 b = b[0:n] 298 299 // Check the resulting bytes 300 if !Equal(buf.Bytes(), b) { 301 t.Fatalf("incorrect result from WriteRune: %q not %q", buf.Bytes(), b) 302 } 303 304 p := make([]byte, utf8.UTFMax) 305 // Read it back with ReadRune 306 for r := rune(0); r < NRune; r++ { 307 size := utf8.EncodeRune(p, r) 308 nr, nbytes, err := buf.ReadRune() 309 if nr != r || nbytes != size || err != nil { 310 t.Fatalf("ReadRune(%U) got %U,%d not %U,%d (err=%s)", r, nr, nbytes, r, size, err) 311 } 312 } 313 314 // Check that UnreadRune works 315 buf.Reset() 316 317 // check at EOF 318 if err := buf.UnreadRune(); err == nil { 319 t.Fatal("UnreadRune at EOF: got no error") 320 } 321 if _, _, err := buf.ReadRune(); err == nil { 322 t.Fatal("ReadRune at EOF: got no error") 323 } 324 if err := buf.UnreadRune(); err == nil { 325 t.Fatal("UnreadRune after ReadRune at EOF: got no error") 326 } 327 328 // check not at EOF 329 buf.Write(b) 330 for r := rune(0); r < NRune; r++ { 331 r1, size, _ := buf.ReadRune() 332 if err := buf.UnreadRune(); err != nil { 333 t.Fatalf("UnreadRune(%U) got error %q", r, err) 334 } 335 r2, nbytes, err := buf.ReadRune() 336 if r1 != r2 || r1 != r || nbytes != size || err != nil { 337 t.Fatalf("ReadRune(%U) after UnreadRune got %U,%d not %U,%d (err=%s)", r, r2, nbytes, r, size, err) 338 } 339 } 340 } 341 342 func TestNext(t *testing.T) { 343 b := []byte{0, 1, 2, 3, 4} 344 tmp := make([]byte, 5) 345 for i := 0; i <= 5; i++ { 346 for j := i; j <= 5; j++ { 347 for k := 0; k <= 6; k++ { 348 // 0 <= i <= j <= 5; 0 <= k <= 6 349 // Check that if we start with a buffer 350 // of length j at offset i and ask for 351 // Next(k), we get the right bytes. 352 buf := NewBuffer(b[0:j]) 353 n, _ := buf.Read(tmp[0:i]) 354 if n != i { 355 t.Fatalf("Read %d returned %d", i, n) 356 } 357 bb := buf.Next(k) 358 want := k 359 if want > j-i { 360 want = j - i 361 } 362 if len(bb) != want { 363 t.Fatalf("in %d,%d: len(Next(%d)) == %d", i, j, k, len(bb)) 364 } 365 for l, v := range bb { 366 if v != byte(l+i) { 367 t.Fatalf("in %d,%d: Next(%d)[%d] = %d, want %d", i, j, k, l, v, l+i) 368 } 369 } 370 } 371 } 372 } 373 } 374 375 var readBytesTests = []struct { 376 buffer string 377 delim byte 378 expected []string 379 err error 380 }{ 381 {"", 0, []string{""}, io.EOF}, 382 {"a\x00", 0, []string{"a\x00"}, nil}, 383 {"abbbaaaba", 'b', []string{"ab", "b", "b", "aaab"}, nil}, 384 {"hello\x01world", 1, []string{"hello\x01"}, nil}, 385 {"foo\nbar", 0, []string{"foo\nbar"}, io.EOF}, 386 {"alpha\nbeta\ngamma\n", '\n', []string{"alpha\n", "beta\n", "gamma\n"}, nil}, 387 {"alpha\nbeta\ngamma", '\n', []string{"alpha\n", "beta\n", "gamma"}, io.EOF}, 388 } 389 390 func TestReadBytes(t *testing.T) { 391 for _, test := range readBytesTests { 392 buf := NewBufferString(test.buffer) 393 var err error 394 for _, expected := range test.expected { 395 var bytes []byte 396 bytes, err = buf.ReadBytes(test.delim) 397 if string(bytes) != expected { 398 t.Errorf("expected %q, got %q", expected, bytes) 399 } 400 if err != nil { 401 break 402 } 403 } 404 if err != test.err { 405 t.Errorf("expected error %v, got %v", test.err, err) 406 } 407 } 408 } 409 410 func TestReadString(t *testing.T) { 411 for _, test := range readBytesTests { 412 buf := NewBufferString(test.buffer) 413 var err error 414 for _, expected := range test.expected { 415 var s string 416 s, err = buf.ReadString(test.delim) 417 if s != expected { 418 t.Errorf("expected %q, got %q", expected, s) 419 } 420 if err != nil { 421 break 422 } 423 } 424 if err != test.err { 425 t.Errorf("expected error %v, got %v", test.err, err) 426 } 427 } 428 } 429 430 func BenchmarkReadString(b *testing.B) { 431 const n = 32 << 10 432 433 data := make([]byte, n) 434 data[n-1] = 'x' 435 b.SetBytes(int64(n)) 436 for i := 0; i < b.N; i++ { 437 buf := NewBuffer(data) 438 _, err := buf.ReadString('x') 439 if err != nil { 440 b.Fatal(err) 441 } 442 } 443 } 444 445 func TestGrow(t *testing.T) { 446 x := []byte{'x'} 447 y := []byte{'y'} 448 tmp := make([]byte, 72) 449 for _, startLen := range []int{0, 100, 1000, 10000, 100000} { 450 xBytes := Repeat(x, startLen) 451 for _, growLen := range []int{0, 100, 1000, 10000, 100000} { 452 buf := NewBuffer(xBytes) 453 // If we read, this affects buf.off, which is good to test. 454 readBytes, _ := buf.Read(tmp) 455 buf.Grow(growLen) 456 yBytes := Repeat(y, growLen) 457 // Check no allocation occurs in write, as long as we're single-threaded. 458 var m1, m2 runtime.MemStats 459 runtime.ReadMemStats(&m1) 460 buf.Write(yBytes) 461 runtime.ReadMemStats(&m2) 462 if runtime.GOMAXPROCS(-1) == 1 && m1.Mallocs != m2.Mallocs { 463 t.Errorf("allocation occurred during write") 464 } 465 // Check that buffer has correct data. 466 if !Equal(buf.Bytes()[0:startLen-readBytes], xBytes[readBytes:]) { 467 t.Errorf("bad initial data at %d %d", startLen, growLen) 468 } 469 if !Equal(buf.Bytes()[startLen-readBytes:startLen-readBytes+growLen], yBytes) { 470 t.Errorf("bad written data at %d %d", startLen, growLen) 471 } 472 } 473 } 474 } 475 476 // Was a bug: used to give EOF reading empty slice at EOF. 477 func TestReadEmptyAtEOF(t *testing.T) { 478 b := new(Buffer) 479 slice := make([]byte, 0) 480 n, err := b.Read(slice) 481 if err != nil { 482 t.Errorf("read error: %v", err) 483 } 484 if n != 0 { 485 t.Errorf("wrong count; got %d want 0", n) 486 } 487 } 488 489 func TestUnreadByte(t *testing.T) { 490 b := new(Buffer) 491 492 // check at EOF 493 if err := b.UnreadByte(); err == nil { 494 t.Fatal("UnreadByte at EOF: got no error") 495 } 496 if _, err := b.ReadByte(); err == nil { 497 t.Fatal("ReadByte at EOF: got no error") 498 } 499 if err := b.UnreadByte(); err == nil { 500 t.Fatal("UnreadByte after ReadByte at EOF: got no error") 501 } 502 503 // check not at EOF 504 b.WriteString("abcdefghijklmnopqrstuvwxyz") 505 506 // after unsuccessful read 507 if n, err := b.Read(nil); n != 0 || err != nil { 508 t.Fatalf("Read(nil) = %d,%v; want 0,nil", n, err) 509 } 510 if err := b.UnreadByte(); err == nil { 511 t.Fatal("UnreadByte after Read(nil): got no error") 512 } 513 514 // after successful read 515 if _, err := b.ReadBytes('m'); err != nil { 516 t.Fatalf("ReadBytes: %v", err) 517 } 518 if err := b.UnreadByte(); err != nil { 519 t.Fatalf("UnreadByte: %v", err) 520 } 521 c, err := b.ReadByte() 522 if err != nil { 523 t.Fatalf("ReadByte: %v", err) 524 } 525 if c != 'm' { 526 t.Errorf("ReadByte = %q; want %q", c, 'm') 527 } 528 } 529 530 // Tests that we occasionally compact. Issue 5154. 531 func TestBufferGrowth(t *testing.T) { 532 var b Buffer 533 buf := make([]byte, 1024) 534 b.Write(buf[0:1]) 535 var cap0 int 536 for i := 0; i < 5<<10; i++ { 537 b.Write(buf) 538 b.Read(buf) 539 if i == 0 { 540 cap0 = b.Cap() 541 } 542 } 543 cap1 := b.Cap() 544 // (*Buffer).grow allows for 2x capacity slop before sliding, 545 // so set our error threshold at 3x. 546 if cap1 > cap0*3 { 547 t.Errorf("buffer cap = %d; too big (grew from %d)", cap1, cap0) 548 } 549 } 550 551 // Test that tryGrowByReslice is inlined. 552 // Only execute on "linux-amd64" builder in order to avoid breakage. 553 func TestTryGrowByResliceInlined(t *testing.T) { 554 targetBuilder := "linux-amd64" 555 if testenv.Builder() != targetBuilder { 556 t.Skipf("%q gets executed on %q builder only", t.Name(), targetBuilder) 557 } 558 t.Parallel() 559 goBin := testenv.GoToolPath(t) 560 out, err := exec.Command(goBin, "tool", "nm", goBin).CombinedOutput() 561 if err != nil { 562 t.Fatalf("go tool nm: %v: %s", err, out) 563 } 564 // Verify this doesn't exist: 565 sym := "bytes.(*Buffer).tryGrowByReslice" 566 if Contains(out, []byte(sym)) { 567 t.Errorf("found symbol %q in cmd/go, but should be inlined", sym) 568 } 569 } 570 571 func BenchmarkWriteByte(b *testing.B) { 572 const n = 4 << 10 573 b.SetBytes(n) 574 buf := NewBuffer(make([]byte, n)) 575 for i := 0; i < b.N; i++ { 576 buf.Reset() 577 for i := 0; i < n; i++ { 578 buf.WriteByte('x') 579 } 580 } 581 } 582 583 func BenchmarkWriteRune(b *testing.B) { 584 const n = 4 << 10 585 const r = '☺' 586 b.SetBytes(int64(n * utf8.RuneLen(r))) 587 buf := NewBuffer(make([]byte, n*utf8.UTFMax)) 588 for i := 0; i < b.N; i++ { 589 buf.Reset() 590 for i := 0; i < n; i++ { 591 buf.WriteRune(r) 592 } 593 } 594 } 595 596 // From Issue 5154. 597 func BenchmarkBufferNotEmptyWriteRead(b *testing.B) { 598 buf := make([]byte, 1024) 599 for i := 0; i < b.N; i++ { 600 var b Buffer 601 b.Write(buf[0:1]) 602 for i := 0; i < 5<<10; i++ { 603 b.Write(buf) 604 b.Read(buf) 605 } 606 } 607 } 608 609 // Check that we don't compact too often. From Issue 5154. 610 func BenchmarkBufferFullSmallReads(b *testing.B) { 611 buf := make([]byte, 1024) 612 for i := 0; i < b.N; i++ { 613 var b Buffer 614 b.Write(buf) 615 for b.Len()+20 < b.Cap() { 616 b.Write(buf[:10]) 617 } 618 for i := 0; i < 5<<10; i++ { 619 b.Read(buf[:1]) 620 b.Write(buf[:1]) 621 } 622 } 623 }