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