Remove reference to net/url URL.RawFragment.
[champa.git] / encapsulation / encapsulation_test.go
blob56bc4d4251e5ef35ed470adc415b46b54baeb256
1 package encapsulation
3 import (
4 "bytes"
5 "io"
6 "math/rand"
7 "testing"
10 // Return a byte slice with non-trivial contents.
11 func pseudorandomBuffer(n int) []byte {
12 source := rand.NewSource(0)
13 p := make([]byte, n)
14 for i := 0; i < len(p); i++ {
15 p[i] = byte(source.Int63() & 0xff)
17 return p
20 func mustWriteData(w io.Writer, p []byte) int {
21 n, err := WriteData(w, p)
22 if err != nil {
23 panic(err)
25 return n
28 func mustWritePadding(w io.Writer, n int) int {
29 n, err := WritePadding(w, n)
30 if err != nil {
31 panic(err)
33 return n
36 // Test that ReadData(WriteData()) recovers the original data.
37 func TestRoundtrip(t *testing.T) {
38 // Test above and below interesting thresholds.
39 for _, i := range []int{
40 0x00, 0x01,
41 0x3e, 0x3f, 0x40, 0x41,
42 0xfe, 0xff, 0x100, 0x101,
43 0x1ffe, 0x1fff, 0x2000, 0x2001,
44 0xfffe, 0xffff, 0x10000, 0x10001,
45 0xffffe, 0xfffff,
46 } {
47 original := pseudorandomBuffer(i)
48 var enc bytes.Buffer
49 n, err := WriteData(&enc, original)
50 if err != nil {
51 t.Fatalf("size %d, WriteData returned error %v", i, err)
53 if enc.Len() != n {
54 t.Fatalf("size %d, returned length was %d, written length was %d",
55 i, n, enc.Len())
57 inverse, err := ReadData(&enc)
58 if err != nil {
59 t.Fatalf("size %d, ReadData returned error %v", i, err)
61 if !bytes.Equal(inverse, original) {
62 t.Fatalf("size %d, got <%x>, expected <%x>", i, inverse, original)
67 // Test that WritePadding writes exactly as much as requested.
68 func TestPaddingLength(t *testing.T) {
69 // Test above and below interesting thresholds. WritePadding also gets
70 // values above 0xfffff, the maximum value of a single length prefix.
71 for _, i := range []int{
72 0x00, 0x01,
73 0x3f, 0x40, 0x41, 0x42,
74 0xff, 0x100, 0x101, 0x102,
75 0x2000, 0x2001, 0x2002, 0x2003,
76 0x10000, 0x10001, 0x10002, 0x10003,
77 0x100001, 0x100002, 0x100003, 0x100004,
78 } {
79 var enc bytes.Buffer
80 n, err := WritePadding(&enc, i)
81 if err != nil {
82 t.Fatalf("size %d, WritePadding returned error %v", i, err)
84 if n != i {
85 t.Fatalf("requested %d bytes, returned %d", i, n)
87 if enc.Len() != n {
88 t.Fatalf("requested %d bytes, wrote %d bytes", i, enc.Len())
93 // Test that ReadData skips over padding.
94 func TestSkipPadding(t *testing.T) {
95 var data = [][]byte{{}, {}, []byte("hello"), {}, []byte("world")}
96 var enc bytes.Buffer
97 mustWritePadding(&enc, 10)
98 mustWritePadding(&enc, 100)
99 mustWriteData(&enc, data[0])
100 mustWriteData(&enc, data[1])
101 mustWritePadding(&enc, 10)
102 mustWriteData(&enc, data[2])
103 mustWriteData(&enc, data[3])
104 mustWritePadding(&enc, 10)
105 mustWriteData(&enc, data[4])
106 mustWritePadding(&enc, 10)
107 mustWritePadding(&enc, 10)
108 for i, expected := range data {
109 actual, err := ReadData(&enc)
110 if err != nil {
111 t.Fatalf("slice %d, got error %v, expected %v", i, err, nil)
113 if !bytes.Equal(actual, expected) {
114 t.Fatalf("slice %d, got <%x>, expected <%x>", i, actual, expected)
117 p, err := ReadData(&enc)
118 if p != nil || err != io.EOF {
119 t.Fatalf("got (<%x>, %v), expected (%v, %v)", p, err, nil, io.EOF)
123 // Test that EOF before a length prefix returns io.EOF.
124 func TestEOF(t *testing.T) {
125 p, err := ReadData(bytes.NewReader(nil))
126 if p != nil || err != io.EOF {
127 t.Fatalf("got (<%x>, %v), expected (%v, %v)", p, err, nil, io.EOF)
131 // Test that an EOF while reading a length prefix, or while reading the
132 // subsequent data/padding, returns io.ErrUnexpectedEOF.
133 func TestUnexpectedEOF(t *testing.T) {
134 for _, test := range [][]byte{
135 {0x40}, // expecting a second length byte
136 {0xc0}, // expecting a second length byte
137 {0x41, 0x80}, // expecting a third length byte
138 {0xc1, 0x80}, // expecting a third length byte
139 {0x02}, // expecting 2 bytes of padding
140 {0x82}, // expecting 2 bytes of data
141 {0x02, 'X'}, // expecting 1 byte of padding
142 {0x82, 'X'}, // expecting 1 byte of data
143 {0x41, 0x00}, // expecting 128 bytes of padding
144 {0xc1, 0x00}, // expecting 128 bytes of data
145 {0x41, 0x00, 'X'}, // expecting 127 bytes of padding
146 {0xc1, 0x00, 'X'}, // expecting 127 bytes of data
147 {0x41, 0x80, 0x00}, // expecting 32768 bytes of padding
148 {0xc1, 0x80, 0x00}, // expecting 32768 bytes of data
149 {0x41, 0x80, 0x00, 'X'}, // expecting 32767 bytes of padding
150 {0xc1, 0x80, 0x00, 'X'}, // expecting 32767 bytes of data
152 p, err := ReadData(bytes.NewReader(test))
153 if p != nil || err != io.ErrUnexpectedEOF {
154 t.Fatalf("<%x> got (<%x>, %v), expected (%v, %v)", test, p, err, nil, io.ErrUnexpectedEOF)
159 // Test that length encodings that are longer than they could be are still
160 // interpreted.
161 func TestNonMinimalLengthEncoding(t *testing.T) {
162 for _, test := range []struct {
163 enc []byte
164 expected []byte
166 {[]byte{0x81, 'X'}, []byte("X")},
167 {[]byte{0xc0, 0x01, 'X'}, []byte("X")},
168 {[]byte{0xc0, 0x80, 0x01, 'X'}, []byte("X")},
170 p, err := ReadData(bytes.NewReader(test.enc))
171 if err != nil {
172 t.Fatalf("<%x> got error %v, expected %v", test.enc, err, nil)
174 if !bytes.Equal(p, test.expected) {
175 t.Fatalf("<%x> got <%x>, expected <%x>", test.enc, p, test.expected)
180 // Test that ReadData only reads up to 3 bytes of length prefix.
181 func TestReadLimits(t *testing.T) {
182 // Test the maximum length that's possible with 3 bytes of length
183 // prefix.
184 maxLength := (0x3f << 14) | (0x7f << 7) | 0x7f
185 data := bytes.Repeat([]byte{'X'}, maxLength)
186 prefix := []byte{0xff, 0xff, 0x7f}
187 p, err := ReadData(bytes.NewReader(append(prefix, data...)))
188 if err != nil {
189 t.Fatalf("got error %v, expected %v", err, nil)
191 if !bytes.Equal(p, data) {
192 t.Fatalf("got %d bytes unequal to %d bytes", len(p), len(data))
194 // Test a 4-byte prefix.
195 prefix = []byte{0xe0, 0x80, 0x80, 0x80}
196 data = bytes.Repeat([]byte{'X'}, maxLength+1)
197 p, err = ReadData(bytes.NewReader(append(prefix, data...)))
198 if p != nil || err != ErrTooLong {
199 t.Fatalf("got (<%x>, %v), expected (%v, %v)", p, err, nil, ErrTooLong)
201 // Test that 4 bytes don't work, even when they encode an integer that
202 // would fix in 3 bytes.
203 prefix = []byte{0xc0, 0x80, 0x80, 0x80}
204 data = []byte{}
205 p, err = ReadData(bytes.NewReader(append(prefix, data...)))
206 if p != nil || err != ErrTooLong {
207 t.Fatalf("got (<%x>, %v), expected (%v, %v)", p, err, nil, ErrTooLong)
210 // Do the same tests with padding lengths.
211 data = []byte("hello")
212 prefix = []byte{0x7f, 0xff, 0x7f}
213 padding := bytes.Repeat([]byte{'X'}, maxLength)
214 enc := bytes.NewBuffer(append(prefix, padding...))
215 mustWriteData(enc, data)
216 p, err = ReadData(enc)
217 if err != nil {
218 t.Fatalf("got error %v, expected %v", err, nil)
220 if !bytes.Equal(p, data) {
221 t.Fatalf("got <%x>, expected <%x>", p, data)
223 prefix = []byte{0xe0, 0x80, 0x80, 0x80}
224 padding = bytes.Repeat([]byte{'X'}, maxLength+1)
225 enc = bytes.NewBuffer(append(prefix, padding...))
226 mustWriteData(enc, data)
227 p, err = ReadData(enc)
228 if p != nil || err != ErrTooLong {
229 t.Fatalf("got (<%x>, %v), expected (%v, %v)", p, err, nil, ErrTooLong)
231 prefix = []byte{0xc0, 0x80, 0x80, 0x80}
232 padding = []byte{}
233 enc = bytes.NewBuffer(append(prefix, padding...))
234 mustWriteData(enc, data)
235 p, err = ReadData(enc)
236 if p != nil || err != ErrTooLong {
237 t.Fatalf("got (<%x>, %v), expected (%v, %v)", p, err, nil, ErrTooLong)
241 // Test that WriteData and WritePadding only accept lengths that can be encoded
242 // in up to 3 bytes of length prefix.
243 func TestWriteLimits(t *testing.T) {
244 maxLength := (0x3f << 14) | (0x7f << 7) | 0x7f
245 var enc bytes.Buffer
246 n, err := WriteData(&enc, bytes.Repeat([]byte{'X'}, maxLength))
247 if n != maxLength+3 || err != nil {
248 t.Fatalf("got (%d, %v), expected (%d, %v)", n, err, maxLength, nil)
250 enc.Reset()
251 n, err = WriteData(&enc, bytes.Repeat([]byte{'X'}, maxLength+1))
252 if n != 0 || err != ErrTooLong {
253 t.Fatalf("got (%d, %v), expected (%d, %v)", n, err, 0, ErrTooLong)
256 // Padding gets an extra 3 bytes because the prefix is counted as part
257 // of the length.
258 enc.Reset()
259 n, err = WritePadding(&enc, maxLength+3)
260 if n != maxLength+3 || err != nil {
261 t.Fatalf("got (%d, %v), expected (%d, %v)", n, err, maxLength+3, nil)
263 // Writing a too-long padding is okay because WritePadding will break it
264 // into smaller chunks.
265 enc.Reset()
266 n, err = WritePadding(&enc, maxLength+4)
267 if n != maxLength+4 || err != nil {
268 t.Fatalf("got (%d, %v), expected (%d, %v)", n, err, maxLength+4, nil)
272 // Test that WritePadding panics when given a negative length.
273 func TestNegativeLength(t *testing.T) {
274 for _, n := range []int{-1, ^0} {
275 var enc bytes.Buffer
276 panicked, nn, err := testNegativeLengthSub(t, &enc, n)
277 if !panicked {
278 t.Fatalf("WritePadding(%d) returned (%d, %v) instead of panicking", n, nn, err)
283 // Calls WritePadding(w, n) and augments the return value with a flag indicating
284 // whether the call panicked.
285 func testNegativeLengthSub(t *testing.T, w io.Writer, n int) (panicked bool, nn int, err error) {
286 defer func() {
287 if r := recover(); r != nil {
288 panicked = true
291 t.Helper()
292 nn, err = WritePadding(w, n)
293 return false, n, err
296 // Test that MaxDataForSize panics when given a 0 length.
297 func TestMaxDataForSizeZero(t *testing.T) {
298 defer func() {
299 if r := recover(); r == nil {
300 t.Fatal("didn't panic")
303 MaxDataForSize(0)
306 // Test thresholds of available sizes for MaxDataForSize.
307 func TestMaxDataForSize(t *testing.T) {
308 for _, test := range []struct {
309 size int
310 expected int
312 {0x01, 0x00},
313 {0x02, 0x01},
314 {0x3f, 0x3e},
315 {0x40, 0x3e},
316 {0x41, 0x3f},
317 {0x1fff, 0x1ffd},
318 {0x2000, 0x1ffd},
319 {0x2001, 0x1ffe},
320 {0xfffff, 0xffffc},
321 {0x100000, 0xffffc},
322 {0x100001, 0xffffc},
323 {0x7fffffff, 0xffffc},
325 max := MaxDataForSize(test.size)
326 if max != test.expected {
327 t.Fatalf("size %d, got %d, expected %d", test.size, max, test.expected)