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
5package bytes_test
6
7import (
8	. "bytes"
9	"fmt"
10	"io"
11	"io/ioutil"
12	"os"
13	"testing"
14)
15
16func 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		seekerr string
25	}{
26		{seek: os.SEEK_SET, off: 0, n: 20, want: "0123456789"},
27		{seek: os.SEEK_SET, off: 1, n: 1, want: "1"},
28		{seek: os.SEEK_CUR, off: 1, wantpos: 3, n: 2, want: "34"},
29		{seek: os.SEEK_SET, off: -1, seekerr: "bytes: negative position"},
30		{seek: os.SEEK_SET, off: 1<<31 - 1},
31		{seek: os.SEEK_CUR, off: 1, seekerr: "bytes: position out of range"},
32		{seek: os.SEEK_SET, n: 5, want: "01234"},
33		{seek: os.SEEK_CUR, n: 5, want: "56789"},
34		{seek: os.SEEK_END, off: -1, n: 1, wantpos: 9, want: "9"},
35	}
36
37	for i, tt := range tests {
38		pos, err := r.Seek(tt.off, tt.seek)
39		if err == nil && tt.seekerr != "" {
40			t.Errorf("%d. want seek error %q", i, tt.seekerr)
41			continue
42		}
43		if err != nil && err.Error() != tt.seekerr {
44			t.Errorf("%d. seek error = %q; want %q", i, err.Error(), tt.seekerr)
45			continue
46		}
47		if tt.wantpos != 0 && tt.wantpos != pos {
48			t.Errorf("%d. pos = %d, want %d", i, pos, tt.wantpos)
49		}
50		buf := make([]byte, tt.n)
51		n, err := r.Read(buf)
52		if err != nil {
53			t.Errorf("%d. read = %v", i, err)
54			continue
55		}
56		got := string(buf[:n])
57		if got != tt.want {
58			t.Errorf("%d. got %q; want %q", i, got, tt.want)
59		}
60	}
61}
62
63func TestReaderAt(t *testing.T) {
64	r := NewReader([]byte("0123456789"))
65	tests := []struct {
66		off     int64
67		n       int
68		want    string
69		wanterr interface{}
70	}{
71		{0, 10, "0123456789", nil},
72		{1, 10, "123456789", io.EOF},
73		{1, 9, "123456789", nil},
74		{11, 10, "", io.EOF},
75		{0, 0, "", nil},
76		{-1, 0, "", "bytes: invalid offset"},
77	}
78	for i, tt := range tests {
79		b := make([]byte, tt.n)
80		rn, err := r.ReadAt(b, tt.off)
81		got := string(b[:rn])
82		if got != tt.want {
83			t.Errorf("%d. got %q; want %q", i, got, tt.want)
84		}
85		if fmt.Sprintf("%v", err) != fmt.Sprintf("%v", tt.wanterr) {
86			t.Errorf("%d. got error = %v; want %v", i, err, tt.wanterr)
87		}
88	}
89}
90
91func TestReaderWriteTo(t *testing.T) {
92	for i := 0; i < 30; i += 3 {
93		var l int
94		if i > 0 {
95			l = len(data) / i
96		}
97		s := data[:l]
98		r := NewReader(testBytes[:l])
99		var b Buffer
100		n, err := r.WriteTo(&b)
101		if expect := int64(len(s)); n != expect {
102			t.Errorf("got %v; want %v", n, expect)
103		}
104		if err != nil {
105			t.Errorf("for length %d: got error = %v; want nil", l, err)
106		}
107		if b.String() != s {
108			t.Errorf("got string %q; want %q", b.String(), s)
109		}
110		if r.Len() != 0 {
111			t.Errorf("reader contains %v bytes; want 0", r.Len())
112		}
113	}
114}
115
116// verify that copying from an empty reader always has the same results,
117// regardless of the presence of a WriteTo method.
118func TestReaderCopyNothing(t *testing.T) {
119	type nErr struct {
120		n   int64
121		err error
122	}
123	type justReader struct {
124		io.Reader
125	}
126	type justWriter struct {
127		io.Writer
128	}
129	discard := justWriter{ioutil.Discard} // hide ReadFrom
130
131	var with, withOut nErr
132	with.n, with.err = io.Copy(discard, NewReader(nil))
133	withOut.n, withOut.err = io.Copy(discard, justReader{NewReader(nil)})
134	if with != withOut {
135		t.Errorf("behavior differs: with = %#v; without: %#v", with, withOut)
136	}
137}
138