Home | History | Annotate | Download | only in bytes
      1 // Copyright 2012 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 	"io/ioutil"
     12 	"sync"
     13 	"testing"
     14 )
     15 
     16 func TestReader(t *testing.T) {
     17 	r := NewReader([]byte("0123456789"))
     18 	tests := []struct {
     19 		off     int64
     20 		seek    int
     21 		n       int
     22 		want    string
     23 		wantpos int64
     24 		readerr error
     25 		seekerr string
     26 	}{
     27 		{seek: io.SeekStart, off: 0, n: 20, want: "0123456789"},
     28 		{seek: io.SeekStart, off: 1, n: 1, want: "1"},
     29 		{seek: io.SeekCurrent, off: 1, wantpos: 3, n: 2, want: "34"},
     30 		{seek: io.SeekStart, off: -1, seekerr: "bytes.Reader.Seek: negative position"},
     31 		{seek: io.SeekStart, off: 1 << 33, wantpos: 1 << 33, readerr: io.EOF},
     32 		{seek: io.SeekCurrent, off: 1, wantpos: 1<<33 + 1, readerr: io.EOF},
     33 		{seek: io.SeekStart, n: 5, want: "01234"},
     34 		{seek: io.SeekCurrent, n: 5, want: "56789"},
     35 		{seek: io.SeekEnd, off: -1, n: 1, wantpos: 9, want: "9"},
     36 	}
     37 
     38 	for i, tt := range tests {
     39 		pos, err := r.Seek(tt.off, tt.seek)
     40 		if err == nil && tt.seekerr != "" {
     41 			t.Errorf("%d. want seek error %q", i, tt.seekerr)
     42 			continue
     43 		}
     44 		if err != nil && err.Error() != tt.seekerr {
     45 			t.Errorf("%d. seek error = %q; want %q", i, err.Error(), tt.seekerr)
     46 			continue
     47 		}
     48 		if tt.wantpos != 0 && tt.wantpos != pos {
     49 			t.Errorf("%d. pos = %d, want %d", i, pos, tt.wantpos)
     50 		}
     51 		buf := make([]byte, tt.n)
     52 		n, err := r.Read(buf)
     53 		if err != tt.readerr {
     54 			t.Errorf("%d. read = %v; want %v", i, err, tt.readerr)
     55 			continue
     56 		}
     57 		got := string(buf[:n])
     58 		if got != tt.want {
     59 			t.Errorf("%d. got %q; want %q", i, got, tt.want)
     60 		}
     61 	}
     62 }
     63 
     64 func TestReadAfterBigSeek(t *testing.T) {
     65 	r := NewReader([]byte("0123456789"))
     66 	if _, err := r.Seek(1<<31+5, io.SeekStart); err != nil {
     67 		t.Fatal(err)
     68 	}
     69 	if n, err := r.Read(make([]byte, 10)); n != 0 || err != io.EOF {
     70 		t.Errorf("Read = %d, %v; want 0, EOF", n, err)
     71 	}
     72 }
     73 
     74 func TestReaderAt(t *testing.T) {
     75 	r := NewReader([]byte("0123456789"))
     76 	tests := []struct {
     77 		off     int64
     78 		n       int
     79 		want    string
     80 		wanterr interface{}
     81 	}{
     82 		{0, 10, "0123456789", nil},
     83 		{1, 10, "123456789", io.EOF},
     84 		{1, 9, "123456789", nil},
     85 		{11, 10, "", io.EOF},
     86 		{0, 0, "", nil},
     87 		{-1, 0, "", "bytes.Reader.ReadAt: negative offset"},
     88 	}
     89 	for i, tt := range tests {
     90 		b := make([]byte, tt.n)
     91 		rn, err := r.ReadAt(b, tt.off)
     92 		got := string(b[:rn])
     93 		if got != tt.want {
     94 			t.Errorf("%d. got %q; want %q", i, got, tt.want)
     95 		}
     96 		if fmt.Sprintf("%v", err) != fmt.Sprintf("%v", tt.wanterr) {
     97 			t.Errorf("%d. got error = %v; want %v", i, err, tt.wanterr)
     98 		}
     99 	}
    100 }
    101 
    102 func TestReaderAtConcurrent(t *testing.T) {
    103 	// Test for the race detector, to verify ReadAt doesn't mutate
    104 	// any state.
    105 	r := NewReader([]byte("0123456789"))
    106 	var wg sync.WaitGroup
    107 	for i := 0; i < 5; i++ {
    108 		wg.Add(1)
    109 		go func(i int) {
    110 			defer wg.Done()
    111 			var buf [1]byte
    112 			r.ReadAt(buf[:], int64(i))
    113 		}(i)
    114 	}
    115 	wg.Wait()
    116 }
    117 
    118 func TestEmptyReaderConcurrent(t *testing.T) {
    119 	// Test for the race detector, to verify a Read that doesn't yield any bytes
    120 	// is okay to use from multiple goroutines. This was our historic behavior.
    121 	// See golang.org/issue/7856
    122 	r := NewReader([]byte{})
    123 	var wg sync.WaitGroup
    124 	for i := 0; i < 5; i++ {
    125 		wg.Add(2)
    126 		go func() {
    127 			defer wg.Done()
    128 			var buf [1]byte
    129 			r.Read(buf[:])
    130 		}()
    131 		go func() {
    132 			defer wg.Done()
    133 			r.Read(nil)
    134 		}()
    135 	}
    136 	wg.Wait()
    137 }
    138 
    139 func TestReaderWriteTo(t *testing.T) {
    140 	for i := 0; i < 30; i += 3 {
    141 		var l int
    142 		if i > 0 {
    143 			l = len(testString) / i
    144 		}
    145 		s := testString[:l]
    146 		r := NewReader(testBytes[:l])
    147 		var b Buffer
    148 		n, err := r.WriteTo(&b)
    149 		if expect := int64(len(s)); n != expect {
    150 			t.Errorf("got %v; want %v", n, expect)
    151 		}
    152 		if err != nil {
    153 			t.Errorf("for length %d: got error = %v; want nil", l, err)
    154 		}
    155 		if b.String() != s {
    156 			t.Errorf("got string %q; want %q", b.String(), s)
    157 		}
    158 		if r.Len() != 0 {
    159 			t.Errorf("reader contains %v bytes; want 0", r.Len())
    160 		}
    161 	}
    162 }
    163 
    164 func TestReaderLen(t *testing.T) {
    165 	const data = "hello world"
    166 	r := NewReader([]byte(data))
    167 	if got, want := r.Len(), 11; got != want {
    168 		t.Errorf("r.Len(): got %d, want %d", got, want)
    169 	}
    170 	if n, err := r.Read(make([]byte, 10)); err != nil || n != 10 {
    171 		t.Errorf("Read failed: read %d %v", n, err)
    172 	}
    173 	if got, want := r.Len(), 1; got != want {
    174 		t.Errorf("r.Len(): got %d, want %d", got, want)
    175 	}
    176 	if n, err := r.Read(make([]byte, 1)); err != nil || n != 1 {
    177 		t.Errorf("Read failed: read %d %v; want 1, nil", n, err)
    178 	}
    179 	if got, want := r.Len(), 0; got != want {
    180 		t.Errorf("r.Len(): got %d, want %d", got, want)
    181 	}
    182 }
    183 
    184 var UnreadRuneErrorTests = []struct {
    185 	name string
    186 	f    func(*Reader)
    187 }{
    188 	{"Read", func(r *Reader) { r.Read([]byte{0}) }},
    189 	{"ReadByte", func(r *Reader) { r.ReadByte() }},
    190 	{"UnreadRune", func(r *Reader) { r.UnreadRune() }},
    191 	{"Seek", func(r *Reader) { r.Seek(0, io.SeekCurrent) }},
    192 	{"WriteTo", func(r *Reader) { r.WriteTo(&Buffer{}) }},
    193 }
    194 
    195 func TestUnreadRuneError(t *testing.T) {
    196 	for _, tt := range UnreadRuneErrorTests {
    197 		reader := NewReader([]byte("0123456789"))
    198 		if _, _, err := reader.ReadRune(); err != nil {
    199 			// should not happen
    200 			t.Fatal(err)
    201 		}
    202 		tt.f(reader)
    203 		err := reader.UnreadRune()
    204 		if err == nil {
    205 			t.Errorf("Unreading after %s: expected error", tt.name)
    206 		}
    207 	}
    208 }
    209 
    210 func TestReaderDoubleUnreadRune(t *testing.T) {
    211 	buf := NewBuffer([]byte("groucho"))
    212 	if _, _, err := buf.ReadRune(); err != nil {
    213 		// should not happen
    214 		t.Fatal(err)
    215 	}
    216 	if err := buf.UnreadByte(); err != nil {
    217 		// should not happen
    218 		t.Fatal(err)
    219 	}
    220 	if err := buf.UnreadByte(); err == nil {
    221 		t.Fatal("UnreadByte: expected error, got nil")
    222 	}
    223 }
    224 
    225 // verify that copying from an empty reader always has the same results,
    226 // regardless of the presence of a WriteTo method.
    227 func TestReaderCopyNothing(t *testing.T) {
    228 	type nErr struct {
    229 		n   int64
    230 		err error
    231 	}
    232 	type justReader struct {
    233 		io.Reader
    234 	}
    235 	type justWriter struct {
    236 		io.Writer
    237 	}
    238 	discard := justWriter{ioutil.Discard} // hide ReadFrom
    239 
    240 	var with, withOut nErr
    241 	with.n, with.err = io.Copy(discard, NewReader(nil))
    242 	withOut.n, withOut.err = io.Copy(discard, justReader{NewReader(nil)})
    243 	if with != withOut {
    244 		t.Errorf("behavior differs: with = %#v; without: %#v", with, withOut)
    245 	}
    246 }
    247 
    248 // tests that Len is affected by reads, but Size is not.
    249 func TestReaderLenSize(t *testing.T) {
    250 	r := NewReader([]byte("abc"))
    251 	io.CopyN(ioutil.Discard, r, 1)
    252 	if r.Len() != 2 {
    253 		t.Errorf("Len = %d; want 2", r.Len())
    254 	}
    255 	if r.Size() != 3 {
    256 		t.Errorf("Size = %d; want 3", r.Size())
    257 	}
    258 }
    259 
    260 func TestReaderReset(t *testing.T) {
    261 	r := NewReader([]byte(""))
    262 	if _, _, err := r.ReadRune(); err != nil {
    263 		t.Errorf("ReadRune: unexpected error: %v", err)
    264 	}
    265 
    266 	const want = "abcdef"
    267 	r.Reset([]byte(want))
    268 	if err := r.UnreadRune(); err == nil {
    269 		t.Errorf("UnreadRune: expected error, got nil")
    270 	}
    271 	buf, err := ioutil.ReadAll(r)
    272 	if err != nil {
    273 		t.Errorf("ReadAll: unexpected error: %v", err)
    274 	}
    275 	if got := string(buf); got != want {
    276 		t.Errorf("ReadAll: got %q, want %q", got, want)
    277 	}
    278 }
    279