Skip to content

Commit 4b9bfe1

Browse files
committed
Initial tests
Add Encoder/Decoder testing for COBS. Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
1 parent 5ea341b commit 4b9bfe1

1 file changed

Lines changed: 299 additions & 0 deletions

File tree

cobs_test.go

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
package cobs
2+
3+
import (
4+
"bufio"
5+
"bytes"
6+
"io"
7+
"sync"
8+
"testing"
9+
)
10+
11+
var testCases = []struct {
12+
name string
13+
dec, enc []byte
14+
}{
15+
{
16+
name: "Empty",
17+
dec: []byte{},
18+
enc: []byte{0x01},
19+
},
20+
{
21+
name: "1 character",
22+
dec: []byte{'1'},
23+
enc: []byte{0x02, '1'},
24+
},
25+
{
26+
name: "1 zero",
27+
dec: []byte{0x00},
28+
enc: []byte{0x01, 0x01},
29+
},
30+
{
31+
name: "2 zeroes",
32+
dec: []byte{0x00, 0x00},
33+
enc: []byte{0x01, 0x01, 0x01},
34+
},
35+
{
36+
name: "3 zeroes",
37+
dec: []byte{0x00, 0x00, 0x00},
38+
enc: []byte{0x01, 0x01, 0x01, 0x01},
39+
},
40+
{
41+
name: "5 characters",
42+
dec: []byte("12345"),
43+
enc: []byte("\x0612345"),
44+
},
45+
{
46+
name: "Embedded zero",
47+
dec: []byte("12345\x006789"),
48+
enc: []byte("\x0612345\x056789"),
49+
},
50+
{
51+
name: "Starting and embedded zero",
52+
dec: []byte("\x0012345\x006789"),
53+
enc: []byte("\x01\x0612345\x056789"),
54+
},
55+
{
56+
name: "Embedded and trailing zero",
57+
dec: []byte("12345\x006789\x00"),
58+
enc: []byte("\x0612345\x056789\x01"),
59+
},
60+
{
61+
name: "253 non-zero bytes",
62+
dec: []byte("0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEF" +
63+
"GHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdef" +
64+
"ghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst012345" +
65+
"6789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst123"),
66+
enc: []byte("\xfe0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789AB" +
67+
"CDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTab" +
68+
"cdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst01" +
69+
"23456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst123"),
70+
},
71+
{
72+
name: "254 non-zero bytes",
73+
dec: []byte("0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEF" +
74+
"GHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdef" +
75+
"ghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst012345" +
76+
"6789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst1234"),
77+
enc: []byte("\xff0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789AB" +
78+
"CDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTab" +
79+
"cdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst01" +
80+
"23456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst1234"),
81+
},
82+
{
83+
name: "255 non-zero bytes",
84+
dec: []byte("0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEF" +
85+
"GHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdef" +
86+
"ghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst012345" +
87+
"6789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst12345"),
88+
enc: []byte("\xff0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789AB" +
89+
"CDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTab" +
90+
"cdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst01" +
91+
"23456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst1234\x025"),
92+
},
93+
{
94+
name: "zero followed by 255 non-zero bytes",
95+
dec: []byte("\x000123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789AB" +
96+
"CDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTab" +
97+
"cdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst01" +
98+
"23456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst12345"),
99+
enc: []byte("\x01\xff0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst01234567" +
100+
"89ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQR" +
101+
"STabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqr" +
102+
"st0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst1234\x025"),
103+
},
104+
{
105+
name: "253 non-zero bytes followed by zero",
106+
dec: []byte("0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEF" +
107+
"GHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdef" +
108+
"ghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst012345" +
109+
"6789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst123\x00"),
110+
enc: []byte("\xfe0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789AB" +
111+
"CDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTab" +
112+
"cdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst01" +
113+
"23456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst123\x01"),
114+
},
115+
{
116+
name: "254 non-zero bytes followed by zero",
117+
dec: []byte("0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEF" +
118+
"GHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdef" +
119+
"ghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst012345" +
120+
"6789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst1234\x00"),
121+
enc: []byte("\xff0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789AB" +
122+
"CDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTab" +
123+
"cdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst01" +
124+
"23456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst1234\x01\x01"),
125+
},
126+
{
127+
name: "255 non-zero bytes followed by zero",
128+
dec: []byte("0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEF" +
129+
"GHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdef" +
130+
"ghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst012345" +
131+
"6789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst12345\x00"),
132+
enc: []byte("\xff0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789AB" +
133+
"CDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTab" +
134+
"cdefghijklmnopqrst0123456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst01" +
135+
"23456789ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst1234\x025\x01"),
136+
},
137+
}
138+
139+
func TestEncode(t *testing.T) {
140+
for _, tc := range testCases {
141+
t.Run(tc.name, func(t *testing.T) {
142+
enc, err := Encode(tc.dec)
143+
if err != nil {
144+
t.Errorf("encode error: %v", err)
145+
}
146+
if !bytes.Equal(enc, tc.enc) {
147+
t.Errorf("got %v, want %v", enc, tc.enc)
148+
}
149+
})
150+
}
151+
}
152+
153+
func TestDecode(t *testing.T) {
154+
for _, tc := range testCases {
155+
t.Run(tc.name, func(t *testing.T) {
156+
dec, err := Decode(tc.enc)
157+
if err != nil {
158+
t.Errorf("decode error: %v", err)
159+
}
160+
if !bytes.Equal(dec, tc.dec) {
161+
t.Errorf("got %v, want %v", dec, tc.dec)
162+
}
163+
})
164+
}
165+
}
166+
167+
func TestWriter(t *testing.T) {
168+
for _, tc := range testCases {
169+
t.Run(tc.name, func(t *testing.T) {
170+
buf := bytes.NewBuffer(make([]byte, 0, len(tc.enc)))
171+
e := NewEncoder(NewDecoder(buf))
172+
173+
n, err := e.Write(tc.dec)
174+
if err != nil {
175+
t.Errorf("writer error: %v", err)
176+
}
177+
err = e.Close()
178+
if err != nil {
179+
t.Errorf("writer close error: %v", err)
180+
}
181+
if n != len(tc.dec) {
182+
t.Errorf("writer length got %d, want %d", n, len(tc.dec))
183+
}
184+
if !bytes.Equal(buf.Bytes(), tc.dec) {
185+
t.Errorf("got %v, want %v", buf.Bytes(), tc.dec)
186+
}
187+
})
188+
}
189+
}
190+
191+
func TestStream(t *testing.T) {
192+
var err error
193+
var wg sync.WaitGroup
194+
195+
pr, pw := io.Pipe()
196+
defer pw.Close()
197+
198+
go func() {
199+
r := bufio.NewReader(pr)
200+
201+
var buf bytes.Buffer
202+
d := NewDecoder(&buf)
203+
204+
for i := 0; ; i++ {
205+
// Read until delimiter
206+
tmp, err := r.ReadBytes(Delimiter)
207+
if err != nil {
208+
if err != io.EOF {
209+
t.Errorf("pipe error: %v", err)
210+
}
211+
return
212+
}
213+
214+
_, err = d.Write(tmp)
215+
if err != EOD {
216+
t.Error("stream decode EOD missing")
217+
}
218+
if !bytes.Equal(buf.Bytes(), testCases[i].dec) {
219+
t.Errorf("stream decode got %v, want %v", buf.Bytes(), testCases[i].dec)
220+
}
221+
222+
buf.Reset()
223+
224+
t.Logf("stream decode %s", testCases[i].name)
225+
wg.Done()
226+
}
227+
228+
}()
229+
230+
e := NewEncoder(pw)
231+
for _, tc := range testCases {
232+
wg.Add(1)
233+
234+
_, err = e.Write(tc.dec)
235+
if err != nil {
236+
t.Errorf("stream encode error: %v", err)
237+
}
238+
err = e.Close()
239+
if err != nil {
240+
t.Errorf("stream close error: %v", err)
241+
}
242+
243+
_, err = pw.Write([]byte{Delimiter})
244+
if err != nil {
245+
t.Errorf("stream delimiter error: %v", err)
246+
}
247+
}
248+
249+
wg.Wait()
250+
}
251+
252+
func FuzzEncodeDecode(f *testing.F) {
253+
for _, tc := range testCases {
254+
f.Add(tc.dec)
255+
}
256+
f.Fuzz(func(t *testing.T, a []byte) {
257+
enc, err := Encode(a)
258+
if err != nil {
259+
t.Errorf("fuzz encode error: %v", err)
260+
}
261+
if i := bytes.IndexByte(enc, Delimiter); i != -1 {
262+
t.Errorf("fuzz encode %v has delimiter at %d", enc, i)
263+
}
264+
265+
dec, err := Decode(enc)
266+
if err != nil {
267+
t.Errorf("fuzz decode error: %v", err)
268+
}
269+
if !bytes.Equal(dec, a) {
270+
t.Errorf("fuzz decode got %v want %v", dec, a)
271+
}
272+
})
273+
}
274+
275+
func FuzzChainWriter(f *testing.F) {
276+
for _, tc := range testCases {
277+
f.Add(tc.dec)
278+
}
279+
f.Fuzz(func(t *testing.T, a []byte) {
280+
var buf bytes.Buffer
281+
e := NewEncoder(NewDecoder(&buf))
282+
283+
n, err := e.Write(a)
284+
if err != nil {
285+
t.Errorf("fuzz chain error: %v", err)
286+
}
287+
if n != len(a) {
288+
t.Errorf("fuzz chain length got %d want %d", n, len(a))
289+
}
290+
291+
err = e.Close()
292+
if err != nil {
293+
t.Errorf("fuzz chain close error: %v", err)
294+
}
295+
if !bytes.Equal(buf.Bytes(), a) {
296+
t.Errorf("fuzz chain got %v want %v", buf.Bytes(), a)
297+
}
298+
})
299+
}

0 commit comments

Comments
 (0)