1
2
3
4
5
6 package flate
7
8 import (
9 "bytes"
10 "fmt"
11 "io"
12 "os"
13 "reflect"
14 "strings"
15 "sync"
16 "testing"
17 )
18
19 type deflateTest struct {
20 in []byte
21 level int
22 out []byte
23 }
24
25 type deflateInflateTest struct {
26 in []byte
27 }
28
29 type reverseBitsTest struct {
30 in uint16
31 bitCount uint8
32 out uint16
33 }
34
35 var deflateTests = []*deflateTest{
36 0: {[]byte{}, 0, []byte{0x3, 0x0}},
37 1: {[]byte{0x11}, BestCompression, []byte{0x12, 0x4, 0xc, 0x0}},
38 2: {[]byte{0x11}, BestCompression, []byte{0x12, 0x4, 0xc, 0x0}},
39 3: {[]byte{0x11}, BestCompression, []byte{0x12, 0x4, 0xc, 0x0}},
40
41 4: {[]byte{0x11}, 0, []byte{0x0, 0x1, 0x0, 0xfe, 0xff, 0x11, 0x3, 0x0}},
42 5: {[]byte{0x11, 0x12}, 0, []byte{0x0, 0x2, 0x0, 0xfd, 0xff, 0x11, 0x12, 0x3, 0x0}},
43 6: {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 0,
44 []byte{0x0, 0x8, 0x0, 0xf7, 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x3, 0x0},
45 },
46 7: {[]byte{}, 1, []byte{0x3, 0x0}},
47 8: {[]byte{0x11}, BestCompression, []byte{0x12, 0x4, 0xc, 0x0}},
48 9: {[]byte{0x11, 0x12}, BestCompression, []byte{0x12, 0x14, 0x2, 0xc, 0x0}},
49 10: {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, BestCompression, []byte{0x12, 0x84, 0x1, 0xc0, 0x0}},
50 11: {[]byte{}, 9, []byte{0x3, 0x0}},
51 12: {[]byte{0x11}, 9, []byte{0x12, 0x4, 0xc, 0x0}},
52 13: {[]byte{0x11, 0x12}, 9, []byte{0x12, 0x14, 0x2, 0xc, 0x0}},
53 14: {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 9, []byte{0x12, 0x84, 0x1, 0xc0, 0x0}},
54 }
55
56 var deflateInflateTests = []*deflateInflateTest{
57 {[]byte{}},
58 {[]byte{0x11}},
59 {[]byte{0x11, 0x12}},
60 {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
61 {[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}},
62 {largeDataChunk()},
63 }
64
65 var reverseBitsTests = []*reverseBitsTest{
66 {1, 1, 1},
67 {1, 2, 2},
68 {1, 3, 4},
69 {1, 4, 8},
70 {1, 5, 16},
71 {17, 5, 17},
72 {257, 9, 257},
73 {29, 5, 23},
74 }
75
76 func largeDataChunk() []byte {
77 result := make([]byte, 100000)
78 for i := range result {
79 result[i] = byte(i * i & 0xFF)
80 }
81 return result
82 }
83
84 func TestBulkHash4(t *testing.T) {
85 for _, x := range deflateTests {
86 y := x.out
87 if len(y) >= minMatchLength {
88 y = append(y, y...)
89 for j := 4; j < len(y); j++ {
90 y := y[:j]
91 dst := make([]uint32, len(y)-minMatchLength+1)
92 for i := range dst {
93 dst[i] = uint32(i + 100)
94 }
95 bulkHash4(y, dst)
96 for i, val := range dst {
97 got := val
98 expect := hash4(y[i:])
99 if got != expect && got == uint32(i)+100 {
100 t.Errorf("Len:%d Index:%d, expected 0x%08x but not modified", len(y), i, expect)
101 } else if got != expect {
102 t.Errorf("Len:%d Index:%d, got 0x%08x expected:0x%08x", len(y), i, got, expect)
103 } else {
104
105 }
106 }
107 }
108 }
109 }
110 }
111
112 func TestDeflate(t *testing.T) {
113 for i, h := range deflateTests {
114 var buf bytes.Buffer
115 w, err := NewWriter(&buf, h.level)
116 if err != nil {
117 t.Errorf("NewWriter: %v", err)
118 continue
119 }
120 w.Write(h.in)
121 w.Close()
122 if !bytes.Equal(buf.Bytes(), h.out) {
123 t.Errorf("%d: Deflate(%d, %x) got \n%#v, want \n%#v", i, h.level, h.in, buf.Bytes(), h.out)
124 }
125 }
126 }
127
128
129
130 type sparseReader struct {
131 l int64
132 cur int64
133 }
134
135 func (r *sparseReader) Read(b []byte) (n int, err error) {
136 if r.cur >= r.l {
137 return 0, io.EOF
138 }
139 n = len(b)
140 cur := r.cur + int64(n)
141 if cur > r.l {
142 n -= int(cur - r.l)
143 cur = r.l
144 }
145 for i := range b[0:n] {
146 if r.cur+int64(i) >= r.l-1<<16 {
147 b[i] = 1
148 } else {
149 b[i] = 0
150 }
151 }
152 r.cur = cur
153 return
154 }
155
156 func TestVeryLongSparseChunk(t *testing.T) {
157 if testing.Short() {
158 t.Skip("skipping sparse chunk during short test")
159 }
160 var buf bytes.Buffer
161 w, err := NewWriter(&buf, 1)
162 if err != nil {
163 t.Errorf("NewWriter: %v", err)
164 return
165 }
166 if _, err = io.Copy(w, &sparseReader{l: 23e8}); err != nil {
167 t.Errorf("Compress failed: %v", err)
168 return
169 }
170 t.Log("Length:", buf.Len())
171 }
172
173 type syncBuffer struct {
174 buf bytes.Buffer
175 mu sync.RWMutex
176 closed bool
177 ready chan bool
178 }
179
180 func newSyncBuffer() *syncBuffer {
181 return &syncBuffer{ready: make(chan bool, 1)}
182 }
183
184 func (b *syncBuffer) Read(p []byte) (n int, err error) {
185 for {
186 b.mu.RLock()
187 n, err = b.buf.Read(p)
188 b.mu.RUnlock()
189 if n > 0 || b.closed {
190 return
191 }
192 <-b.ready
193 }
194 }
195
196 func (b *syncBuffer) signal() {
197 select {
198 case b.ready <- true:
199 default:
200 }
201 }
202
203 func (b *syncBuffer) Write(p []byte) (n int, err error) {
204 n, err = b.buf.Write(p)
205 b.signal()
206 return
207 }
208
209 func (b *syncBuffer) WriteMode() {
210 b.mu.Lock()
211 }
212
213 func (b *syncBuffer) ReadMode() {
214 b.mu.Unlock()
215 b.signal()
216 }
217
218 func (b *syncBuffer) Close() error {
219 b.closed = true
220 b.signal()
221 return nil
222 }
223
224 func testSync(t *testing.T, level int, input []byte, name string) {
225 if len(input) == 0 {
226 return
227 }
228
229 t.Logf("--testSync %d, %d, %s", level, len(input), name)
230 buf := newSyncBuffer()
231 buf1 := new(bytes.Buffer)
232 buf.WriteMode()
233 w, err := NewWriter(io.MultiWriter(buf, buf1), level)
234 if err != nil {
235 t.Errorf("NewWriter: %v", err)
236 return
237 }
238 r := NewReader(buf)
239
240
241 for i := 0; i < 2; i++ {
242 var lo, hi int
243 if i == 0 {
244 lo, hi = 0, (len(input)+1)/2
245 } else {
246 lo, hi = (len(input)+1)/2, len(input)
247 }
248 t.Logf("#%d: write %d-%d", i, lo, hi)
249 if _, err := w.Write(input[lo:hi]); err != nil {
250 t.Errorf("testSync: write: %v", err)
251 return
252 }
253 if i == 0 {
254 if err := w.Flush(); err != nil {
255 t.Errorf("testSync: flush: %v", err)
256 return
257 }
258 } else {
259 if err := w.Close(); err != nil {
260 t.Errorf("testSync: close: %v", err)
261 }
262 }
263 buf.ReadMode()
264 out := make([]byte, hi-lo+1)
265 m, err := io.ReadAtLeast(r, out, hi-lo)
266 t.Logf("#%d: read %d", i, m)
267 if m != hi-lo || err != nil {
268 t.Errorf("testSync/%d (%d, %d, %s): read %d: %d, %v (%d left)", i, level, len(input), name, hi-lo, m, err, buf.buf.Len())
269 return
270 }
271 if !bytes.Equal(input[lo:hi], out[:hi-lo]) {
272 t.Errorf("testSync/%d: read wrong bytes: %x vs %x", i, input[lo:hi], out[:hi-lo])
273 return
274 }
275
276
277
278
279
280
281
282
283
284
285 buf.WriteMode()
286 }
287 buf.ReadMode()
288 out := make([]byte, 10)
289 if n, err := r.Read(out); n > 0 || err != io.EOF {
290 t.Errorf("testSync (%d, %d, %s): final Read: %d, %v (hex: %x)", level, len(input), name, n, err, out[0:n])
291 }
292 if buf.buf.Len() != 0 {
293 t.Errorf("testSync (%d, %d, %s): extra data at end", level, len(input), name)
294 }
295 r.Close()
296
297
298 r = NewReader(buf1)
299 out, err = io.ReadAll(r)
300 if err != nil {
301 t.Errorf("testSync: read: %s", err)
302 return
303 }
304 r.Close()
305 if !bytes.Equal(input, out) {
306 t.Errorf("testSync: decompress(compress(data)) != data: level=%d input=%s", level, name)
307 }
308 }
309
310 func testToFromWithLevelAndLimit(t *testing.T, level int, input []byte, name string, limit int) {
311 var buffer bytes.Buffer
312 w, err := NewWriter(&buffer, level)
313 if err != nil {
314 t.Errorf("NewWriter: %v", err)
315 return
316 }
317 w.Write(input)
318 w.Close()
319 if limit > 0 {
320 t.Logf("level: %d - Size:%.2f%%, %d b\n", level, float64(buffer.Len()*100)/float64(limit), buffer.Len())
321 }
322 if limit > 0 && buffer.Len() > limit {
323 t.Errorf("level: %d, len(compress(data)) = %d > limit = %d", level, buffer.Len(), limit)
324 }
325
326 r := NewReader(&buffer)
327 out, err := io.ReadAll(r)
328 if err != nil {
329 t.Errorf("read: %s", err)
330 return
331 }
332 r.Close()
333 if !bytes.Equal(input, out) {
334 os.WriteFile("testdata/fails/"+t.Name()+".got", out, os.ModePerm)
335 os.WriteFile("testdata/fails/"+t.Name()+".want", input, os.ModePerm)
336 t.Errorf("decompress(compress(data)) != data: level=%d input=%s", level, name)
337 return
338 }
339 testSync(t, level, input, name)
340 }
341
342 func testToFromWithLimit(t *testing.T, input []byte, name string, limit [11]int) {
343 for i := 0; i < 10; i++ {
344 testToFromWithLevelAndLimit(t, i, input, name, limit[i])
345 }
346 testToFromWithLevelAndLimit(t, -2, input, name, limit[10])
347 }
348
349 func TestDeflateInflate(t *testing.T) {
350 for i, h := range deflateInflateTests {
351 testToFromWithLimit(t, h.in, fmt.Sprintf("#%d", i), [11]int{})
352 }
353 }
354
355 func TestReverseBits(t *testing.T) {
356 for _, h := range reverseBitsTests {
357 if v := reverseBits(h.in, h.bitCount); v != h.out {
358 t.Errorf("reverseBits(%v,%v) = %v, want %v",
359 h.in, h.bitCount, v, h.out)
360 }
361 }
362 }
363
364 type deflateInflateStringTest struct {
365 filename string
366 label string
367 limit [11]int
368 }
369
370 var deflateInflateStringTests = []deflateInflateStringTest{
371 {
372 "../testdata/e.txt",
373 "2.718281828...",
374 [...]int{100018, 67900, 50960, 51150, 50930, 50790, 50790, 50790, 50790, 50790, 43683 + 100},
375 },
376 {
377 "../testdata/Mark.Twain-Tom.Sawyer.txt",
378 "Mark.Twain-Tom.Sawyer",
379 [...]int{387999, 185000, 182361, 179974, 174124, 168819, 162936, 160506, 160295, 160295, 233460 + 100},
380 },
381 }
382
383 func TestDeflateInflateString(t *testing.T) {
384 for _, test := range deflateInflateStringTests {
385 gold, err := os.ReadFile(test.filename)
386 if err != nil {
387 t.Error(err)
388 }
389
390 neutral := strings.Map(func(r rune) rune {
391 if r != '\r' {
392 return r
393 }
394 return -1
395 }, string(gold))
396
397 testToFromWithLimit(t, []byte(neutral), test.label, test.limit)
398
399 if testing.Short() {
400 break
401 }
402 }
403 }
404
405 func TestReaderDict(t *testing.T) {
406 const (
407 dict = "hello world"
408 text = "hello again world"
409 )
410 var b bytes.Buffer
411 w, err := NewWriter(&b, 5)
412 if err != nil {
413 t.Fatalf("NewWriter: %v", err)
414 }
415 w.Write([]byte(dict))
416 w.Flush()
417 b.Reset()
418 w.Write([]byte(text))
419 w.Close()
420
421 r := NewReaderDict(&b, []byte(dict))
422 data, err := io.ReadAll(r)
423 if err != nil {
424 t.Fatal(err)
425 }
426 if string(data) != "hello again world" {
427 t.Fatalf("read returned %q want %q", string(data), text)
428 }
429 }
430
431 func TestWriterDict(t *testing.T) {
432 const (
433 dict = "hello world Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
434 text = "hello world Lorem ipsum dolor sit amet"
435 )
436
437
438
439 for l := 4; l < 9; l++ {
440 var b bytes.Buffer
441 w, err := NewWriter(&b, l)
442 if err != nil {
443 t.Fatalf("level %d, NewWriter: %v", l, err)
444 }
445 w.Write([]byte(dict))
446 w.Flush()
447 b.Reset()
448 w.Write([]byte(text))
449 w.Close()
450
451 var b1 bytes.Buffer
452 w, _ = NewWriterDict(&b1, l, []byte(dict))
453 w.Write([]byte(text))
454 w.Close()
455
456 if !bytes.Equal(b1.Bytes(), b.Bytes()) {
457 t.Errorf("level %d, writer wrote\n%v\n want\n%v", l, b1.Bytes(), b.Bytes())
458 }
459 }
460 }
461
462
463 func TestRegression2508(t *testing.T) {
464 if testing.Short() {
465 t.Logf("test disabled with -short")
466 return
467 }
468 w, err := NewWriter(io.Discard, 1)
469 if err != nil {
470 t.Fatalf("NewWriter: %v", err)
471 }
472 buf := make([]byte, 1024)
473 for i := 0; i < 131072; i++ {
474 if _, err := w.Write(buf); err != nil {
475 t.Fatalf("writer failed: %v", err)
476 }
477 }
478 w.Close()
479 }
480
481 func TestWriterReset(t *testing.T) {
482 for level := -2; level <= 9; level++ {
483 if level == -1 {
484 level++
485 }
486 if testing.Short() && level > 1 {
487 break
488 }
489 w, err := NewWriter(io.Discard, level)
490 if err != nil {
491 t.Fatalf("NewWriter: %v", err)
492 }
493 buf := []byte("hello world")
494 for i := 0; i < 1024; i++ {
495 w.Write(buf)
496 }
497 w.Reset(io.Discard)
498
499 wref, err := NewWriter(io.Discard, level)
500 if err != nil {
501 t.Fatalf("NewWriter: %v", err)
502 }
503
504
505 w.d.fill, wref.d.fill = nil, nil
506 w.d.step, wref.d.step = nil, nil
507 w.d.state, wref.d.state = nil, nil
508 w.d.fast, wref.d.fast = nil, nil
509
510
511 if w.d.tokens.n != 0 {
512 t.Errorf("level %d Writer not reset after Reset. %d tokens were present", level, w.d.tokens.n)
513 }
514
515 w.d.tokens = wref.d.tokens
516
517
518 w.d.window = wref.d.window
519 if !reflect.DeepEqual(w, wref) {
520 t.Errorf("level %d Writer not reset after Reset", level)
521 }
522 }
523
524 for i := HuffmanOnly; i <= BestCompression; i++ {
525 testResetOutput(t, fmt.Sprint("level-", i), func(w io.Writer) (*Writer, error) { return NewWriter(w, i) })
526 }
527 dict := []byte(strings.Repeat("we are the world - how are you?", 3))
528 for i := HuffmanOnly; i <= BestCompression; i++ {
529 testResetOutput(t, fmt.Sprint("dict-level-", i), func(w io.Writer) (*Writer, error) { return NewWriterDict(w, i, dict) })
530 }
531 for i := HuffmanOnly; i <= BestCompression; i++ {
532 testResetOutput(t, fmt.Sprint("dict-reset-level-", i), func(w io.Writer) (*Writer, error) {
533 w2, err := NewWriter(nil, i)
534 if err != nil {
535 return w2, err
536 }
537 w2.ResetDict(w, dict)
538 return w2, nil
539 })
540 }
541 testResetOutput(t, fmt.Sprint("dict-reset-window"), func(w io.Writer) (*Writer, error) {
542 w2, err := NewWriterWindow(nil, 1024)
543 if err != nil {
544 return w2, err
545 }
546 w2.ResetDict(w, dict)
547 return w2, nil
548 })
549 }
550
551 func testResetOutput(t *testing.T, name string, newWriter func(w io.Writer) (*Writer, error)) {
552 t.Run(name, func(t *testing.T) {
553 buf := new(bytes.Buffer)
554 w, err := newWriter(buf)
555 if err != nil {
556 t.Fatalf("NewWriter: %v", err)
557 }
558 b := []byte("hello world - how are you doing?")
559 for i := 0; i < 1024; i++ {
560 w.Write(b)
561 }
562 w.Close()
563 out1 := buf.Bytes()
564
565 buf2 := new(bytes.Buffer)
566 w.Reset(buf2)
567 for i := 0; i < 1024; i++ {
568 w.Write(b)
569 }
570 w.Close()
571 out2 := buf2.Bytes()
572
573 if len(out1) != len(out2) {
574 t.Errorf("got %d, expected %d bytes", len(out2), len(out1))
575 }
576 if !bytes.Equal(out1, out2) {
577 mm := 0
578 for i, b := range out1[:len(out2)] {
579 if b != out2[i] {
580 t.Errorf("mismatch index %d: %02x, expected %02x", i, out2[i], b)
581 }
582 mm++
583 if mm == 10 {
584 t.Fatal("Stopping")
585 }
586 }
587 }
588 t.Logf("got %d bytes", len(out1))
589 })
590 }
591
592
593
594
595
596 func TestBestSpeed(t *testing.T) {
597 abc := make([]byte, 128)
598 for i := range abc {
599 abc[i] = byte(i)
600 }
601 abcabc := bytes.Repeat(abc, 131072/len(abc))
602 var want []byte
603
604 testCases := [][]int{
605 {65536, 0},
606 {65536, 1},
607 {65536, 1, 256},
608 {65536, 1, 65536},
609 {65536, 14},
610 {65536, 15},
611 {65536, 16},
612 {65536, 16, 256},
613 {65536, 16, 65536},
614 {65536, 127},
615 {65536, 128},
616 {65536, 128, 256},
617 {65536, 128, 65536},
618 {65536, 129},
619 {65536, 65536, 256},
620 {65536, 65536, 65536},
621 }
622
623 for i, tc := range testCases {
624 if testing.Short() && i > 5 {
625 t.Skip()
626 }
627 for _, firstN := range []int{1, 65534, 65535, 65536, 65537, 131072} {
628 tc[0] = firstN
629 outer:
630 for _, flush := range []bool{false, true} {
631 buf := new(bytes.Buffer)
632 want = want[:0]
633
634 w, err := NewWriter(buf, BestSpeed)
635 if err != nil {
636 t.Errorf("i=%d, firstN=%d, flush=%t: NewWriter: %v", i, firstN, flush, err)
637 continue
638 }
639 for _, n := range tc {
640 want = append(want, abcabc[:n]...)
641 if _, err := w.Write(abcabc[:n]); err != nil {
642 t.Errorf("i=%d, firstN=%d, flush=%t: Write: %v", i, firstN, flush, err)
643 continue outer
644 }
645 if !flush {
646 continue
647 }
648 if err := w.Flush(); err != nil {
649 t.Errorf("i=%d, firstN=%d, flush=%t: Flush: %v", i, firstN, flush, err)
650 continue outer
651 }
652 }
653 if err := w.Close(); err != nil {
654 t.Errorf("i=%d, firstN=%d, flush=%t: Close: %v", i, firstN, flush, err)
655 continue
656 }
657
658 r := NewReader(buf)
659 got, err := io.ReadAll(r)
660 if err != nil {
661 t.Errorf("i=%d, firstN=%d, flush=%t: ReadAll: %v", i, firstN, flush, err)
662 continue
663 }
664 r.Close()
665
666 if !bytes.Equal(got, want) {
667 t.Errorf("i=%d, firstN=%d, flush=%t: corruption during deflate-then-inflate", i, firstN, flush)
668 continue
669 }
670 }
671 }
672 }
673 }
674
View as plain text