codekingpro/portable-devtools
114k
1// Copyright 2009 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.4 5package bufio_test6 7import (8 . "bufio"9 "bytes"10 "errors"11 "fmt"12 "internal/asan"13 "io"14 "math/rand"15 "strconv"16 "strings"17 "testing"18 "testing/iotest"19 "time"20 "unicode/utf8"21)22 23// Reads from a reader and rot13s the result.24type rot13Reader struct {25 r io.Reader26}27 28func newRot13Reader(r io.Reader) *rot13Reader {29 r13 := new(rot13Reader)30 r13.r = r31 return r1332}33 34func (r13 *rot13Reader) Read(p []byte) (int, error) {35 n, err := r13.r.Read(p)36 for i := 0; i < n; i++ {37 c := p[i] | 0x20 // lowercase byte38 if 'a' <= c && c <= 'm' {39 p[i] += 1340 } else if 'n' <= c && c <= 'z' {41 p[i] -= 1342 }43 }44 return n, err45}46 47// Call ReadByte to accumulate the text of a file48func readBytes(buf *Reader) string {49 var b [1000]byte50 nb := 051 for {52 c, err := buf.ReadByte()53 if err == io.EOF {54 break55 }56 if err == nil {57 b[nb] = c58 nb++59 } else if err != iotest.ErrTimeout {60 panic("Data: " + err.Error())61 }62 }63 return string(b[0:nb])64}65 66func TestReaderSimple(t *testing.T) {67 data := "hello world"68 b := NewReader(strings.NewReader(data))69 if s := readBytes(b); s != "hello world" {70 t.Errorf("simple hello world test failed: got %q", s)71 }72 73 b = NewReader(newRot13Reader(strings.NewReader(data)))74 if s := readBytes(b); s != "uryyb jbeyq" {75 t.Errorf("rot13 hello world test failed: got %q", s)76 }77}78 79type readMaker struct {80 name string81 fn func(io.Reader) io.Reader82}83 84var readMakers = []readMaker{85 {"full", func(r io.Reader) io.Reader { return r }},86 {"byte", iotest.OneByteReader},87 {"half", iotest.HalfReader},88 {"data+err", iotest.DataErrReader},89 {"timeout", iotest.TimeoutReader},90}91 92// Call ReadString (which ends up calling everything else)93// to accumulate the text of a file.94func readLines(b *Reader) string {95 s := ""96 for {97 s1, err := b.ReadString('\n')98 if err == io.EOF {99 break100 }101 if err != nil && err != iotest.ErrTimeout {102 panic("GetLines: " + err.Error())103 }104 s += s1105 }106 return s107}108 109// Call Read to accumulate the text of a file110func reads(buf *Reader, m int) string {111 var b [1000]byte112 nb := 0113 for {114 n, err := buf.Read(b[nb : nb+m])115 nb += n116 if err == io.EOF {117 break118 }119 }120 return string(b[0:nb])121}122 123type bufReader struct {124 name string125 fn func(*Reader) string126}127 128var bufreaders = []bufReader{129 {"1", func(b *Reader) string { return reads(b, 1) }},130 {"2", func(b *Reader) string { return reads(b, 2) }},131 {"3", func(b *Reader) string { return reads(b, 3) }},132 {"4", func(b *Reader) string { return reads(b, 4) }},133 {"5", func(b *Reader) string { return reads(b, 5) }},134 {"7", func(b *Reader) string { return reads(b, 7) }},135 {"bytes", readBytes},136 {"lines", readLines},137}138 139const minReadBufferSize = 16140 141var bufsizes = []int{142 0, minReadBufferSize, 23, 32, 46, 64, 93, 128, 1024, 4096,143}144 145func TestReader(t *testing.T) {146 var texts [31]string147 str := ""148 all := ""149 for i := 0; i < len(texts)-1; i++ {150 texts[i] = str + "\n"151 all += texts[i]152 str += string(rune(i%26 + 'a'))153 }154 texts[len(texts)-1] = all155 156 for h := 0; h < len(texts); h++ {157 text := texts[h]158 for i := 0; i < len(readMakers); i++ {159 for j := 0; j < len(bufreaders); j++ {160 for k := 0; k < len(bufsizes); k++ {161 readmaker := readMakers[i]162 bufreader := bufreaders[j]163 bufsize := bufsizes[k]164 read := readmaker.fn(strings.NewReader(text))165 buf := NewReaderSize(read, bufsize)166 s := bufreader.fn(buf)167 if s != text {168 t.Errorf("reader=%s fn=%s bufsize=%d want=%q got=%q",169 readmaker.name, bufreader.name, bufsize, text, s)170 }171 }172 }173 }174 }175}176 177type zeroReader struct{}178 179func (zeroReader) Read(p []byte) (int, error) {180 return 0, nil181}182 183func TestZeroReader(t *testing.T) {184 var z zeroReader185 r := NewReader(z)186 187 c := make(chan error)188 go func() {189 _, err := r.ReadByte()190 c <- err191 }()192 193 select {194 case err := <-c:195 if err == nil {196 t.Error("error expected")197 } else if err != io.ErrNoProgress {198 t.Error("unexpected error:", err)199 }200 case <-time.After(time.Second):201 t.Error("test timed out (endless loop in ReadByte?)")202 }203}204 205// A StringReader delivers its data one string segment at a time via Read.206type StringReader struct {207 data []string208 step int209}210 211func (r *StringReader) Read(p []byte) (n int, err error) {212 if r.step < len(r.data) {213 s := r.data[r.step]214 n = copy(p, s)215 r.step++216 } else {217 err = io.EOF218 }219 return220}221 222func readRuneSegments(t *testing.T, segments []string) {223 got := ""224 want := strings.Join(segments, "")225 r := NewReader(&StringReader{data: segments})226 for {227 r, _, err := r.ReadRune()228 if err != nil {229 if err != io.EOF {230 return231 }232 break233 }234 got += string(r)235 }236 if got != want {237 t.Errorf("segments=%v got=%s want=%s", segments, got, want)238 }239}240 241var segmentList = [][]string{242 {},243 {""},244 {"日", "本語"},245 {"\u65e5", "\u672c", "\u8a9e"},246 {"\U000065e5", "\U0000672c", "\U00008a9e"},247 {"\xe6", "\x97\xa5\xe6", "\x9c\xac\xe8\xaa\x9e"},248 {"Hello", ", ", "World", "!"},249 {"Hello", ", ", "", "World", "!"},250}251 252func TestReadRune(t *testing.T) {253 for _, s := range segmentList {254 readRuneSegments(t, s)255 }256}257 258func TestUnreadRune(t *testing.T) {259 segments := []string{"Hello, world:", "日本語"}260 r := NewReader(&StringReader{data: segments})261 got := ""262 want := strings.Join(segments, "")263 // Normal execution.264 for {265 r1, _, err := r.ReadRune()266 if err != nil {267 if err != io.EOF {268 t.Error("unexpected error on ReadRune:", err)269 }270 break271 }272 got += string(r1)273 // Put it back and read it again.274 if err = r.UnreadRune(); err != nil {275 t.Fatal("unexpected error on UnreadRune:", err)276 }277 r2, _, err := r.ReadRune()278 if err != nil {279 t.Fatal("unexpected error reading after unreading:", err)280 }281 if r1 != r2 {282 t.Fatalf("incorrect rune after unread: got %c, want %c", r1, r2)283 }284 }285 if got != want {286 t.Errorf("got %q, want %q", got, want)287 }288}289 290func TestNoUnreadRuneAfterPeek(t *testing.T) {291 br := NewReader(strings.NewReader("example"))292 br.ReadRune()293 br.Peek(1)294 if err := br.UnreadRune(); err == nil {295 t.Error("UnreadRune didn't fail after Peek")296 }297}298 299func TestNoUnreadByteAfterPeek(t *testing.T) {300 br := NewReader(strings.NewReader("example"))301 br.ReadByte()302 br.Peek(1)303 if err := br.UnreadByte(); err == nil {304 t.Error("UnreadByte didn't fail after Peek")305 }306}307 308func TestNoUnreadRuneAfterDiscard(t *testing.T) {309 br := NewReader(strings.NewReader("example"))310 br.ReadRune()311 br.Discard(1)312 if err := br.UnreadRune(); err == nil {313 t.Error("UnreadRune didn't fail after Discard")314 }315}316 317func TestNoUnreadByteAfterDiscard(t *testing.T) {318 br := NewReader(strings.NewReader("example"))319 br.ReadByte()320 br.Discard(1)321 if err := br.UnreadByte(); err == nil {322 t.Error("UnreadByte didn't fail after Discard")323 }324}325 326func TestNoUnreadRuneAfterWriteTo(t *testing.T) {327 br := NewReader(strings.NewReader("example"))328 br.WriteTo(io.Discard)329 if err := br.UnreadRune(); err == nil {330 t.Error("UnreadRune didn't fail after WriteTo")331 }332}333 334func TestNoUnreadByteAfterWriteTo(t *testing.T) {335 br := NewReader(strings.NewReader("example"))336 br.WriteTo(io.Discard)337 if err := br.UnreadByte(); err == nil {338 t.Error("UnreadByte didn't fail after WriteTo")339 }340}341 342func TestUnreadByte(t *testing.T) {343 segments := []string{"Hello, ", "world"}344 r := NewReader(&StringReader{data: segments})345 got := ""346 want := strings.Join(segments, "")347 // Normal execution.348 for {349 b1, err := r.ReadByte()350 if err != nil {351 if err != io.EOF {352 t.Error("unexpected error on ReadByte:", err)353 }354 break355 }356 got += string(b1)357 // Put it back and read it again.358 if err = r.UnreadByte(); err != nil {359 t.Fatal("unexpected error on UnreadByte:", err)360 }361 b2, err := r.ReadByte()362 if err != nil {363 t.Fatal("unexpected error reading after unreading:", err)364 }365 if b1 != b2 {366 t.Fatalf("incorrect byte after unread: got %q, want %q", b1, b2)367 }368 }369 if got != want {370 t.Errorf("got %q, want %q", got, want)371 }372}373 374func TestUnreadByteMultiple(t *testing.T) {375 segments := []string{"Hello, ", "world"}376 data := strings.Join(segments, "")377 for n := 0; n <= len(data); n++ {378 r := NewReader(&StringReader{data: segments})379 // Read n bytes.380 for i := 0; i < n; i++ {381 b, err := r.ReadByte()382 if err != nil {383 t.Fatalf("n = %d: unexpected error on ReadByte: %v", n, err)384 }385 if b != data[i] {386 t.Fatalf("n = %d: incorrect byte returned from ReadByte: got %q, want %q", n, b, data[i])387 }388 }389 // Unread one byte if there is one.390 if n > 0 {391 if err := r.UnreadByte(); err != nil {392 t.Errorf("n = %d: unexpected error on UnreadByte: %v", n, err)393 }394 }395 // Test that we cannot unread any further.396 if err := r.UnreadByte(); err == nil {397 t.Errorf("n = %d: expected error on UnreadByte", n)398 }399 }400}401 402func TestUnreadByteOthers(t *testing.T) {403 // A list of readers to use in conjunction with UnreadByte.404 var readers = []func(*Reader, byte) ([]byte, error){405 (*Reader).ReadBytes,406 (*Reader).ReadSlice,407 func(r *Reader, delim byte) ([]byte, error) {408 data, err := r.ReadString(delim)409 return []byte(data), err410 },411 // ReadLine doesn't fit the data/pattern easily412 // so we leave it out. It should be covered via413 // the ReadSlice test since ReadLine simply calls414 // ReadSlice, and it's that function that handles415 // the last byte.416 }417 418 // Try all readers with UnreadByte.419 for rno, read := range readers {420 // Some input data that is longer than the minimum reader buffer size.421 const n = 10422 var buf bytes.Buffer423 for i := 0; i < n; i++ {424 buf.WriteString("abcdefg")425 }426 427 r := NewReaderSize(&buf, minReadBufferSize)428 readTo := func(delim byte, want string) {429 data, err := read(r, delim)430 if err != nil {431 t.Fatalf("#%d: unexpected error reading to %c: %v", rno, delim, err)432 }433 if got := string(data); got != want {434 t.Fatalf("#%d: got %q, want %q", rno, got, want)435 }436 }437 438 // Read the data with occasional UnreadByte calls.439 for i := 0; i < n; i++ {440 readTo('d', "abcd")441 for j := 0; j < 3; j++ {442 if err := r.UnreadByte(); err != nil {443 t.Fatalf("#%d: unexpected error on UnreadByte: %v", rno, err)444 }445 readTo('d', "d")446 }447 readTo('g', "efg")448 }449 450 // All data should have been read.451 _, err := r.ReadByte()452 if err != io.EOF {453 t.Errorf("#%d: got error %v; want EOF", rno, err)454 }455 }456}457 458// Test that UnreadRune fails if the preceding operation was not a ReadRune.459func TestUnreadRuneError(t *testing.T) {460 buf := make([]byte, 3) // All runes in this test are 3 bytes long461 r := NewReader(&StringReader{data: []string{"日本語日本語日本語"}})462 if r.UnreadRune() == nil {463 t.Error("expected error on UnreadRune from fresh buffer")464 }465 _, _, err := r.ReadRune()466 if err != nil {467 t.Error("unexpected error on ReadRune (1):", err)468 }469 if err = r.UnreadRune(); err != nil {470 t.Error("unexpected error on UnreadRune (1):", err)471 }472 if r.UnreadRune() == nil {473 t.Error("expected error after UnreadRune (1)")474 }475 // Test error after Read.476 _, _, err = r.ReadRune() // reset state477 if err != nil {478 t.Error("unexpected error on ReadRune (2):", err)479 }480 _, err = r.Read(buf)481 if err != nil {482 t.Error("unexpected error on Read (2):", err)483 }484 if r.UnreadRune() == nil {485 t.Error("expected error after Read (2)")486 }487 // Test error after ReadByte.488 _, _, err = r.ReadRune() // reset state489 if err != nil {490 t.Error("unexpected error on ReadRune (2):", err)491 }492 for range buf {493 _, err = r.ReadByte()494 if err != nil {495 t.Error("unexpected error on ReadByte (2):", err)496 }497 }498 if r.UnreadRune() == nil {499 t.Error("expected error after ReadByte")500 }501 // Test error after UnreadByte.502 _, _, err = r.ReadRune() // reset state503 if err != nil {504 t.Error("unexpected error on ReadRune (3):", err)505 }506 _, err = r.ReadByte()507 if err != nil {508 t.Error("unexpected error on ReadByte (3):", err)509 }510 err = r.UnreadByte()511 if err != nil {512 t.Error("unexpected error on UnreadByte (3):", err)513 }514 if r.UnreadRune() == nil {515 t.Error("expected error after UnreadByte (3)")516 }517 // Test error after ReadSlice.518 _, _, err = r.ReadRune() // reset state519 if err != nil {520 t.Error("unexpected error on ReadRune (4):", err)521 }522 _, err = r.ReadSlice(0)523 if err != io.EOF {524 t.Error("unexpected error on ReadSlice (4):", err)525 }526 if r.UnreadRune() == nil {527 t.Error("expected error after ReadSlice (4)")528 }529}530 531func TestUnreadRuneAtEOF(t *testing.T) {532 // UnreadRune/ReadRune should error at EOF (was a bug; used to panic)533 r := NewReader(strings.NewReader("x"))534 r.ReadRune()535 r.ReadRune()536 r.UnreadRune()537 _, _, err := r.ReadRune()538 if err == nil {539 t.Error("expected error at EOF")540 } else if err != io.EOF {541 t.Error("expected EOF; got", err)542 }543}544 545func TestReadWriteRune(t *testing.T) {546 const NRune = 1000547 byteBuf := new(bytes.Buffer)548 w := NewWriter(byteBuf)549 // Write the runes out using WriteRune550 buf := make([]byte, utf8.UTFMax)551 for r := rune(0); r < NRune; r++ {552 size := utf8.EncodeRune(buf, r)553 nbytes, err := w.WriteRune(r)554 if err != nil {555 t.Fatalf("WriteRune(0x%x) error: %s", r, err)556 }557 if nbytes != size {558 t.Fatalf("WriteRune(0x%x) expected %d, got %d", r, size, nbytes)559 }560 }561 w.Flush()562 563 r := NewReader(byteBuf)564 // Read them back with ReadRune565 for r1 := rune(0); r1 < NRune; r1++ {566 size := utf8.EncodeRune(buf, r1)567 nr, nbytes, err := r.ReadRune()568 if nr != r1 || nbytes != size || err != nil {569 t.Fatalf("ReadRune(0x%x) got 0x%x,%d not 0x%x,%d (err=%s)", r1, nr, nbytes, r1, size, err)570 }571 }572}573 574func TestWriteInvalidRune(t *testing.T) {575 // Invalid runes, including negative ones, should be written as the576 // replacement character.577 for _, r := range []rune{-1, utf8.MaxRune + 1} {578 var buf strings.Builder579 w := NewWriter(&buf)580 w.WriteRune(r)581 w.Flush()582 if s := buf.String(); s != "\uFFFD" {583 t.Errorf("WriteRune(%d) wrote %q, not replacement character", r, s)584 }585 }586}587 588func TestReadStringAllocs(t *testing.T) {589 if asan.Enabled {590 t.Skip("test allocates more with -asan; see #70079")591 }592 r := strings.NewReader(" foo foo 42 42 42 42 42 42 42 42 4.2 4.2 4.2 4.2\n")593 buf := NewReader(r)594 allocs := testing.AllocsPerRun(100, func() {595 r.Seek(0, io.SeekStart)596 buf.Reset(r)597 598 _, err := buf.ReadString('\n')599 if err != nil {600 t.Fatal(err)601 }602 })603 if allocs != 1 {604 t.Errorf("Unexpected number of allocations, got %f, want 1", allocs)605 }606}607 608func TestWriter(t *testing.T) {609 var data [8192]byte610 611 for i := 0; i < len(data); i++ {612 data[i] = byte(' ' + i%('~'-' '))613 }614 w := new(bytes.Buffer)615 for i := 0; i < len(bufsizes); i++ {616 for j := 0; j < len(bufsizes); j++ {617 nwrite := bufsizes[i]618 bs := bufsizes[j]619 620 // Write nwrite bytes using buffer size bs.621 // Check that the right amount makes it out622 // and that the data is correct.623 624 w.Reset()625 buf := NewWriterSize(w, bs)626 context := fmt.Sprintf("nwrite=%d bufsize=%d", nwrite, bs)627 n, e1 := buf.Write(data[0:nwrite])628 if e1 != nil || n != nwrite {629 t.Errorf("%s: buf.Write %d = %d, %v", context, nwrite, n, e1)630 continue631 }632 if e := buf.Flush(); e != nil {633 t.Errorf("%s: buf.Flush = %v", context, e)634 }635 636 written := w.Bytes()637 if len(written) != nwrite {638 t.Errorf("%s: %d bytes written", context, len(written))639 }640 for l := 0; l < len(written); l++ {641 if written[l] != data[l] {642 t.Errorf("wrong bytes written")643 t.Errorf("want=%q", data[:len(written)])644 t.Errorf("have=%q", written)645 }646 }647 }648 }649}650 651func TestWriterAppend(t *testing.T) {652 got := new(bytes.Buffer)653 var want []byte654 rn := rand.New(rand.NewSource(0))655 w := NewWriterSize(got, 64)656 for i := 0; i < 100; i++ {657 // Obtain a buffer to append to.658 b := w.AvailableBuffer()659 if w.Available() != cap(b) {660 t.Fatalf("Available() = %v, want %v", w.Available(), cap(b))661 }662 663 // While not recommended, it is valid to append to a shifted buffer.664 // This forces Write to copy the input.665 if rn.Intn(8) == 0 && cap(b) > 0 {666 b = b[1:1:cap(b)]667 }668 669 // Append a random integer of varying width.670 n := int64(rn.Intn(1 << rn.Intn(30)))671 want = append(strconv.AppendInt(want, n, 10), ' ')672 b = append(strconv.AppendInt(b, n, 10), ' ')673 w.Write(b)674 }675 w.Flush()676 677 if !bytes.Equal(got.Bytes(), want) {678 t.Errorf("output mismatch:\ngot %s\nwant %s", got.Bytes(), want)679 }680}681 682// Check that write errors are returned properly.683 684type errorWriterTest struct {685 n, m int686 err error687 expect error688}689 690func (w errorWriterTest) Write(p []byte) (int, error) {691 return len(p) * w.n / w.m, w.err692}693 694var errorWriterTests = []errorWriterTest{695 {0, 1, nil, io.ErrShortWrite},696 {1, 2, nil, io.ErrShortWrite},697 {1, 1, nil, nil},698 {0, 1, io.ErrClosedPipe, io.ErrClosedPipe},699 {1, 2, io.ErrClosedPipe, io.ErrClosedPipe},700 {1, 1, io.ErrClosedPipe, io.ErrClosedPipe},701}702 703func TestWriteErrors(t *testing.T) {704 for _, w := range errorWriterTests {705 buf := NewWriter(w)706 _, e := buf.Write([]byte("hello world"))707 if e != nil {708 t.Errorf("Write hello to %v: %v", w, e)709 continue710 }711 // Two flushes, to verify the error is sticky.712 for i := 0; i < 2; i++ {713 e = buf.Flush()714 if e != w.expect {715 t.Errorf("Flush %d/2 %v: got %v, wanted %v", i+1, w, e, w.expect)716 }717 }718 }719}720 721func TestNewReaderSizeIdempotent(t *testing.T) {722 const BufSize = 1000723 b := NewReaderSize(strings.NewReader("hello world"), BufSize)724 // Does it recognize itself?725 b1 := NewReaderSize(b, BufSize)726 if b1 != b {727 t.Error("NewReaderSize did not detect underlying Reader")728 }729 // Does it wrap if existing buffer is too small?730 b2 := NewReaderSize(b, 2*BufSize)731 if b2 == b {732 t.Error("NewReaderSize did not enlarge buffer")733 }734}735 736func TestNewWriterSizeIdempotent(t *testing.T) {737 const BufSize = 1000738 b := NewWriterSize(new(bytes.Buffer), BufSize)739 // Does it recognize itself?740 b1 := NewWriterSize(b, BufSize)741 if b1 != b {742 t.Error("NewWriterSize did not detect underlying Writer")743 }744 // Does it wrap if existing buffer is too small?745 b2 := NewWriterSize(b, 2*BufSize)746 if b2 == b {747 t.Error("NewWriterSize did not enlarge buffer")748 }749}750 751func TestWriteString(t *testing.T) {752 const BufSize = 8753 buf := new(strings.Builder)754 b := NewWriterSize(buf, BufSize)755 b.WriteString("0") // easy756 b.WriteString("123456") // still easy757 b.WriteString("7890") // easy after flush758 b.WriteString("abcdefghijklmnopqrstuvwxy") // hard759 b.WriteString("z")760 if err := b.Flush(); err != nil {761 t.Error("WriteString", err)762 }763 s := "01234567890abcdefghijklmnopqrstuvwxyz"764 if buf.String() != s {765 t.Errorf("WriteString wants %q gets %q", s, buf.String())766 }767}768 769func TestWriteStringStringWriter(t *testing.T) {770 const BufSize = 8771 {772 tw := &teststringwriter{}773 b := NewWriterSize(tw, BufSize)774 b.WriteString("1234")775 tw.check(t, "", "")776 b.WriteString("56789012") // longer than BufSize777 tw.check(t, "12345678", "") // but not enough (after filling the partially-filled buffer)778 b.Flush()779 tw.check(t, "123456789012", "")780 }781 {782 tw := &teststringwriter{}783 b := NewWriterSize(tw, BufSize)784 b.WriteString("123456789") // long string, empty buffer:785 tw.check(t, "", "123456789") // use WriteString786 }787 {788 tw := &teststringwriter{}789 b := NewWriterSize(tw, BufSize)790 b.WriteString("abc")791 tw.check(t, "", "")792 b.WriteString("123456789012345") // long string, non-empty buffer793 tw.check(t, "abc12345", "6789012345") // use Write and then WriteString since the remaining part is still longer than BufSize794 }795 {796 tw := &teststringwriter{}797 b := NewWriterSize(tw, BufSize)798 b.Write([]byte("abc")) // same as above, but use Write instead of WriteString799 tw.check(t, "", "")800 b.WriteString("123456789012345")801 tw.check(t, "abc12345", "6789012345") // same as above802 }803}804 805type teststringwriter struct {806 write string807 writeString string808}809 810func (w *teststringwriter) Write(b []byte) (int, error) {811 w.write += string(b)812 return len(b), nil813}814 815func (w *teststringwriter) WriteString(s string) (int, error) {816 w.writeString += s817 return len(s), nil818}819 820func (w *teststringwriter) check(t *testing.T, write, writeString string) {821 t.Helper()822 if w.write != write {823 t.Errorf("write: expected %q, got %q", write, w.write)824 }825 if w.writeString != writeString {826 t.Errorf("writeString: expected %q, got %q", writeString, w.writeString)827 }828}829 830func TestBufferFull(t *testing.T) {831 const longString = "And now, hello, world! It is the time for all good men to come to the aid of their party"832 buf := NewReaderSize(strings.NewReader(longString), minReadBufferSize)833 line, err := buf.ReadSlice('!')834 if string(line) != "And now, hello, " || err != ErrBufferFull {835 t.Errorf("first ReadSlice(,) = %q, %v", line, err)836 }837 line, err = buf.ReadSlice('!')838 if string(line) != "world!" || err != nil {839 t.Errorf("second ReadSlice(,) = %q, %v", line, err)840 }841}842 843func TestPeek(t *testing.T) {844 p := make([]byte, 10)845 // string is 16 (minReadBufferSize) long.846 buf := NewReaderSize(strings.NewReader("abcdefghijklmnop"), minReadBufferSize)847 if s, err := buf.Peek(1); string(s) != "a" || err != nil {848 t.Fatalf("want %q got %q, err=%v", "a", string(s), err)849 }850 if s, err := buf.Peek(4); string(s) != "abcd" || err != nil {851 t.Fatalf("want %q got %q, err=%v", "abcd", string(s), err)852 }853 if _, err := buf.Peek(-1); err != ErrNegativeCount {854 t.Fatalf("want ErrNegativeCount got %v", err)855 }856 if s, err := buf.Peek(32); string(s) != "abcdefghijklmnop" || err != ErrBufferFull {857 t.Fatalf("want %q, ErrBufFull got %q, err=%v", "abcdefghijklmnop", string(s), err)858 }859 if _, err := buf.Read(p[0:3]); string(p[0:3]) != "abc" || err != nil {860 t.Fatalf("want %q got %q, err=%v", "abc", string(p[0:3]), err)861 }862 if s, err := buf.Peek(1); string(s) != "d" || err != nil {863 t.Fatalf("want %q got %q, err=%v", "d", string(s), err)864 }865 if s, err := buf.Peek(2); string(s) != "de" || err != nil {866 t.Fatalf("want %q got %q, err=%v", "de", string(s), err)867 }868 if _, err := buf.Read(p[0:3]); string(p[0:3]) != "def" || err != nil {869 t.Fatalf("want %q got %q, err=%v", "def", string(p[0:3]), err)870 }871 if s, err := buf.Peek(4); string(s) != "ghij" || err != nil {872 t.Fatalf("want %q got %q, err=%v", "ghij", string(s), err)873 }874 if _, err := buf.Read(p[0:]); string(p[0:]) != "ghijklmnop" || err != nil {875 t.Fatalf("want %q got %q, err=%v", "ghijklmnop", string(p[0:minReadBufferSize]), err)876 }877 if s, err := buf.Peek(0); string(s) != "" || err != nil {878 t.Fatalf("want %q got %q, err=%v", "", string(s), err)879 }880 if _, err := buf.Peek(1); err != io.EOF {881 t.Fatalf("want EOF got %v", err)882 }883 884 // Test for issue 3022, not exposing a reader's error on a successful Peek.885 buf = NewReaderSize(dataAndEOFReader("abcd"), 32)886 if s, err := buf.Peek(2); string(s) != "ab" || err != nil {887 t.Errorf(`Peek(2) on "abcd", EOF = %q, %v; want "ab", nil`, string(s), err)888 }889 if s, err := buf.Peek(4); string(s) != "abcd" || err != nil {890 t.Errorf(`Peek(4) on "abcd", EOF = %q, %v; want "abcd", nil`, string(s), err)891 }892 if n, err := buf.Read(p[0:5]); string(p[0:n]) != "abcd" || err != nil {893 t.Fatalf("Read after peek = %q, %v; want abcd, EOF", p[0:n], err)894 }895 if n, err := buf.Read(p[0:1]); string(p[0:n]) != "" || err != io.EOF {896 t.Fatalf(`second Read after peek = %q, %v; want "", EOF`, p[0:n], err)897 }898}899 900type dataAndEOFReader string901 902func (r dataAndEOFReader) Read(p []byte) (int, error) {903 return copy(p, r), io.EOF904}905 906func TestPeekThenUnreadRune(t *testing.T) {907 // This sequence used to cause a crash.908 r := NewReader(strings.NewReader("x"))909 r.ReadRune()910 r.Peek(1)911 r.UnreadRune()912 r.ReadRune() // Used to panic here913}914 915var testOutput = []byte("0123456789abcdefghijklmnopqrstuvwxy")916var testInput = []byte("012\n345\n678\n9ab\ncde\nfgh\nijk\nlmn\nopq\nrst\nuvw\nxy")917var testInputrn = []byte("012\r\n345\r\n678\r\n9ab\r\ncde\r\nfgh\r\nijk\r\nlmn\r\nopq\r\nrst\r\nuvw\r\nxy\r\n\n\r\n")918 919// TestReader wraps a []byte and returns reads of a specific length.920type testReader struct {921 data []byte922 stride int923}924 925func (t *testReader) Read(buf []byte) (n int, err error) {926 n = t.stride927 if n > len(t.data) {928 n = len(t.data)929 }930 if n > len(buf) {931 n = len(buf)932 }933 copy(buf, t.data)934 t.data = t.data[n:]935 if len(t.data) == 0 {936 err = io.EOF937 }938 return939}940 941func testReadLine(t *testing.T, input []byte) {942 for stride := 1; stride < 2; stride++ {943 done := 0944 reader := testReader{input, stride}945 l := NewReaderSize(&reader, len(input)+1)946 for {947 line, isPrefix, err := l.ReadLine()948 if len(line) > 0 && err != nil {949 t.Errorf("ReadLine returned both data and error: %s", err)950 }951 if isPrefix {952 t.Errorf("ReadLine returned prefix")953 }954 if err != nil {955 if err != io.EOF {956 t.Fatalf("Got unknown error: %s", err)957 }958 break959 }960 if want := testOutput[done : done+len(line)]; !bytes.Equal(want, line) {961 t.Errorf("Bad line at stride %d: want: %x got: %x", stride, want, line)962 }963 done += len(line)964 }965 if done != len(testOutput) {966 t.Errorf("ReadLine didn't return everything: got: %d, want: %d (stride: %d)", done, len(testOutput), stride)967 }968 }969}970 971func TestReadLine(t *testing.T) {972 testReadLine(t, testInput)973 testReadLine(t, testInputrn)974}975 976func TestLineTooLong(t *testing.T) {977 data := make([]byte, 0)978 for i := 0; i < minReadBufferSize*5/2; i++ {979 data = append(data, '0'+byte(i%10))980 }981 buf := bytes.NewReader(data)982 l := NewReaderSize(buf, minReadBufferSize)983 line, isPrefix, err := l.ReadLine()984 if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil {985 t.Errorf("bad result for first line: got %q want %q %v", line, data[:minReadBufferSize], err)986 }987 data = data[len(line):]988 line, isPrefix, err = l.ReadLine()989 if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil {990 t.Errorf("bad result for second line: got %q want %q %v", line, data[:minReadBufferSize], err)991 }992 data = data[len(line):]993 line, isPrefix, err = l.ReadLine()994 if isPrefix || !bytes.Equal(line, data[:minReadBufferSize/2]) || err != nil {995 t.Errorf("bad result for third line: got %q want %q %v", line, data[:minReadBufferSize/2], err)996 }997 line, isPrefix, err = l.ReadLine()998 if isPrefix || err == nil {999 t.Errorf("expected no more lines: %x %s", line, err)1000 }1001}1002 1003func TestReadAfterLines(t *testing.T) {1004 line1 := "this is line1"1005 restData := "this is line2\nthis is line 3\n"1006 inbuf := bytes.NewReader([]byte(line1 + "\n" + restData))1007 outbuf := new(strings.Builder)1008 maxLineLength := len(line1) + len(restData)/21009 l := NewReaderSize(inbuf, maxLineLength)1010 line, isPrefix, err := l.ReadLine()1011 if isPrefix || err != nil || string(line) != line1 {1012 t.Errorf("bad result for first line: isPrefix=%v err=%v line=%q", isPrefix, err, string(line))1013 }1014 n, err := io.Copy(outbuf, l)1015 if int(n) != len(restData) || err != nil {1016 t.Errorf("bad result for Read: n=%d err=%v", n, err)1017 }1018 if outbuf.String() != restData {1019 t.Errorf("bad result for Read: got %q; expected %q", outbuf.String(), restData)1020 }1021}1022 1023func TestReadEmptyBuffer(t *testing.T) {1024 l := NewReaderSize(new(bytes.Buffer), minReadBufferSize)1025 line, isPrefix, err := l.ReadLine()1026 if err != io.EOF {1027 t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)1028 }1029}1030 1031func TestLinesAfterRead(t *testing.T) {1032 l := NewReaderSize(bytes.NewReader([]byte("foo")), minReadBufferSize)1033 _, err := io.ReadAll(l)1034 if err != nil {1035 t.Error(err)1036 return1037 }1038 1039 line, isPrefix, err := l.ReadLine()1040 if err != io.EOF {1041 t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)1042 }1043}1044 1045func TestReadLineNonNilLineOrError(t *testing.T) {1046 r := NewReader(strings.NewReader("line 1\n"))1047 for i := 0; i < 2; i++ {1048 l, _, err := r.ReadLine()1049 if l != nil && err != nil {1050 t.Fatalf("on line %d/2; ReadLine=%#v, %v; want non-nil line or Error, but not both",1051 i+1, l, err)1052 }1053 }1054}1055 1056type readLineResult struct {1057 line []byte1058 isPrefix bool1059 err error1060}1061 1062var readLineNewlinesTests = []struct {1063 input string1064 expect []readLineResult1065}{1066 {"012345678901234\r\n012345678901234\r\n", []readLineResult{1067 {[]byte("012345678901234"), true, nil},1068 {nil, false, nil},1069 {[]byte("012345678901234"), true, nil},1070 {nil, false, nil},1071 {nil, false, io.EOF},1072 }},1073 {"0123456789012345\r012345678901234\r", []readLineResult{1074 {[]byte("0123456789012345"), true, nil},1075 {[]byte("\r012345678901234"), true, nil},1076 {[]byte("\r"), false, nil},1077 {nil, false, io.EOF},1078 }},1079}1080 1081func TestReadLineNewlines(t *testing.T) {1082 for _, e := range readLineNewlinesTests {1083 testReadLineNewlines(t, e.input, e.expect)1084 }1085}1086 1087func testReadLineNewlines(t *testing.T, input string, expect []readLineResult) {1088 b := NewReaderSize(strings.NewReader(input), minReadBufferSize)1089 for i, e := range expect {1090 line, isPrefix, err := b.ReadLine()1091 if !bytes.Equal(line, e.line) {1092 t.Errorf("%q call %d, line == %q, want %q", input, i, line, e.line)1093 return1094 }1095 if isPrefix != e.isPrefix {1096 t.Errorf("%q call %d, isPrefix == %v, want %v", input, i, isPrefix, e.isPrefix)1097 return1098 }1099 if err != e.err {1100 t.Errorf("%q call %d, err == %v, want %v", input, i, err, e.err)1101 return1102 }1103 }1104}1105 1106func createTestInput(n int) []byte {1107 input := make([]byte, n)1108 for i := range input {1109 // 101 and 251 are arbitrary prime numbers.1110 // The idea is to create an input sequence1111 // which doesn't repeat too frequently.1112 input[i] = byte(i % 251)1113 if i%101 == 0 {1114 input[i] ^= byte(i / 101)1115 }1116 }1117 return input1118}1119 1120func TestReaderWriteTo(t *testing.T) {1121 input := createTestInput(8192)1122 r := NewReader(onlyReader{bytes.NewReader(input)})1123 w := new(bytes.Buffer)1124 if n, err := r.WriteTo(w); err != nil || n != int64(len(input)) {1125 t.Fatalf("r.WriteTo(w) = %d, %v, want %d, nil", n, err, len(input))1126 }1127 1128 for i, val := range w.Bytes() {1129 if val != input[i] {1130 t.Errorf("after write: out[%d] = %#x, want %#x", i, val, input[i])1131 }1132 }1133}1134 1135type errorWriterToTest struct {1136 rn, wn int1137 rerr, werr error1138 expected error1139}1140 1141func (r errorWriterToTest) Read(p []byte) (int, error) {1142 return len(p) * r.rn, r.rerr1143}1144 1145func (w errorWriterToTest) Write(p []byte) (int, error) {1146 return len(p) * w.wn, w.werr1147}1148 1149var errorWriterToTests = []errorWriterToTest{1150 {1, 0, nil, io.ErrClosedPipe, io.ErrClosedPipe},1151 {0, 1, io.ErrClosedPipe, nil, io.ErrClosedPipe},1152 {0, 0, io.ErrUnexpectedEOF, io.ErrClosedPipe, io.ErrUnexpectedEOF},1153 {0, 1, io.EOF, nil, nil},1154}1155 1156func TestReaderWriteToErrors(t *testing.T) {1157 for i, rw := range errorWriterToTests {1158 r := NewReader(rw)1159 if _, err := r.WriteTo(rw); err != rw.expected {1160 t.Errorf("r.WriteTo(errorWriterToTests[%d]) = _, %v, want _,%v", i, err, rw.expected)1161 }1162 }1163}1164 1165func TestWriterReadFrom(t *testing.T) {1166 ws := []func(io.Writer) io.Writer{1167 func(w io.Writer) io.Writer { return onlyWriter{w} },1168 func(w io.Writer) io.Writer { return w },1169 }1170 1171 rs := []func(io.Reader) io.Reader{1172 iotest.DataErrReader,1173 func(r io.Reader) io.Reader { return r },1174 }1175 1176 for ri, rfunc := range rs {1177 for wi, wfunc := range ws {1178 input := createTestInput(8192)1179 b := new(strings.Builder)1180 w := NewWriter(wfunc(b))1181 r := rfunc(bytes.NewReader(input))1182 if n, err := w.ReadFrom(r); err != nil || n != int64(len(input)) {1183 t.Errorf("ws[%d],rs[%d]: w.ReadFrom(r) = %d, %v, want %d, nil", wi, ri, n, err, len(input))1184 continue1185 }1186 if err := w.Flush(); err != nil {1187 t.Errorf("Flush returned %v", err)1188 continue1189 }1190 if got, want := b.String(), string(input); got != want {1191 t.Errorf("ws[%d], rs[%d]:\ngot %q\nwant %q\n", wi, ri, got, want)1192 }1193 }1194 }1195}1196 1197type errorReaderFromTest struct {1198 rn, wn int1199 rerr, werr error1200 expected error