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