1package fwd
2
3import (
4	"bytes"
5	"io"
6	"math/rand"
7	"testing"
8)
9
10type chunkedWriter struct {
11	w *Writer
12}
13
14// writes 'p' in randomly-sized chunks
15func (c chunkedWriter) Write(p []byte) (int, error) {
16	l := len(p)
17	n := 0
18	for n < l {
19		amt := max(rand.Intn(l-n), 1)      // number of bytes to write; at least 1
20		nn, err := c.w.Write(p[n : n+amt]) //
21		n += nn
22		if err == nil && nn < amt {
23			err = io.ErrShortWrite
24		}
25		if err != nil {
26			return n, err
27		}
28	}
29	return n, nil
30}
31
32// analogous to Write(), but w/ str
33func (c chunkedWriter) WriteString(s string) (int, error) {
34	l := len(s)
35	n := 0
36	for n < l {
37		amt := max(rand.Intn(l-n), 1)            // number of bytes to write; at least 1
38		nn, err := c.w.WriteString(s[n : n+amt]) //
39		n += nn
40		if err == nil && nn < amt {
41			err = io.ErrShortWrite
42		}
43		if err != nil {
44			return n, err
45		}
46	}
47	return n, nil
48}
49
50// writes via random calls to Next()
51type nextWriter struct {
52	wr *Writer
53}
54
55func (c nextWriter) Write(p []byte) (int, error) {
56	l := len(p)
57	n := 0
58	for n < l {
59		amt := max(rand.Intn(l-n), 1) // at least 1 byte
60		fwd, err := c.wr.Next(amt)    // get next (amt) bytes
61		if err != nil {
62
63			// this may happen occasionally
64			if err == io.ErrShortBuffer {
65				if cap(c.wr.buf) >= amt {
66					panic("bad io.ErrShortBuffer")
67				}
68				continue
69			}
70
71			return n, err
72		}
73		if len(fwd) != amt {
74			panic("bad Next() len")
75		}
76		n += copy(fwd, p[n:])
77	}
78	return n, nil
79}
80
81func TestWrite(t *testing.T) {
82	nbts := 4096
83	bts := randomBts(nbts)
84	var buf bytes.Buffer
85	wr := NewWriterSize(&buf, 512)
86
87	if wr.BufferSize() != 512 {
88		t.Fatalf("expected BufferSize() to be %d; found %d", 512, wr.BufferSize())
89	}
90
91	cwr := chunkedWriter{wr}
92	nb, err := cwr.Write(bts)
93	if err != nil {
94		t.Fatal(err)
95	}
96	if nb != nbts {
97		t.Fatalf("expected to write %d bytes; wrote %d bytes", nbts, nb)
98	}
99	err = wr.Flush()
100	if err != nil {
101		t.Fatal(err)
102	}
103
104	if wr.Buffered() != 0 {
105		t.Fatalf("expected 0 buffered bytes; found %d", wr.Buffered())
106	}
107
108	if buf.Len() != nbts {
109		t.Fatalf("wrote %d bytes, but buffer is %d bytes long", nbts, buf.Len())
110	}
111	if !bytes.Equal(bts, buf.Bytes()) {
112		t.Fatal("buf.Bytes() is not the same as the input bytes")
113	}
114}
115
116func TestWriteString(t *testing.T) {
117	nbts := 3998
118	str := string(randomBts(nbts))
119	var buf bytes.Buffer
120	wr := NewWriterSize(&buf, 1137)
121
122	if wr.BufferSize() != 1137 {
123		t.Fatalf("expected BufferSize() to return %d; returned %d", 1137, wr.BufferSize())
124	}
125
126	cwr := chunkedWriter{wr}
127	nb, err := cwr.WriteString(str)
128	if err != nil {
129		t.Fatal(err)
130	}
131	if nb != nbts {
132		t.Fatalf("expected to write %d bytes; wrote %d bytes", nbts, nb)
133	}
134
135	err = wr.Flush()
136	if err != nil {
137		t.Fatal(err)
138	}
139
140	if wr.Buffered() != 0 {
141		t.Fatalf("expected 0 buffered bytes; found %d", wr.Buffered())
142	}
143
144	if buf.Len() != nbts {
145		t.Fatalf("wrote %d bytes, buf buffer is %d bytes long", nbts, buf.Len())
146	}
147	if buf.String() != str {
148		t.Fatal("buf.String() is not the same as input string")
149	}
150}
151
152func TestWriteByte(t *testing.T) {
153	nbts := 3200
154	bts := randomBts(nbts)
155	var buf bytes.Buffer
156	wr := NewWriter(&buf)
157
158	if wr.BufferSize() != DefaultWriterSize {
159		t.Fatalf("expected BufferSize() to return %d; returned %d", DefaultWriterSize, wr.BufferSize())
160	}
161
162	// write byte-by-byte
163	for _, b := range bts {
164		if err := wr.WriteByte(b); err != nil {
165			t.Fatal(err)
166		}
167	}
168
169	err := wr.Flush()
170	if err != nil {
171		t.Fatal(err)
172	}
173
174	if buf.Len() != nbts {
175		t.Fatalf("expected buf.Len() to be %d; got %d", nbts, buf.Len())
176	}
177
178	if !bytes.Equal(buf.Bytes(), bts) {
179		t.Fatal("buf.Bytes() and input are not equal")
180	}
181}
182
183func TestWriterNext(t *testing.T) {
184	nbts := 1871
185	bts := randomBts(nbts)
186	var buf bytes.Buffer
187	wr := NewWriterSize(&buf, 500)
188	nwr := nextWriter{wr}
189
190	nb, err := nwr.Write(bts)
191	if err != nil {
192		t.Fatal(err)
193	}
194
195	if nb != nbts {
196		t.Fatalf("expected to write %d bytes; wrote %d", nbts, nb)
197	}
198
199	err = wr.Flush()
200	if err != nil {
201		t.Fatal(err)
202	}
203
204	if buf.Len() != nbts {
205		t.Fatalf("expected buf.Len() to be %d; got %d", nbts, buf.Len())
206	}
207
208	if !bytes.Equal(buf.Bytes(), bts) {
209		t.Fatal("buf.Bytes() and input are not equal")
210	}
211}
212
213func TestReadFrom(t *testing.T) {
214	nbts := 2139
215	bts := randomBts(nbts)
216	var buf bytes.Buffer
217	wr := NewWriterSize(&buf, 987)
218
219	rd := partialReader{bytes.NewReader(bts)}
220
221	nb, err := wr.ReadFrom(rd)
222	if err != nil {
223		t.Fatal(err)
224	}
225	if nb != int64(nbts) {
226		t.Fatalf("expeted to write %d bytes; wrote %d", nbts, nb)
227	}
228	err = wr.Flush()
229	if err != nil {
230		t.Fatal(err)
231	}
232	if buf.Len() != nbts {
233		t.Fatalf("expected buf.Len() to be %d; got %d", nbts, buf.Len())
234	}
235	if !bytes.Equal(buf.Bytes(), bts) {
236		t.Fatal("buf.Bytes() and input are not equal")
237	}
238
239}
240