1
2
3
4
5 package flate
6
7 import (
8 "bytes"
9 "crypto/rand"
10 "io"
11 "strconv"
12 "strings"
13 "testing"
14 )
15
16 func TestReset(t *testing.T) {
17 ss := []string{
18 "lorem ipsum izzle fo rizzle",
19 "the quick brown fox jumped over",
20 }
21
22 deflated := make([]bytes.Buffer, 2)
23 for i, s := range ss {
24 w, _ := NewWriter(&deflated[i], 1)
25 w.Write([]byte(s))
26 w.Close()
27 }
28
29 inflated := make([]bytes.Buffer, 2)
30
31 f := NewReader(&deflated[0])
32 io.Copy(&inflated[0], f)
33 f.(Resetter).Reset(&deflated[1], nil)
34 io.Copy(&inflated[1], f)
35 f.Close()
36
37 for i, s := range ss {
38 if s != inflated[i].String() {
39 t.Errorf("inflated[%d]:\ngot %q\nwant %q", i, inflated[i], s)
40 }
41 }
42 }
43
44 func TestReaderTruncated(t *testing.T) {
45 vectors := []struct{ input, output string }{
46 {"\x00", ""},
47 {"\x00\f", ""},
48 {"\x00\f\x00", ""},
49 {"\x00\f\x00\xf3\xff", ""},
50 {"\x00\f\x00\xf3\xffhello", "hello"},
51 {"\x00\f\x00\xf3\xffhello, world", "hello, world"},
52 {"\x02", ""},
53 {"\xf2H\xcd", "He"},
54 {"\xf2H͙0a\u0084\t", "Hel\x90\x90\x90\x90\x90"},
55 {"\xf2H͙0a\u0084\t\x00", "Hel\x90\x90\x90\x90\x90"},
56 }
57
58 for i, v := range vectors {
59 r := strings.NewReader(v.input)
60 zr := NewReader(r)
61 b, err := io.ReadAll(zr)
62 if err != io.ErrUnexpectedEOF {
63 t.Errorf("test %d, error mismatch: got %v, want io.ErrUnexpectedEOF", i, err)
64 }
65 if string(b) != v.output {
66 t.Errorf("test %d, output mismatch: got %q, want %q", i, b, v.output)
67 }
68 }
69 }
70
71 func TestResetDict(t *testing.T) {
72 dict := []byte("the lorem fox")
73 ss := []string{
74 "lorem ipsum izzle fo rizzle",
75 "the quick brown fox jumped over",
76 }
77
78 deflated := make([]bytes.Buffer, len(ss))
79 for i, s := range ss {
80 w, _ := NewWriterDict(&deflated[i], DefaultCompression, dict)
81 w.Write([]byte(s))
82 w.Close()
83 }
84
85 inflated := make([]bytes.Buffer, len(ss))
86
87 f := NewReader(nil)
88 for i := range inflated {
89 f.(Resetter).Reset(&deflated[i], dict)
90 io.Copy(&inflated[i], f)
91 }
92 f.Close()
93
94 for i, s := range ss {
95 if s != inflated[i].String() {
96 t.Errorf("inflated[%d]:\ngot %q\nwant %q", i, inflated[i], s)
97 }
98 }
99 }
100
101
102 type infTest struct {
103 hex string
104 id string
105 n int
106 }
107
108 var infTests = []infTest{
109 {"0 0 0 0 0", "invalid stored block lengths", 1},
110 {"3 0", "fixed", 0},
111 {"6", "invalid block type", 1},
112 {"1 1 0 fe ff 0", "stored", 0},
113 {"fc 0 0", "too many length or distance symbols", 1},
114 {"4 0 fe ff", "invalid code lengths set", 1},
115 {"4 0 24 49 0", "invalid bit length repeat", 1},
116 {"4 0 24 e9 ff ff", "invalid bit length repeat", 1},
117 {"4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1},
118 {"4 80 49 92 24 49 92 24 71 ff ff 93 11 0", "invalid literal/lengths set", 1},
119 {"4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1},
120 {"4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1},
121 {"2 7e ff ff", "invalid distance code", 1},
122 {"c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1},
123
124
125 {"1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1},
126 {"1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1", "incorrect length check", -1},
127 {"5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0},
128 {"5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f", "long code", 0},
129 {"ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0},
130 {"ed cf c1 b1 2c 47 10 c4 30 fa 6f 35 1d 1 82 59 3d fb be 2e 2a fc f c", "long distance and extra", 0},
131 {"ed c0 81 0 0 0 0 80 a0 fd a9 17 a9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0},
132 }
133
134 func TestInflate(t *testing.T) {
135 for _, test := range infTests {
136 hex := strings.Split(test.hex, " ")
137 data := make([]byte, len(hex))
138 for i, h := range hex {
139 b, _ := strconv.ParseInt(h, 16, 32)
140 data[i] = byte(b)
141 }
142 buf := bytes.NewReader(data)
143 r := NewReader(buf)
144
145 _, err := io.Copy(io.Discard, r)
146 if (test.n == 0 && err == nil) || (test.n != 0 && err != nil) {
147 t.Logf("%q: OK:", test.id)
148 t.Logf(" - got %v", err)
149 continue
150 }
151
152 if test.n == 0 && err != nil {
153 t.Errorf("%q: Expected no error, but got %v", test.id, err)
154 continue
155 }
156
157 if test.n != 0 && err == nil {
158 t.Errorf("%q:Expected an error, but got none", test.id)
159 continue
160 }
161 t.Fatal(test.n, err)
162 }
163
164 for _, test := range infOutTests {
165 hex := strings.Split(test.hex, " ")
166 data := make([]byte, len(hex))
167 for i, h := range hex {
168 b, _ := strconv.ParseInt(h, 16, 32)
169 data[i] = byte(b)
170 }
171 buf := bytes.NewReader(data)
172 r := NewReader(buf)
173
174 _, err := io.Copy(io.Discard, r)
175 if test.err == (err != nil) {
176 t.Logf("%q: OK:", test.id)
177 t.Logf(" - got %v", err)
178 continue
179 }
180
181 if test.err == false && err != nil {
182 t.Errorf("%q: Expected no error, but got %v", test.id, err)
183 continue
184 }
185
186 if test.err && err == nil {
187 t.Errorf("%q: Expected an error, but got none", test.id)
188 continue
189 }
190 t.Fatal(test.err, err)
191 }
192
193 }
194
195
196
197
198
199 type infOutTest struct {
200 hex string
201 id string
202 step int
203 win int
204 length int
205 err bool
206 }
207
208 var infOutTests = []infOutTest{
209 {"2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258, false},
210 {"63 18 5 40 c 0", "window wrap", 3, -8, 300, false},
211 {"e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68 ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, true},
212 {"25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258, true},
213 {"3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258, true},
214 {"1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258, true},
215 {"d c7 1 ae eb 38 c 4 41 a0 87 72 de df fb 1f b8 36 b1 38 5d ff ff 0", "fast 2nd level codes and too far back", 0, -8, 258, true},
216 {"63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, false},
217 {"63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0", "contiguous and wrap around window", 6, -8, 259, false},
218 {"63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259, false},
219 {"1f 8b 0 0", "bad gzip method", 0, 31, 0, true},
220 {"1f 8b 8 80", "bad gzip flags", 0, 31, 0, true},
221 {"77 85", "bad zlib method", 0, 15, 0, true},
222 {"78 9c", "bad zlib window size", 0, 8, 0, true},
223 {"1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1, true},
224 {"1f 8b 8 2 0 0 0 0 0 0 1d 26 3 0 0 0 0 0 0 0 0 0", "check gzip length", 0, 47, 0, true},
225 {"78 90", "bad zlib header check", 0, 47, 0, true},
226 {"8 b8 0 0 0 1", "need dictionary", 0, 8, 0, true},
227 {"63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, false},
228 {"3 0", "use fixed blocks", 0, -15, 1, false},
229 {"", "bad window size", 0, 1, 0, true},
230 }
231
232 func TestWriteTo(t *testing.T) {
233 input := make([]byte, 100000)
234 n, err := rand.Read(input)
235 if err != nil {
236 t.Fatal(err)
237 }
238 if n != len(input) {
239 t.Fatal("did not fill buffer")
240 }
241 compressed := &bytes.Buffer{}
242 w, err := NewWriter(compressed, -2)
243 if err != nil {
244 t.Fatal(err)
245 }
246 n, err = w.Write(input)
247 if err != nil {
248 t.Fatal(err)
249 }
250 if n != len(input) {
251 t.Fatal("did not fill buffer")
252 }
253 w.Close()
254 buf := compressed.Bytes()
255
256 dec := NewReader(bytes.NewBuffer(buf))
257
258 readall, err := io.ReadAll(io.NopCloser(dec))
259 if err != nil {
260 t.Fatal(err)
261 }
262 if len(readall) != len(input) {
263 t.Fatal("did not decompress everything")
264 }
265
266 dec = NewReader(bytes.NewBuffer(buf))
267 wtbuf := &bytes.Buffer{}
268 written, err := dec.(io.WriterTo).WriteTo(wtbuf)
269 if err != nil {
270 t.Fatal(err)
271 }
272 if written != int64(len(input)) {
273 t.Error("Returned length did not match, expected", len(input), "got", written)
274 }
275 if wtbuf.Len() != len(input) {
276 t.Error("Actual Length did not match, expected", len(input), "got", wtbuf.Len())
277 }
278 if !bytes.Equal(wtbuf.Bytes(), input) {
279 t.Fatal("output did not match input")
280 }
281 }
282
View as plain text