Source file src/io/io_test.go

     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 io_test
     6  
     7  import (
     8  	"bytes"
     9  	"errors"
    10  	"fmt"
    11  	. "io"
    12  	"strings"
    13  	"testing"
    14  )
    15  
    16  // A version of bytes.Buffer without ReadFrom and WriteTo
    17  type Buffer struct {
    18  	bytes.Buffer
    19  	ReaderFrom // conflicts with and hides bytes.Buffer's ReaderFrom.
    20  	WriterTo   // conflicts with and hides bytes.Buffer's WriterTo.
    21  }
    22  
    23  // Simple tests, primarily to verify the ReadFrom and WriteTo callouts inside Copy, CopyBuffer and CopyN.
    24  
    25  func TestCopy(t *testing.T) {
    26  	rb := new(Buffer)
    27  	wb := new(Buffer)
    28  	rb.WriteString("hello, world.")
    29  	Copy(wb, rb)
    30  	if wb.String() != "hello, world." {
    31  		t.Errorf("Copy did not work properly")
    32  	}
    33  }
    34  
    35  func TestCopyNegative(t *testing.T) {
    36  	rb := new(Buffer)
    37  	wb := new(Buffer)
    38  	rb.WriteString("hello")
    39  	Copy(wb, &LimitedReader{R: rb, N: -1})
    40  	if wb.String() != "" {
    41  		t.Errorf("Copy on LimitedReader with N<0 copied data")
    42  	}
    43  
    44  	CopyN(wb, rb, -1)
    45  	if wb.String() != "" {
    46  		t.Errorf("CopyN with N<0 copied data")
    47  	}
    48  }
    49  
    50  func TestCopyBuffer(t *testing.T) {
    51  	rb := new(Buffer)
    52  	wb := new(Buffer)
    53  	rb.WriteString("hello, world.")
    54  	CopyBuffer(wb, rb, make([]byte, 1)) // Tiny buffer to keep it honest.
    55  	if wb.String() != "hello, world." {
    56  		t.Errorf("CopyBuffer did not work properly")
    57  	}
    58  }
    59  
    60  func TestCopyBufferNil(t *testing.T) {
    61  	rb := new(Buffer)
    62  	wb := new(Buffer)
    63  	rb.WriteString("hello, world.")
    64  	CopyBuffer(wb, rb, nil) // Should allocate a buffer.
    65  	if wb.String() != "hello, world." {
    66  		t.Errorf("CopyBuffer did not work properly")
    67  	}
    68  }
    69  
    70  func TestCopyReadFrom(t *testing.T) {
    71  	rb := new(Buffer)
    72  	wb := new(bytes.Buffer) // implements ReadFrom.
    73  	rb.WriteString("hello, world.")
    74  	Copy(wb, rb)
    75  	if wb.String() != "hello, world." {
    76  		t.Errorf("Copy did not work properly")
    77  	}
    78  }
    79  
    80  func TestCopyWriteTo(t *testing.T) {
    81  	rb := new(bytes.Buffer) // implements WriteTo.
    82  	wb := new(Buffer)
    83  	rb.WriteString("hello, world.")
    84  	Copy(wb, rb)
    85  	if wb.String() != "hello, world." {
    86  		t.Errorf("Copy did not work properly")
    87  	}
    88  }
    89  
    90  // Version of bytes.Buffer that checks whether WriteTo was called or not
    91  type writeToChecker struct {
    92  	bytes.Buffer
    93  	writeToCalled bool
    94  }
    95  
    96  func (wt *writeToChecker) WriteTo(w Writer) (int64, error) {
    97  	wt.writeToCalled = true
    98  	return wt.Buffer.WriteTo(w)
    99  }
   100  
   101  // It's preferable to choose WriterTo over ReaderFrom, since a WriterTo can issue one large write,
   102  // while the ReaderFrom must read until EOF, potentially allocating when running out of buffer.
   103  // Make sure that we choose WriterTo when both are implemented.
   104  func TestCopyPriority(t *testing.T) {
   105  	rb := new(writeToChecker)
   106  	wb := new(bytes.Buffer)
   107  	rb.WriteString("hello, world.")
   108  	Copy(wb, rb)
   109  	if wb.String() != "hello, world." {
   110  		t.Errorf("Copy did not work properly")
   111  	} else if !rb.writeToCalled {
   112  		t.Errorf("WriteTo was not prioritized over ReadFrom")
   113  	}
   114  }
   115  
   116  type zeroErrReader struct {
   117  	err error
   118  }
   119  
   120  func (r zeroErrReader) Read(p []byte) (int, error) {
   121  	return copy(p, []byte{0}), r.err
   122  }
   123  
   124  type errWriter struct {
   125  	err error
   126  }
   127  
   128  func (w errWriter) Write([]byte) (int, error) {
   129  	return 0, w.err
   130  }
   131  
   132  // In case a Read results in an error with non-zero bytes read, and
   133  // the subsequent Write also results in an error, the error from Write
   134  // is returned, as it is the one that prevented progressing further.
   135  func TestCopyReadErrWriteErr(t *testing.T) {
   136  	er, ew := errors.New("readError"), errors.New("writeError")
   137  	r, w := zeroErrReader{err: er}, errWriter{err: ew}
   138  	n, err := Copy(w, r)
   139  	if n != 0 || err != ew {
   140  		t.Errorf("Copy(zeroErrReader, errWriter) = %d, %v; want 0, writeError", n, err)
   141  	}
   142  }
   143  
   144  func TestCopyN(t *testing.T) {
   145  	rb := new(Buffer)
   146  	wb := new(Buffer)
   147  	rb.WriteString("hello, world.")
   148  	CopyN(wb, rb, 5)
   149  	if wb.String() != "hello" {
   150  		t.Errorf("CopyN did not work properly")
   151  	}
   152  }
   153  
   154  func TestCopyNReadFrom(t *testing.T) {
   155  	rb := new(Buffer)
   156  	wb := new(bytes.Buffer) // implements ReadFrom.
   157  	rb.WriteString("hello")
   158  	CopyN(wb, rb, 5)
   159  	if wb.String() != "hello" {
   160  		t.Errorf("CopyN did not work properly")
   161  	}
   162  }
   163  
   164  func TestCopyNWriteTo(t *testing.T) {
   165  	rb := new(bytes.Buffer) // implements WriteTo.
   166  	wb := new(Buffer)
   167  	rb.WriteString("hello, world.")
   168  	CopyN(wb, rb, 5)
   169  	if wb.String() != "hello" {
   170  		t.Errorf("CopyN did not work properly")
   171  	}
   172  }
   173  
   174  func BenchmarkCopyNSmall(b *testing.B) {
   175  	bs := bytes.Repeat([]byte{0}, 512+1)
   176  	rd := bytes.NewReader(bs)
   177  	buf := new(Buffer)
   178  	b.ResetTimer()
   179  
   180  	for i := 0; i < b.N; i++ {
   181  		CopyN(buf, rd, 512)
   182  		rd.Reset(bs)
   183  	}
   184  }
   185  
   186  func BenchmarkCopyNLarge(b *testing.B) {
   187  	bs := bytes.Repeat([]byte{0}, (32*1024)+1)
   188  	rd := bytes.NewReader(bs)
   189  	buf := new(Buffer)
   190  	b.ResetTimer()
   191  
   192  	for i := 0; i < b.N; i++ {
   193  		CopyN(buf, rd, 32*1024)
   194  		rd.Reset(bs)
   195  	}
   196  }
   197  
   198  type noReadFrom struct {
   199  	w Writer
   200  }
   201  
   202  func (w *noReadFrom) Write(p []byte) (n int, err error) {
   203  	return w.w.Write(p)
   204  }
   205  
   206  type wantedAndErrReader struct{}
   207  
   208  func (wantedAndErrReader) Read(p []byte) (int, error) {
   209  	return len(p), errors.New("wantedAndErrReader error")
   210  }
   211  
   212  func TestCopyNEOF(t *testing.T) {
   213  	// Test that EOF behavior is the same regardless of whether
   214  	// argument to CopyN has ReadFrom.
   215  
   216  	b := new(bytes.Buffer)
   217  
   218  	n, err := CopyN(&noReadFrom{b}, strings.NewReader("foo"), 3)
   219  	if n != 3 || err != nil {
   220  		t.Errorf("CopyN(noReadFrom, foo, 3) = %d, %v; want 3, nil", n, err)
   221  	}
   222  
   223  	n, err = CopyN(&noReadFrom{b}, strings.NewReader("foo"), 4)
   224  	if n != 3 || err != EOF {
   225  		t.Errorf("CopyN(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n, err)
   226  	}
   227  
   228  	n, err = CopyN(b, strings.NewReader("foo"), 3) // b has read from
   229  	if n != 3 || err != nil {
   230  		t.Errorf("CopyN(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n, err)
   231  	}
   232  
   233  	n, err = CopyN(b, strings.NewReader("foo"), 4) // b has read from
   234  	if n != 3 || err != EOF {
   235  		t.Errorf("CopyN(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err)
   236  	}
   237  
   238  	n, err = CopyN(b, wantedAndErrReader{}, 5)
   239  	if n != 5 || err != nil {
   240  		t.Errorf("CopyN(bytes.Buffer, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err)
   241  	}
   242  
   243  	n, err = CopyN(&noReadFrom{b}, wantedAndErrReader{}, 5)
   244  	if n != 5 || err != nil {
   245  		t.Errorf("CopyN(noReadFrom, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err)
   246  	}
   247  }
   248  
   249  func TestReadAtLeast(t *testing.T) {
   250  	var rb bytes.Buffer
   251  	testReadAtLeast(t, &rb)
   252  }
   253  
   254  // A version of bytes.Buffer that returns n > 0, err on Read
   255  // when the input is exhausted.
   256  type dataAndErrorBuffer struct {
   257  	err error
   258  	bytes.Buffer
   259  }
   260  
   261  func (r *dataAndErrorBuffer) Read(p []byte) (n int, err error) {
   262  	n, err = r.Buffer.Read(p)
   263  	if n > 0 && r.Buffer.Len() == 0 && err == nil {
   264  		err = r.err
   265  	}
   266  	return
   267  }
   268  
   269  func TestReadAtLeastWithDataAndEOF(t *testing.T) {
   270  	var rb dataAndErrorBuffer
   271  	rb.err = EOF
   272  	testReadAtLeast(t, &rb)
   273  }
   274  
   275  func TestReadAtLeastWithDataAndError(t *testing.T) {
   276  	var rb dataAndErrorBuffer
   277  	rb.err = fmt.Errorf("fake error")
   278  	testReadAtLeast(t, &rb)
   279  }
   280  
   281  func testReadAtLeast(t *testing.T, rb ReadWriter) {
   282  	rb.Write([]byte("0123"))
   283  	buf := make([]byte, 2)
   284  	n, err := ReadAtLeast(rb, buf, 2)
   285  	if err != nil {
   286  		t.Error(err)
   287  	}
   288  	if n != 2 {
   289  		t.Errorf("expected to have read 2 bytes, got %v", n)
   290  	}
   291  	n, err = ReadAtLeast(rb, buf, 4)
   292  	if err != ErrShortBuffer {
   293  		t.Errorf("expected ErrShortBuffer got %v", err)
   294  	}
   295  	if n != 0 {
   296  		t.Errorf("expected to have read 0 bytes, got %v", n)
   297  	}
   298  	n, err = ReadAtLeast(rb, buf, 1)
   299  	if err != nil {
   300  		t.Error(err)
   301  	}
   302  	if n != 2 {
   303  		t.Errorf("expected to have read 2 bytes, got %v", n)
   304  	}
   305  	n, err = ReadAtLeast(rb, buf, 2)
   306  	if err != EOF {
   307  		t.Errorf("expected EOF, got %v", err)
   308  	}
   309  	if n != 0 {
   310  		t.Errorf("expected to have read 0 bytes, got %v", n)
   311  	}
   312  	rb.Write([]byte("4"))
   313  	n, err = ReadAtLeast(rb, buf, 2)
   314  	want := ErrUnexpectedEOF
   315  	if rb, ok := rb.(*dataAndErrorBuffer); ok && rb.err != EOF {
   316  		want = rb.err
   317  	}
   318  	if err != want {
   319  		t.Errorf("expected %v, got %v", want, err)
   320  	}
   321  	if n != 1 {
   322  		t.Errorf("expected to have read 1 bytes, got %v", n)
   323  	}
   324  }
   325  
   326  func TestTeeReader(t *testing.T) {
   327  	src := []byte("hello, world")
   328  	dst := make([]byte, len(src))
   329  	rb := bytes.NewBuffer(src)
   330  	wb := new(bytes.Buffer)
   331  	r := TeeReader(rb, wb)
   332  	if n, err := ReadFull(r, dst); err != nil || n != len(src) {
   333  		t.Fatalf("ReadFull(r, dst) = %d, %v; want %d, nil", n, err, len(src))
   334  	}
   335  	if !bytes.Equal(dst, src) {
   336  		t.Errorf("bytes read = %q want %q", dst, src)
   337  	}
   338  	if !bytes.Equal(wb.Bytes(), src) {
   339  		t.Errorf("bytes written = %q want %q", wb.Bytes(), src)
   340  	}
   341  	if n, err := r.Read(dst); n != 0 || err != EOF {
   342  		t.Errorf("r.Read at EOF = %d, %v want 0, EOF", n, err)
   343  	}
   344  	rb = bytes.NewBuffer(src)
   345  	pr, pw := Pipe()
   346  	pr.Close()
   347  	r = TeeReader(rb, pw)
   348  	if n, err := ReadFull(r, dst); n != 0 || err != ErrClosedPipe {
   349  		t.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n, err)
   350  	}
   351  }
   352  
   353  func TestSectionReader_ReadAt(t *testing.T) {
   354  	dat := "a long sample data, 1234567890"
   355  	tests := []struct {
   356  		data   string
   357  		off    int
   358  		n      int
   359  		bufLen int
   360  		at     int
   361  		exp    string
   362  		err    error
   363  	}{
   364  		{data: "", off: 0, n: 10, bufLen: 2, at: 0, exp: "", err: EOF},
   365  		{data: dat, off: 0, n: len(dat), bufLen: 0, at: 0, exp: "", err: nil},
   366  		{data: dat, off: len(dat), n: 1, bufLen: 1, at: 0, exp: "", err: EOF},
   367  		{data: dat, off: 0, n: len(dat) + 2, bufLen: len(dat), at: 0, exp: dat, err: nil},
   368  		{data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 0, exp: dat[:len(dat)/2], err: nil},
   369  		{data: dat, off: 0, n: len(dat), bufLen: len(dat), at: 0, exp: dat, err: nil},
   370  		{data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[2 : 2+len(dat)/2], err: nil},
   371  		{data: dat, off: 3, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[5 : 5+len(dat)/2], err: nil},
   372  		{data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 - 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: nil},
   373  		{data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 + 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: EOF},
   374  		{data: dat, off: 0, n: 0, bufLen: 0, at: -1, exp: "", err: EOF},
   375  		{data: dat, off: 0, n: 0, bufLen: 0, at: 1, exp: "", err: EOF},
   376  	}
   377  	for i, tt := range tests {
   378  		r := strings.NewReader(tt.data)
   379  		s := NewSectionReader(r, int64(tt.off), int64(tt.n))
   380  		buf := make([]byte, tt.bufLen)
   381  		if n, err := s.ReadAt(buf, int64(tt.at)); n != len(tt.exp) || string(buf[:n]) != tt.exp || err != tt.err {
   382  			t.Fatalf("%d: ReadAt(%d) = %q, %v; expected %q, %v", i, tt.at, buf[:n], err, tt.exp, tt.err)
   383  		}
   384  	}
   385  }
   386  
   387  func TestSectionReader_Seek(t *testing.T) {
   388  	// Verifies that NewSectionReader's Seeker behaves like bytes.NewReader (which is like strings.NewReader)
   389  	br := bytes.NewReader([]byte("foo"))
   390  	sr := NewSectionReader(br, 0, int64(len("foo")))
   391  
   392  	for _, whence := range []int{SeekStart, SeekCurrent, SeekEnd} {
   393  		for offset := int64(-3); offset <= 4; offset++ {
   394  			brOff, brErr := br.Seek(offset, whence)
   395  			srOff, srErr := sr.Seek(offset, whence)
   396  			if (brErr != nil) != (srErr != nil) || brOff != srOff {
   397  				t.Errorf("For whence %d, offset %d: bytes.Reader.Seek = (%v, %v) != SectionReader.Seek = (%v, %v)",
   398  					whence, offset, brOff, brErr, srErr, srOff)
   399  			}
   400  		}
   401  	}
   402  
   403  	// And verify we can just seek past the end and get an EOF
   404  	got, err := sr.Seek(100, SeekStart)
   405  	if err != nil || got != 100 {
   406  		t.Errorf("Seek = %v, %v; want 100, nil", got, err)
   407  	}
   408  
   409  	n, err := sr.Read(make([]byte, 10))
   410  	if n != 0 || err != EOF {
   411  		t.Errorf("Read = %v, %v; want 0, EOF", n, err)
   412  	}
   413  }
   414  
   415  func TestSectionReader_Size(t *testing.T) {
   416  	tests := []struct {
   417  		data string
   418  		want int64
   419  	}{
   420  		{"a long sample data, 1234567890", 30},
   421  		{"", 0},
   422  	}
   423  
   424  	for _, tt := range tests {
   425  		r := strings.NewReader(tt.data)
   426  		sr := NewSectionReader(r, 0, int64(len(tt.data)))
   427  		if got := sr.Size(); got != tt.want {
   428  			t.Errorf("Size = %v; want %v", got, tt.want)
   429  		}
   430  	}
   431  }
   432  
   433  func TestSectionReader_Max(t *testing.T) {
   434  	r := strings.NewReader("abcdef")
   435  	const maxint64 = 1<<63 - 1
   436  	sr := NewSectionReader(r, 3, maxint64)
   437  	n, err := sr.Read(make([]byte, 3))
   438  	if n != 3 || err != nil {
   439  		t.Errorf("Read = %v %v, want 3, nil", n, err)
   440  	}
   441  	n, err = sr.Read(make([]byte, 3))
   442  	if n != 0 || err != EOF {
   443  		t.Errorf("Read = %v, %v, want 0, EOF", n, err)
   444  	}
   445  }
   446  
   447  // largeWriter returns an invalid count that is larger than the number
   448  // of bytes provided (issue 39978).
   449  type largeWriter struct {
   450  	err error
   451  }
   452  
   453  func (w largeWriter) Write(p []byte) (int, error) {
   454  	return len(p) + 1, w.err
   455  }
   456  
   457  func TestCopyLargeWriter(t *testing.T) {
   458  	want := ErrInvalidWrite
   459  	rb := new(Buffer)
   460  	wb := largeWriter{}
   461  	rb.WriteString("hello, world.")
   462  	if _, err := Copy(wb, rb); err != want {
   463  		t.Errorf("Copy error: got %v, want %v", err, want)
   464  	}
   465  
   466  	want = errors.New("largeWriterError")
   467  	rb = new(Buffer)
   468  	wb = largeWriter{err: want}
   469  	rb.WriteString("hello, world.")
   470  	if _, err := Copy(wb, rb); err != want {
   471  		t.Errorf("Copy error: got %v, want %v", err, want)
   472  	}
   473  }
   474  

View as plain text