1
2
3
4
5 package flate
6
7 import (
8 "bytes"
9 "errors"
10 "fmt"
11 "internal/testenv"
12 "io"
13 "math/rand"
14 "os"
15 "reflect"
16 "runtime/debug"
17 "sync"
18 "testing"
19 )
20
21 type deflateTest struct {
22 in []byte
23 level int
24 out []byte
25 }
26
27 type deflateInflateTest struct {
28 in []byte
29 }
30
31 type reverseBitsTest struct {
32 in uint16
33 bitCount uint8
34 out uint16
35 }
36
37 var deflateTests = []*deflateTest{
38 {[]byte{}, 0, []byte{1, 0, 0, 255, 255}},
39 {[]byte{0x11}, -1, []byte{18, 4, 4, 0, 0, 255, 255}},
40 {[]byte{0x11}, DefaultCompression, []byte{18, 4, 4, 0, 0, 255, 255}},
41 {[]byte{0x11}, 4, []byte{18, 4, 4, 0, 0, 255, 255}},
42
43 {[]byte{0x11}, 0, []byte{0, 1, 0, 254, 255, 17, 1, 0, 0, 255, 255}},
44 {[]byte{0x11, 0x12}, 0, []byte{0, 2, 0, 253, 255, 17, 18, 1, 0, 0, 255, 255}},
45 {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 0,
46 []byte{0, 8, 0, 247, 255, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0, 0, 255, 255},
47 },
48 {[]byte{}, 2, []byte{1, 0, 0, 255, 255}},
49 {[]byte{0x11}, 2, []byte{18, 4, 4, 0, 0, 255, 255}},
50 {[]byte{0x11, 0x12}, 2, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
51 {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 2, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
52 {[]byte{}, 9, []byte{1, 0, 0, 255, 255}},
53 {[]byte{0x11}, 9, []byte{18, 4, 4, 0, 0, 255, 255}},
54 {[]byte{0x11, 0x12}, 9, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
55 {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 9, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
56 }
57
58 var deflateInflateTests = []*deflateInflateTest{
59 {[]byte{}},
60 {[]byte{0x11}},
61 {[]byte{0x11, 0x12}},
62 {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
63 {[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}},
64 {largeDataChunk()},
65 }
66
67 var reverseBitsTests = []*reverseBitsTest{
68 {1, 1, 1},
69 {1, 2, 2},
70 {1, 3, 4},
71 {1, 4, 8},
72 {1, 5, 16},
73 {17, 5, 17},
74 {257, 9, 257},
75 {29, 5, 23},
76 }
77
78 func largeDataChunk() []byte {
79 result := make([]byte, 100000)
80 for i := range result {
81 result[i] = byte(i * i & 0xFF)
82 }
83 return result
84 }
85
86 func TestBulkHash4(t *testing.T) {
87 for _, x := range deflateTests {
88 y := x.out
89 if len(y) < minMatchLength {
90 continue
91 }
92 y = append(y, y...)
93 for j := 4; j < len(y); j++ {
94 y := y[:j]
95 dst := make([]uint32, len(y)-minMatchLength+1)
96 for i := range dst {
97 dst[i] = uint32(i + 100)
98 }
99 bulkHash4(y, dst)
100 for i, got := range dst {
101 want := hash4(y[i:])
102 if got != want && got == uint32(i)+100 {
103 t.Errorf("Len:%d Index:%d, want 0x%08x but not modified", len(y), i, want)
104 } else if got != want {
105 t.Errorf("Len:%d Index:%d, got 0x%08x want:0x%08x", len(y), i, got, want)
106 }
107 }
108 }
109 }
110 }
111
112 func TestDeflate(t *testing.T) {
113 for _, 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("Deflate(%d, %x) = \n%#v, want \n%#v", h.level, h.in, buf.Bytes(), h.out)
124 }
125 }
126 }
127
128 func TestWriterClose(t *testing.T) {
129 b := new(bytes.Buffer)
130 zw, err := NewWriter(b, 6)
131 if err != nil {
132 t.Fatalf("NewWriter: %v", err)
133 }
134
135 if c, err := zw.Write([]byte("Test")); err != nil || c != 4 {
136 t.Fatalf("Write to not closed writer: %s, %d", err, c)
137 }
138
139 if err := zw.Close(); err != nil {
140 t.Fatalf("Close: %v", err)
141 }
142
143 afterClose := b.Len()
144
145 if c, err := zw.Write([]byte("Test")); err == nil || c != 0 {
146 t.Fatalf("Write to closed writer: %v, %d", err, c)
147 }
148
149 if err := zw.Flush(); err == nil {
150 t.Fatalf("Flush to closed writer: %s", err)
151 }
152
153 if err := zw.Close(); err != nil {
154 t.Fatalf("Close: %v", err)
155 }
156
157 if afterClose != b.Len() {
158 t.Fatalf("Writer wrote data after close. After close: %d. After writes on closed stream: %d", afterClose, b.Len())
159 }
160 }
161
162
163
164 type sparseReader struct {
165 l int64
166 cur int64
167 }
168
169 func (r *sparseReader) Read(b []byte) (n int, err error) {
170 if r.cur >= r.l {
171 return 0, io.EOF
172 }
173 n = len(b)
174 cur := r.cur + int64(n)
175 if cur > r.l {
176 n -= int(cur - r.l)
177 cur = r.l
178 }
179 for i := range b[0:n] {
180 if r.cur+int64(i) >= r.l-1<<16 {
181 b[i] = 1
182 } else {
183 b[i] = 0
184 }
185 }
186 r.cur = cur
187 return
188 }
189
190 func TestVeryLongSparseChunk(t *testing.T) {
191 if testing.Short() {
192 t.Skip("skipping sparse chunk during short test")
193 }
194 w, err := NewWriter(io.Discard, 1)
195 if err != nil {
196 t.Errorf("NewWriter: %v", err)
197 return
198 }
199 if _, err = io.Copy(w, &sparseReader{l: 23e8}); err != nil {
200 t.Errorf("Compress failed: %v", err)
201 return
202 }
203 }
204
205 type syncBuffer struct {
206 buf bytes.Buffer
207 mu sync.RWMutex
208 closed bool
209 ready chan bool
210 }
211
212 func newSyncBuffer() *syncBuffer {
213 return &syncBuffer{ready: make(chan bool, 1)}
214 }
215
216 func (b *syncBuffer) Read(p []byte) (n int, err error) {
217 for {
218 b.mu.RLock()
219 n, err = b.buf.Read(p)
220 b.mu.RUnlock()
221 if n > 0 || b.closed {
222 return
223 }
224 <-b.ready
225 }
226 }
227
228 func (b *syncBuffer) signal() {
229 select {
230 case b.ready <- true:
231 default:
232 }
233 }
234
235 func (b *syncBuffer) Write(p []byte) (n int, err error) {
236 n, err = b.buf.Write(p)
237 b.signal()
238 return
239 }
240
241 func (b *syncBuffer) WriteMode() {
242 b.mu.Lock()
243 }
244
245 func (b *syncBuffer) ReadMode() {
246 b.mu.Unlock()
247 b.signal()
248 }
249
250 func (b *syncBuffer) Close() error {
251 b.closed = true
252 b.signal()
253 return nil
254 }
255
256 func testSync(t *testing.T, level int, input []byte, name string) {
257 if len(input) == 0 {
258 return
259 }
260
261 t.Logf("--testSync %d, %d, %s", level, len(input), name)
262 buf := newSyncBuffer()
263 buf1 := new(bytes.Buffer)
264 buf.WriteMode()
265 w, err := NewWriter(io.MultiWriter(buf, buf1), level)
266 if err != nil {
267 t.Errorf("NewWriter: %v", err)
268 return
269 }
270 r := NewReader(buf)
271
272
273 for i := 0; i < 2; i++ {
274 var lo, hi int
275 if i == 0 {
276 lo, hi = 0, (len(input)+1)/2
277 } else {
278 lo, hi = (len(input)+1)/2, len(input)
279 }
280 t.Logf("#%d: write %d-%d", i, lo, hi)
281 if _, err := w.Write(input[lo:hi]); err != nil {
282 t.Errorf("testSync: write: %v", err)
283 return
284 }
285 if i == 0 {
286 if err := w.Flush(); err != nil {
287 t.Errorf("testSync: flush: %v", err)
288 return
289 }
290 } else {
291 if err := w.Close(); err != nil {
292 t.Errorf("testSync: close: %v", err)
293 }
294 }
295 buf.ReadMode()
296 out := make([]byte, hi-lo+1)
297 m, err := io.ReadAtLeast(r, out, hi-lo)
298 t.Logf("#%d: read %d", i, m)
299 if m != hi-lo || err != nil {
300 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())
301 return
302 }
303 if !bytes.Equal(input[lo:hi], out[:hi-lo]) {
304 t.Errorf("testSync/%d: read wrong bytes: %x vs %x", i, input[lo:hi], out[:hi-lo])
305 return
306 }
307
308
309
310
311
312
313
314
315
316
317 buf.WriteMode()
318 }
319 buf.ReadMode()
320 out := make([]byte, 10)
321 if n, err := r.Read(out); n > 0 || err != io.EOF {
322 t.Errorf("testSync (%d, %d, %s): final Read: %d, %v (hex: %x)", level, len(input), name, n, err, out[0:n])
323 }
324 if buf.buf.Len() != 0 {
325 t.Errorf("testSync (%d, %d, %s): extra data at end", level, len(input), name)
326 }
327 r.Close()
328
329
330 r = NewReader(buf1)
331 out, err = io.ReadAll(r)
332 if err != nil {
333 t.Errorf("testSync: read: %s", err)
334 return
335 }
336 r.Close()
337 if !bytes.Equal(input, out) {
338 t.Errorf("testSync: decompress(compress(data)) != data: level=%d input=%s", level, name)
339 }
340 }
341
342 func testToFromWithLevelAndLimit(t *testing.T, level int, input []byte, name string, limit int) {
343 var buffer bytes.Buffer
344 w, err := NewWriter(&buffer, level)
345 if err != nil {
346 t.Errorf("NewWriter: %v", err)
347 return
348 }
349 w.Write(input)
350 w.Close()
351 if limit > 0 && buffer.Len() > limit {
352 t.Errorf("level: %d, len(compress(data)) = %d > limit = %d", level, buffer.Len(), limit)
353 return
354 }
355 if limit > 0 {
356 t.Logf("level: %d, size:%.2f%%, %d b\n", level, float64(buffer.Len()*100)/float64(limit), buffer.Len())
357 }
358 r := NewReader(&buffer)
359 out, err := io.ReadAll(r)
360 if err != nil {
361 t.Errorf("read: %s", err)
362 return
363 }
364 r.Close()
365 if !bytes.Equal(input, out) {
366 t.Errorf("decompress(compress(data)) != data: level=%d input=%s", level, name)
367 return
368 }
369 testSync(t, level, input, name)
370 }
371
372 func testToFromWithLimit(t *testing.T, input []byte, name string, limit [11]int) {
373 for i := 0; i < 10; i++ {
374 testToFromWithLevelAndLimit(t, i, input, name, limit[i])
375 }
376
377 testToFromWithLevelAndLimit(t, -2, input, name, limit[10])
378 }
379
380 func TestDeflateInflate(t *testing.T) {
381 t.Parallel()
382 for i, h := range deflateInflateTests {
383 if testing.Short() && len(h.in) > 10000 {
384 continue
385 }
386 testToFromWithLimit(t, h.in, fmt.Sprintf("#%d", i), [11]int{})
387 }
388 }
389
390 func TestReverseBits(t *testing.T) {
391 for _, h := range reverseBitsTests {
392 if v := reverseBits(h.in, h.bitCount); v != h.out {
393 t.Errorf("reverseBits(%v,%v) = %v, want %v",
394 h.in, h.bitCount, v, h.out)
395 }
396 }
397 }
398
399 type deflateInflateStringTest struct {
400 filename string
401 label string
402 limit [11]int
403 }
404
405 var deflateInflateStringTests = []deflateInflateStringTest{
406 {
407 "../testdata/e.txt",
408 "2.718281828...",
409 [...]int{100018, 50650, 50960, 51150, 50930, 50790, 50790, 50790, 50790, 50790, 43683},
410 },
411 {
412 "../../testdata/Isaac.Newton-Opticks.txt",
413 "Isaac.Newton-Opticks",
414 [...]int{567248, 218338, 198211, 193152, 181100, 175427, 175427, 173597, 173422, 173422, 325240},
415 },
416 }
417
418 func TestDeflateInflateString(t *testing.T) {
419 t.Parallel()
420 if testing.Short() && testenv.Builder() == "" {
421 t.Skip("skipping in short mode")
422 }
423 for _, test := range deflateInflateStringTests {
424 gold, err := os.ReadFile(test.filename)
425 if err != nil {
426 t.Error(err)
427 }
428 testToFromWithLimit(t, gold, test.label, test.limit)
429 if testing.Short() {
430 break
431 }
432 }
433 }
434
435 func TestReaderDict(t *testing.T) {
436 const (
437 dict = "hello world"
438 text = "hello again world"
439 )
440 var b bytes.Buffer
441 w, err := NewWriter(&b, 5)
442 if err != nil {
443 t.Fatalf("NewWriter: %v", err)
444 }
445 w.Write([]byte(dict))
446 w.Flush()
447 b.Reset()
448 w.Write([]byte(text))
449 w.Close()
450
451 r := NewReaderDict(&b, []byte(dict))
452 data, err := io.ReadAll(r)
453 if err != nil {
454 t.Fatal(err)
455 }
456 if string(data) != "hello again world" {
457 t.Fatalf("read returned %q want %q", string(data), text)
458 }
459 }
460
461 func TestWriterDict(t *testing.T) {
462 const (
463 dict = "hello world"
464 text = "hello again world"
465 )
466 var b bytes.Buffer
467 w, err := NewWriter(&b, 5)
468 if err != nil {
469 t.Fatalf("NewWriter: %v", err)
470 }
471 w.Write([]byte(dict))
472 w.Flush()
473 b.Reset()
474 w.Write([]byte(text))
475 w.Close()
476
477 var b1 bytes.Buffer
478 w, _ = NewWriterDict(&b1, 5, []byte(dict))
479 w.Write([]byte(text))
480 w.Close()
481
482 if !bytes.Equal(b1.Bytes(), b.Bytes()) {
483 t.Fatalf("writer wrote %q want %q", b1.Bytes(), b.Bytes())
484 }
485 }
486
487
488 func TestRegression2508(t *testing.T) {
489 if testing.Short() {
490 t.Logf("test disabled with -short")
491 return
492 }
493 w, err := NewWriter(io.Discard, 1)
494 if err != nil {
495 t.Fatalf("NewWriter: %v", err)
496 }
497 buf := make([]byte, 1024)
498 for i := 0; i < 131072; i++ {
499 if _, err := w.Write(buf); err != nil {
500 t.Fatalf("writer failed: %v", err)
501 }
502 }
503 w.Close()
504 }
505
506 func TestWriterReset(t *testing.T) {
507 t.Parallel()
508 for level := 0; level <= 9; level++ {
509 if testing.Short() && level > 1 {
510 break
511 }
512 w, err := NewWriter(io.Discard, level)
513 if err != nil {
514 t.Fatalf("NewWriter: %v", err)
515 }
516 buf := []byte("hello world")
517 n := 1024
518 if testing.Short() {
519 n = 10
520 }
521 for i := 0; i < n; i++ {
522 w.Write(buf)
523 }
524 w.Reset(io.Discard)
525
526 wref, err := NewWriter(io.Discard, level)
527 if err != nil {
528 t.Fatalf("NewWriter: %v", err)
529 }
530
531
532 w.d.fill, wref.d.fill = nil, nil
533 w.d.step, wref.d.step = nil, nil
534 w.d.bulkHasher, wref.d.bulkHasher = nil, nil
535 w.d.bestSpeed, wref.d.bestSpeed = nil, nil
536
537 copy(w.d.hashMatch[:], wref.d.hashMatch[:])
538 if len(w.d.tokens) != 0 {
539 t.Errorf("level %d Writer not reset after Reset. %d tokens were present", level, len(w.d.tokens))
540 }
541
542 w.d.tokens = wref.d.tokens
543
544
545 w.d.window = wref.d.window
546 if !reflect.DeepEqual(w, wref) {
547 t.Errorf("level %d Writer not reset after Reset", level)
548 }
549 }
550
551 levels := []int{0, 1, 2, 5, 9}
552 for _, level := range levels {
553 t.Run(fmt.Sprint(level), func(t *testing.T) {
554 testResetOutput(t, level, nil)
555 })
556 }
557
558 t.Run("dict", func(t *testing.T) {
559 for _, level := range levels {
560 t.Run(fmt.Sprint(level), func(t *testing.T) {
561 testResetOutput(t, level, nil)
562 })
563 }
564 })
565 }
566
567 func testResetOutput(t *testing.T, level int, dict []byte) {
568 writeData := func(w *Writer) {
569 msg := []byte("now is the time for all good gophers")
570 w.Write(msg)
571 w.Flush()
572
573 hello := []byte("hello world")
574 for i := 0; i < 1024; i++ {
575 w.Write(hello)
576 }
577
578 fill := bytes.Repeat([]byte("x"), 65000)
579 w.Write(fill)
580 }
581
582 buf := new(bytes.Buffer)
583 var w *Writer
584 var err error
585 if dict == nil {
586 w, err = NewWriter(buf, level)
587 } else {
588 w, err = NewWriterDict(buf, level, dict)
589 }
590 if err != nil {
591 t.Fatalf("NewWriter: %v", err)
592 }
593
594 writeData(w)
595 w.Close()
596 out1 := buf.Bytes()
597
598 buf2 := new(bytes.Buffer)
599 w.Reset(buf2)
600 writeData(w)
601 w.Close()
602 out2 := buf2.Bytes()
603
604 if len(out1) != len(out2) {
605 t.Errorf("got %d, expected %d bytes", len(out2), len(out1))
606 return
607 }
608 if !bytes.Equal(out1, out2) {
609 mm := 0
610 for i, b := range out1[:len(out2)] {
611 if b != out2[i] {
612 t.Errorf("mismatch index %d: %#02x, expected %#02x", i, out2[i], b)
613 }
614 mm++
615 if mm == 10 {
616 t.Fatal("Stopping")
617 }
618 }
619 }
620 t.Logf("got %d bytes", len(out1))
621 }
622
623
624
625
626
627 func TestBestSpeed(t *testing.T) {
628 t.Parallel()
629 abc := make([]byte, 128)
630 for i := range abc {
631 abc[i] = byte(i)
632 }
633 abcabc := bytes.Repeat(abc, 131072/len(abc))
634 var want []byte
635
636 testCases := [][]int{
637 {65536, 0},
638 {65536, 1},
639 {65536, 1, 256},
640 {65536, 1, 65536},
641 {65536, 14},
642 {65536, 15},
643 {65536, 16},
644 {65536, 16, 256},
645 {65536, 16, 65536},
646 {65536, 127},
647 {65536, 128},
648 {65536, 128, 256},
649 {65536, 128, 65536},
650 {65536, 129},
651 {65536, 65536, 256},
652 {65536, 65536, 65536},
653 }
654
655 for i, tc := range testCases {
656 if i >= 3 && testing.Short() {
657 break
658 }
659 for _, firstN := range []int{1, 65534, 65535, 65536, 65537, 131072} {
660 tc[0] = firstN
661 outer:
662 for _, flush := range []bool{false, true} {
663 buf := new(bytes.Buffer)
664 want = want[:0]
665
666 w, err := NewWriter(buf, BestSpeed)
667 if err != nil {
668 t.Errorf("i=%d, firstN=%d, flush=%t: NewWriter: %v", i, firstN, flush, err)
669 continue
670 }
671 for _, n := range tc {
672 want = append(want, abcabc[:n]...)
673 if _, err := w.Write(abcabc[:n]); err != nil {
674 t.Errorf("i=%d, firstN=%d, flush=%t: Write: %v", i, firstN, flush, err)
675 continue outer
676 }
677 if !flush {
678 continue
679 }
680 if err := w.Flush(); err != nil {
681 t.Errorf("i=%d, firstN=%d, flush=%t: Flush: %v", i, firstN, flush, err)
682 continue outer
683 }
684 }
685 if err := w.Close(); err != nil {
686 t.Errorf("i=%d, firstN=%d, flush=%t: Close: %v", i, firstN, flush, err)
687 continue
688 }
689
690 r := NewReader(buf)
691 got, err := io.ReadAll(r)
692 if err != nil {
693 t.Errorf("i=%d, firstN=%d, flush=%t: ReadAll: %v", i, firstN, flush, err)
694 continue
695 }
696 r.Close()
697
698 if !bytes.Equal(got, want) {
699 t.Errorf("i=%d, firstN=%d, flush=%t: corruption during deflate-then-inflate", i, firstN, flush)
700 continue
701 }
702 }
703 }
704 }
705 }
706
707 var errIO = errors.New("IO error")
708
709
710 type failWriter struct{ n int }
711
712 func (w *failWriter) Write(b []byte) (int, error) {
713 w.n--
714 if w.n == -1 {
715 return 0, errIO
716 }
717 return len(b), nil
718 }
719
720 func TestWriterPersistentWriteError(t *testing.T) {
721 t.Parallel()
722 d, err := os.ReadFile("../../testdata/Isaac.Newton-Opticks.txt")
723 if err != nil {
724 t.Fatalf("ReadFile: %v", err)
725 }
726 d = d[:10000]
727
728 zw, err := NewWriter(nil, DefaultCompression)
729 if err != nil {
730 t.Fatalf("NewWriter: %v", err)
731 }
732
733
734
735
736
737 for i := 0; i < 1000; i++ {
738 fw := &failWriter{i}
739 zw.Reset(fw)
740
741 _, werr := zw.Write(d)
742 cerr := zw.Close()
743 ferr := zw.Flush()
744 if werr != errIO && werr != nil {
745 t.Errorf("test %d, mismatching Write error: got %v, want %v", i, werr, errIO)
746 }
747 if cerr != errIO && fw.n < 0 {
748 t.Errorf("test %d, mismatching Close error: got %v, want %v", i, cerr, errIO)
749 }
750 if ferr != errIO && fw.n < 0 {
751 t.Errorf("test %d, mismatching Flush error: got %v, want %v", i, ferr, errIO)
752 }
753 if fw.n >= 0 {
754
755
756 return
757 }
758 }
759 }
760 func TestWriterPersistentFlushError(t *testing.T) {
761 zw, err := NewWriter(&failWriter{0}, DefaultCompression)
762 if err != nil {
763 t.Fatalf("NewWriter: %v", err)
764 }
765 flushErr := zw.Flush()
766 closeErr := zw.Close()
767 _, writeErr := zw.Write([]byte("Test"))
768 checkErrors([]error{closeErr, flushErr, writeErr}, errIO, t)
769 }
770
771 func TestWriterPersistentCloseError(t *testing.T) {
772
773 zw, err := NewWriter(&failWriter{0}, DefaultCompression)
774 if err != nil {
775 t.Fatalf("NewWriter: %v", err)
776 }
777 closeErr := zw.Close()
778 flushErr := zw.Flush()
779 _, writeErr := zw.Write([]byte("Test"))
780 checkErrors([]error{closeErr, flushErr, writeErr}, errIO, t)
781
782
783
784 var b bytes.Buffer
785 zw.Reset(&b)
786 err = zw.Close()
787 if err != nil {
788 t.Fatalf("First call to close returned error: %s", err)
789 }
790 err = zw.Close()
791 if err != nil {
792 t.Fatalf("Second call to close returned error: %s", err)
793 }
794
795 flushErr = zw.Flush()
796 _, writeErr = zw.Write([]byte("Test"))
797 checkErrors([]error{flushErr, writeErr}, errWriterClosed, t)
798 }
799
800 func checkErrors(got []error, want error, t *testing.T) {
801 t.Helper()
802 for _, err := range got {
803 if err != want {
804 t.Errorf("Error doesn't match\nWant: %s\nGot: %s", want, got)
805 }
806 }
807 }
808
809 func TestBestSpeedMatch(t *testing.T) {
810 t.Parallel()
811 cases := []struct {
812 previous, current []byte
813 t, s, want int32
814 }{{
815 previous: []byte{0, 0, 0, 1, 2},
816 current: []byte{3, 4, 5, 0, 1, 2, 3, 4, 5},
817 t: -3,
818 s: 3,
819 want: 6,
820 }, {
821 previous: []byte{0, 0, 0, 1, 2},
822 current: []byte{2, 4, 5, 0, 1, 2, 3, 4, 5},
823 t: -3,
824 s: 3,
825 want: 3,
826 }, {
827 previous: []byte{0, 0, 0, 1, 1},
828 current: []byte{3, 4, 5, 0, 1, 2, 3, 4, 5},
829 t: -3,
830 s: 3,
831 want: 2,
832 }, {
833 previous: []byte{0, 0, 0, 1, 2},
834 current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5},
835 t: -1,
836 s: 0,
837 want: 4,
838 }, {
839 previous: []byte{0, 0, 0, 1, 2, 3, 4, 5, 2, 2},
840 current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5},
841 t: -7,
842 s: 4,
843 want: 5,
844 }, {
845 previous: []byte{9, 9, 9, 9, 9},
846 current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5},
847 t: -1,
848 s: 0,
849 want: 0,
850 }, {
851 previous: []byte{9, 9, 9, 9, 9},
852 current: []byte{9, 2, 2, 2, 1, 2, 3, 4, 5},
853 t: 0,
854 s: 1,
855 want: 0,
856 }, {
857 previous: []byte{},
858 current: []byte{9, 2, 2, 2, 1, 2, 3, 4, 5},
859 t: -5,
860 s: 1,
861 want: 0,
862 }, {
863 previous: []byte{},
864 current: []byte{9, 2, 2, 2, 1, 2, 3, 4, 5},
865 t: -1,
866 s: 1,
867 want: 0,
868 }, {
869 previous: []byte{},
870 current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5},
871 t: 0,
872 s: 1,
873 want: 3,
874 }, {
875 previous: []byte{3, 4, 5},
876 current: []byte{3, 4, 5},
877 t: -3,
878 s: 0,
879 want: 3,
880 }, {
881 previous: make([]byte, 1000),
882 current: make([]byte, 1000),
883 t: -1000,
884 s: 0,
885 want: maxMatchLength - 4,
886 }, {
887 previous: make([]byte, 200),
888 current: make([]byte, 500),
889 t: -200,
890 s: 0,
891 want: maxMatchLength - 4,
892 }, {
893 previous: make([]byte, 200),
894 current: make([]byte, 500),
895 t: 0,
896 s: 1,
897 want: maxMatchLength - 4,
898 }, {
899 previous: make([]byte, maxMatchLength-4),
900 current: make([]byte, 500),
901 t: -(maxMatchLength - 4),
902 s: 0,
903 want: maxMatchLength - 4,
904 }, {
905 previous: make([]byte, 200),
906 current: make([]byte, 500),
907 t: -200,
908 s: 400,
909 want: 100,
910 }, {
911 previous: make([]byte, 10),
912 current: make([]byte, 500),
913 t: 200,
914 s: 400,
915 want: 100,
916 }}
917 for i, c := range cases {
918 e := deflateFast{prev: c.previous}
919 got := e.matchLen(c.s, c.t, c.current)
920 if got != c.want {
921 t.Errorf("Test %d: match length, want %d, got %d", i, c.want, got)
922 }
923 }
924 }
925
926 func TestBestSpeedMaxMatchOffset(t *testing.T) {
927 t.Parallel()
928 const abc, xyz = "abcdefgh", "stuvwxyz"
929 for _, matchBefore := range []bool{false, true} {
930 for _, extra := range []int{0, inputMargin - 1, inputMargin, inputMargin + 1, 2 * inputMargin} {
931 for offsetAdj := -5; offsetAdj <= +5; offsetAdj++ {
932 report := func(desc string, err error) {
933 t.Errorf("matchBefore=%t, extra=%d, offsetAdj=%d: %s%v",
934 matchBefore, extra, offsetAdj, desc, err)
935 }
936
937 offset := maxMatchOffset + offsetAdj
938
939
940
941
942
943
944
945
946
947 src := make([]byte, offset+len(abc)+extra)
948 copy(src, abc)
949 if !matchBefore {
950 copy(src[offset-len(xyz):], xyz)
951 }
952 copy(src[offset:], abc)
953
954 buf := new(bytes.Buffer)
955 w, err := NewWriter(buf, BestSpeed)
956 if err != nil {
957 report("NewWriter: ", err)
958 continue
959 }
960 if _, err := w.Write(src); err != nil {
961 report("Write: ", err)
962 continue
963 }
964 if err := w.Close(); err != nil {
965 report("Writer.Close: ", err)
966 continue
967 }
968
969 r := NewReader(buf)
970 dst, err := io.ReadAll(r)
971 r.Close()
972 if err != nil {
973 report("ReadAll: ", err)
974 continue
975 }
976
977 if !bytes.Equal(dst, src) {
978 report("", fmt.Errorf("bytes differ after round-tripping"))
979 continue
980 }
981 }
982 }
983 }
984 }
985
986 func TestBestSpeedShiftOffsets(t *testing.T) {
987
988
989 enc := newDeflateFast()
990
991
992 testData := make([]byte, 32)
993 rng := rand.New(rand.NewSource(0))
994 for i := range testData {
995 testData[i] = byte(rng.Uint32())
996 }
997
998
999
1000 wantFirstTokens := len(enc.encode(nil, testData))
1001 wantSecondTokens := len(enc.encode(nil, testData))
1002
1003 if wantFirstTokens <= wantSecondTokens {
1004 t.Fatalf("test needs matches between inputs to be generated")
1005 }
1006
1007 enc.cur = bufferReset - int32(len(testData))
1008
1009
1010 got := len(enc.encode(nil, testData))
1011 if wantFirstTokens != got {
1012 t.Errorf("got %d, want %d tokens", got, wantFirstTokens)
1013 }
1014
1015
1016 if enc.cur != bufferReset {
1017 t.Errorf("got %d, want e.cur to be at bufferReset (%d)", enc.cur, bufferReset)
1018 }
1019
1020
1021 got = len(enc.encode(nil, testData))
1022 if wantSecondTokens != got {
1023 t.Errorf("got %d, want %d token", got, wantSecondTokens)
1024 }
1025
1026
1027 if enc.cur >= bufferReset {
1028 t.Errorf("want e.cur to be < bufferReset (%d), got %d", bufferReset, enc.cur)
1029 }
1030
1031
1032 enc.cur = bufferReset
1033 enc.shiftOffsets()
1034
1035
1036 got = len(enc.encode(nil, testData))
1037 if wantFirstTokens != got {
1038 t.Errorf("got %d, want %d tokens", got, wantFirstTokens)
1039 }
1040 }
1041
1042 func TestMaxStackSize(t *testing.T) {
1043
1044
1045 n := debug.SetMaxStack(1 << 16)
1046 defer debug.SetMaxStack(n)
1047
1048 var wg sync.WaitGroup
1049 defer wg.Wait()
1050
1051 b := make([]byte, 1<<20)
1052 for level := HuffmanOnly; level <= BestCompression; level++ {
1053
1054 wg.Add(1)
1055 go func(level int) {
1056 defer wg.Done()
1057 zw, err := NewWriter(io.Discard, level)
1058 if err != nil {
1059 t.Errorf("level %d, NewWriter() = %v, want nil", level, err)
1060 }
1061 if n, err := zw.Write(b); n != len(b) || err != nil {
1062 t.Errorf("level %d, Write() = (%d, %v), want (%d, nil)", level, n, err, len(b))
1063 }
1064 if err := zw.Close(); err != nil {
1065 t.Errorf("level %d, Close() = %v, want nil", level, err)
1066 }
1067 zw.Reset(io.Discard)
1068 }(level)
1069 }
1070 }
1071
View as plain text