github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/src/io/io_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 io_test
     6  
     7  import (
     8  	"bytes"
     9  	"errors"
    10  	"fmt"
    11  	. "io"
    12  	"strings"
    13  	"testing"
    14  )
    15  
    16  // An 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 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 TestCopyReadFrom(t *testing.T) {
    36  	rb := new(Buffer)
    37  	wb := new(bytes.Buffer) // implements ReadFrom.
    38  	rb.WriteString("hello, world.")
    39  	Copy(wb, rb)
    40  	if wb.String() != "hello, world." {
    41  		t.Errorf("Copy did not work properly")
    42  	}
    43  }
    44  
    45  func TestCopyWriteTo(t *testing.T) {
    46  	rb := new(bytes.Buffer) // implements WriteTo.
    47  	wb := new(Buffer)
    48  	rb.WriteString("hello, world.")
    49  	Copy(wb, rb)
    50  	if wb.String() != "hello, world." {
    51  		t.Errorf("Copy did not work properly")
    52  	}
    53  }
    54  
    55  // Version of bytes.Buffer that checks whether WriteTo was called or not
    56  type writeToChecker struct {
    57  	bytes.Buffer
    58  	writeToCalled bool
    59  }
    60  
    61  func (wt *writeToChecker) WriteTo(w Writer) (int64, error) {
    62  	wt.writeToCalled = true
    63  	return wt.Buffer.WriteTo(w)
    64  }
    65  
    66  // It's preferable to choose WriterTo over ReaderFrom, since a WriterTo can issue one large write,
    67  // while the ReaderFrom must read until EOF, potentially allocating when running out of buffer.
    68  // Make sure that we choose WriterTo when both are implemented.
    69  func TestCopyPriority(t *testing.T) {
    70  	rb := new(writeToChecker)
    71  	wb := new(bytes.Buffer)
    72  	rb.WriteString("hello, world.")
    73  	Copy(wb, rb)
    74  	if wb.String() != "hello, world." {
    75  		t.Errorf("Copy did not work properly")
    76  	} else if !rb.writeToCalled {
    77  		t.Errorf("WriteTo was not prioritized over ReadFrom")
    78  	}
    79  }
    80  
    81  func TestCopyN(t *testing.T) {
    82  	rb := new(Buffer)
    83  	wb := new(Buffer)
    84  	rb.WriteString("hello, world.")
    85  	CopyN(wb, rb, 5)
    86  	if wb.String() != "hello" {
    87  		t.Errorf("CopyN did not work properly")
    88  	}
    89  }
    90  
    91  func TestCopyNReadFrom(t *testing.T) {
    92  	rb := new(Buffer)
    93  	wb := new(bytes.Buffer) // implements ReadFrom.
    94  	rb.WriteString("hello")
    95  	CopyN(wb, rb, 5)
    96  	if wb.String() != "hello" {
    97  		t.Errorf("CopyN did not work properly")
    98  	}
    99  }
   100  
   101  func TestCopyNWriteTo(t *testing.T) {
   102  	rb := new(bytes.Buffer) // implements WriteTo.
   103  	wb := new(Buffer)
   104  	rb.WriteString("hello, world.")
   105  	CopyN(wb, rb, 5)
   106  	if wb.String() != "hello" {
   107  		t.Errorf("CopyN did not work properly")
   108  	}
   109  }
   110  
   111  type noReadFrom struct {
   112  	w Writer
   113  }
   114  
   115  func (w *noReadFrom) Write(p []byte) (n int, err error) {
   116  	return w.w.Write(p)
   117  }
   118  
   119  type wantedAndErrReader struct{}
   120  
   121  func (wantedAndErrReader) Read(p []byte) (int, error) {
   122  	return len(p), errors.New("wantedAndErrReader error")
   123  }
   124  
   125  func TestCopyNEOF(t *testing.T) {
   126  	// Test that EOF behavior is the same regardless of whether
   127  	// argument to CopyN has ReadFrom.
   128  
   129  	b := new(bytes.Buffer)
   130  
   131  	n, err := CopyN(&noReadFrom{b}, strings.NewReader("foo"), 3)
   132  	if n != 3 || err != nil {
   133  		t.Errorf("CopyN(noReadFrom, foo, 3) = %d, %v; want 3, nil", n, err)
   134  	}
   135  
   136  	n, err = CopyN(&noReadFrom{b}, strings.NewReader("foo"), 4)
   137  	if n != 3 || err != EOF {
   138  		t.Errorf("CopyN(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n, err)
   139  	}
   140  
   141  	n, err = CopyN(b, strings.NewReader("foo"), 3) // b has read from
   142  	if n != 3 || err != nil {
   143  		t.Errorf("CopyN(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n, err)
   144  	}
   145  
   146  	n, err = CopyN(b, strings.NewReader("foo"), 4) // b has read from
   147  	if n != 3 || err != EOF {
   148  		t.Errorf("CopyN(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err)
   149  	}
   150  
   151  	n, err = CopyN(b, wantedAndErrReader{}, 5)
   152  	if n != 5 || err != nil {
   153  		t.Errorf("CopyN(bytes.Buffer, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err)
   154  	}
   155  
   156  	n, err = CopyN(&noReadFrom{b}, wantedAndErrReader{}, 5)
   157  	if n != 5 || err != nil {
   158  		t.Errorf("CopyN(noReadFrom, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err)
   159  	}
   160  }
   161  
   162  func TestReadAtLeast(t *testing.T) {
   163  	var rb bytes.Buffer
   164  	testReadAtLeast(t, &rb)
   165  }
   166  
   167  // A version of bytes.Buffer that returns n > 0, err on Read
   168  // when the input is exhausted.
   169  type dataAndErrorBuffer struct {
   170  	err error
   171  	bytes.Buffer
   172  }
   173  
   174  func (r *dataAndErrorBuffer) Read(p []byte) (n int, err error) {
   175  	n, err = r.Buffer.Read(p)
   176  	if n > 0 && r.Buffer.Len() == 0 && err == nil {
   177  		err = r.err
   178  	}
   179  	return
   180  }
   181  
   182  func TestReadAtLeastWithDataAndEOF(t *testing.T) {
   183  	var rb dataAndErrorBuffer
   184  	rb.err = EOF
   185  	testReadAtLeast(t, &rb)
   186  }
   187  
   188  func TestReadAtLeastWithDataAndError(t *testing.T) {
   189  	var rb dataAndErrorBuffer
   190  	rb.err = fmt.Errorf("fake error")
   191  	testReadAtLeast(t, &rb)
   192  }
   193  
   194  func testReadAtLeast(t *testing.T, rb ReadWriter) {
   195  	rb.Write([]byte("0123"))
   196  	buf := make([]byte, 2)
   197  	n, err := ReadAtLeast(rb, buf, 2)
   198  	if err != nil {
   199  		t.Error(err)
   200  	}
   201  	n, err = ReadAtLeast(rb, buf, 4)
   202  	if err != ErrShortBuffer {
   203  		t.Errorf("expected ErrShortBuffer got %v", err)
   204  	}
   205  	if n != 0 {
   206  		t.Errorf("expected to have read 0 bytes, got %v", n)
   207  	}
   208  	n, err = ReadAtLeast(rb, buf, 1)
   209  	if err != nil {
   210  		t.Error(err)
   211  	}
   212  	if n != 2 {
   213  		t.Errorf("expected to have read 2 bytes, got %v", n)
   214  	}
   215  	n, err = ReadAtLeast(rb, buf, 2)
   216  	if err != EOF {
   217  		t.Errorf("expected EOF, got %v", err)
   218  	}
   219  	if n != 0 {
   220  		t.Errorf("expected to have read 0 bytes, got %v", n)
   221  	}
   222  	rb.Write([]byte("4"))
   223  	n, err = ReadAtLeast(rb, buf, 2)
   224  	want := ErrUnexpectedEOF
   225  	if rb, ok := rb.(*dataAndErrorBuffer); ok && rb.err != EOF {
   226  		want = rb.err
   227  	}
   228  	if err != want {
   229  		t.Errorf("expected %v, got %v", want, err)
   230  	}
   231  	if n != 1 {
   232  		t.Errorf("expected to have read 1 bytes, got %v", n)
   233  	}
   234  }
   235  
   236  func TestTeeReader(t *testing.T) {
   237  	src := []byte("hello, world")
   238  	dst := make([]byte, len(src))
   239  	rb := bytes.NewBuffer(src)
   240  	wb := new(bytes.Buffer)
   241  	r := TeeReader(rb, wb)
   242  	if n, err := ReadFull(r, dst); err != nil || n != len(src) {
   243  		t.Fatalf("ReadFull(r, dst) = %d, %v; want %d, nil", n, err, len(src))
   244  	}
   245  	if !bytes.Equal(dst, src) {
   246  		t.Errorf("bytes read = %q want %q", dst, src)
   247  	}
   248  	if !bytes.Equal(wb.Bytes(), src) {
   249  		t.Errorf("bytes written = %q want %q", wb.Bytes(), src)
   250  	}
   251  	if n, err := r.Read(dst); n != 0 || err != EOF {
   252  		t.Errorf("r.Read at EOF = %d, %v want 0, EOF", n, err)
   253  	}
   254  	rb = bytes.NewBuffer(src)
   255  	pr, pw := Pipe()
   256  	pr.Close()
   257  	r = TeeReader(rb, pw)
   258  	if n, err := ReadFull(r, dst); n != 0 || err != ErrClosedPipe {
   259  		t.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n, err)
   260  	}
   261  }
   262  
   263  func TestSectionReader_ReadAt(t *testing.T) {
   264  	dat := "a long sample data, 1234567890"
   265  	tests := []struct {
   266  		data   string
   267  		off    int
   268  		n      int
   269  		bufLen int
   270  		at     int
   271  		exp    string
   272  		err    error
   273  	}{
   274  		{data: "", off: 0, n: 10, bufLen: 2, at: 0, exp: "", err: EOF},
   275  		{data: dat, off: 0, n: len(dat), bufLen: 0, at: 0, exp: "", err: nil},
   276  		{data: dat, off: len(dat), n: 1, bufLen: 1, at: 0, exp: "", err: EOF},
   277  		{data: dat, off: 0, n: len(dat) + 2, bufLen: len(dat), at: 0, exp: dat, err: nil},
   278  		{data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 0, exp: dat[:len(dat)/2], err: nil},
   279  		{data: dat, off: 0, n: len(dat), bufLen: len(dat), at: 0, exp: dat, err: nil},
   280  		{data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[2 : 2+len(dat)/2], err: nil},
   281  		{data: dat, off: 3, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[5 : 5+len(dat)/2], err: nil},
   282  		{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},
   283  		{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},
   284  		{data: dat, off: 0, n: 0, bufLen: 0, at: -1, exp: "", err: EOF},
   285  		{data: dat, off: 0, n: 0, bufLen: 0, at: 1, exp: "", err: EOF},
   286  	}
   287  	for i, tt := range tests {
   288  		r := strings.NewReader(tt.data)
   289  		s := NewSectionReader(r, int64(tt.off), int64(tt.n))
   290  		buf := make([]byte, tt.bufLen)
   291  		if n, err := s.ReadAt(buf, int64(tt.at)); n != len(tt.exp) || string(buf[:n]) != tt.exp || err != tt.err {
   292  			t.Fatalf("%d: ReadAt(%d) = %q, %v; expected %q, %v", i, tt.at, buf[:n], err, tt.exp, tt.err)
   293  		}
   294  	}
   295  }
   296  
   297  func TestSectionReader_Seek(t *testing.T) {
   298  	// Verifies that NewSectionReader's Seeker behaves like bytes.NewReader (which is like strings.NewReader)
   299  	br := bytes.NewReader([]byte("foo"))
   300  	sr := NewSectionReader(br, 0, int64(len("foo")))
   301  
   302  	for whence := 0; whence <= 2; whence++ {
   303  		for offset := int64(-3); offset <= 4; offset++ {
   304  			brOff, brErr := br.Seek(offset, whence)
   305  			srOff, srErr := sr.Seek(offset, whence)
   306  			if (brErr != nil) != (srErr != nil) || brOff != srOff {
   307  				t.Errorf("For whence %d, offset %d: bytes.Reader.Seek = (%v, %v) != SectionReader.Seek = (%v, %v)",
   308  					whence, offset, brOff, brErr, srErr, srOff)
   309  			}
   310  		}
   311  	}
   312  
   313  	// And verify we can just seek past the end and get an EOF
   314  	got, err := sr.Seek(100, 0)
   315  	if err != nil || got != 100 {
   316  		t.Errorf("Seek = %v, %v; want 100, nil", got, err)
   317  	}
   318  
   319  	n, err := sr.Read(make([]byte, 10))
   320  	if n != 0 || err != EOF {
   321  		t.Errorf("Read = %v, %v; want 0, EOF", n, err)
   322  	}
   323  }
   324  
   325  func TestSectionReader_Size(t *testing.T) {
   326  	tests := []struct {
   327  		data string
   328  		want int64
   329  	}{
   330  		{"a long sample data, 1234567890", 30},
   331  		{"", 0},
   332  	}
   333  
   334  	for _, tt := range tests {
   335  		r := strings.NewReader(tt.data)
   336  		sr := NewSectionReader(r, 0, int64(len(tt.data)))
   337  		if got := sr.Size(); got != tt.want {
   338  			t.Errorf("Size = %v; want %v", got, tt.want)
   339  		}
   340  	}
   341  }