1 package huff0
2
3 import (
4 "bytes"
5 "fmt"
6 "io"
7 "math/rand"
8 "os"
9 "path/filepath"
10 "reflect"
11 "strings"
12 "testing"
13
14 "github.com/klauspost/compress/flate"
15 "github.com/klauspost/compress/zip"
16 )
17
18 type inputFn func() ([]byte, error)
19
20 var testfiles = []struct {
21 name string
22 fn inputFn
23 err1X error
24 err4X error
25 }{
26
27
28
29 {name: "digits", fn: func() ([]byte, error) { return os.ReadFile("../testdata/e.txt") }},
30
31 {name: "gettysburg", fn: func() ([]byte, error) { return os.ReadFile("../testdata/gettysburg.txt") }},
32
33 {name: "twain", fn: func() ([]byte, error) { return os.ReadFile("../testdata/Mark.Twain-Tom.Sawyer.txt") }},
34
35 {name: "random", fn: func() ([]byte, error) { return os.ReadFile("../testdata/sharnd.out") }, err1X: ErrIncompressible, err4X: ErrIncompressible},
36
37 {name: "low-ent.10k", fn: func() ([]byte, error) { return []byte(strings.Repeat("1221", 10000)), nil }},
38
39 {name: "superlow-ent-10k", fn: func() ([]byte, error) { return []byte(strings.Repeat("1", 10000) + strings.Repeat("2", 500)), nil }},
40
41 {name: "zeroes", fn: func() ([]byte, error) { return make([]byte, 10000), nil }, err1X: ErrUseRLE, err4X: ErrUseRLE},
42 {name: "crash1", fn: func() ([]byte, error) { return os.ReadFile("../testdata/crash1.bin") }, err1X: ErrIncompressible, err4X: ErrIncompressible},
43 {name: "crash2", fn: func() ([]byte, error) { return os.ReadFile("../testdata/crash2.bin") }, err4X: ErrIncompressible},
44 {name: "crash3", fn: func() ([]byte, error) { return os.ReadFile("../testdata/crash3.bin") }, err1X: ErrIncompressible, err4X: ErrIncompressible},
45 {name: "endzerobits", fn: func() ([]byte, error) { return os.ReadFile("../testdata/endzerobits.bin") }, err1X: nil, err4X: ErrIncompressible},
46 {name: "endnonzero", fn: func() ([]byte, error) { return os.ReadFile("../testdata/endnonzero.bin") }, err4X: ErrIncompressible},
47 {name: "case1", fn: func() ([]byte, error) { return os.ReadFile("../testdata/case1.bin") }, err1X: nil},
48 {name: "case2", fn: func() ([]byte, error) { return os.ReadFile("../testdata/case2.bin") }, err1X: nil},
49 {name: "case3", fn: func() ([]byte, error) { return os.ReadFile("../testdata/case3.bin") }, err1X: nil},
50 {name: "pngdata.001", fn: func() ([]byte, error) { return os.ReadFile("../testdata/pngdata.bin") }, err1X: nil},
51 {name: "normcount2", fn: func() ([]byte, error) { return os.ReadFile("../testdata/normcount2.bin") }, err1X: nil},
52 }
53
54 type fuzzInput struct {
55 name string
56 fn inputFn
57 }
58
59
60
61 var testfilesExtended []fuzzInput
62
63 func init() {
64 data, err := os.ReadFile("testdata/regression.zip")
65 if err != nil {
66 panic(err)
67 }
68 zr, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
69 if err != nil {
70 panic(err)
71 }
72 for _, tt := range zr.File {
73 if tt.UncompressedSize64 == 0 {
74 continue
75 }
76 rc, err := tt.Open()
77 if err != nil {
78 panic(err)
79 }
80 b, err := io.ReadAll(rc)
81 if err != nil {
82 panic(err)
83 }
84 testfilesExtended = append(testfilesExtended, fuzzInput{
85 name: filepath.Base(tt.Name),
86 fn: func() ([]byte, error) {
87 return b, nil
88 },
89 })
90 }
91 }
92
93 func TestCompressRegression(t *testing.T) {
94
95 var testInput = func(t *testing.T, data []byte) int {
96 var enc Scratch
97 enc.WantLogLess = 5
98 comp, _, err := Compress1X(data, &enc)
99 if err == ErrIncompressible || err == ErrUseRLE || err == ErrTooBig {
100 return 0
101 }
102 if err != nil {
103 panic(err)
104 }
105 if len(comp) >= len(data)-len(data)>>enc.WantLogLess {
106 panic(fmt.Errorf("too large output provided. got %d, but should be < %d", len(comp), len(data)-len(data)>>enc.WantLogLess))
107 }
108
109 dec, remain, err := ReadTable(comp, nil)
110 if err != nil {
111 panic(err)
112 }
113 out, err := dec.Decompress1X(remain)
114 if err != nil {
115 t.Error(err)
116 }
117 if !bytes.Equal(out, data) {
118 t.Error("decompression 1x mismatch")
119 }
120
121 enc.Reuse = ReusePolicyAllow
122 comp, reUsed, err := Compress4X(data, &enc)
123 if err == ErrIncompressible || err == ErrUseRLE || err == ErrTooBig {
124 return 0
125 }
126 if err != nil {
127 panic(err)
128 }
129 if len(comp) >= len(data)-len(data)>>enc.WantLogLess {
130 panic(fmt.Errorf("too large output provided. got %d, but should be < %d", len(comp), len(data)-len(data)>>enc.WantLogLess))
131 }
132
133 remain = comp
134 if !reUsed {
135 dec, remain, err = ReadTable(comp, dec)
136 if err != nil {
137 panic(err)
138 }
139 }
140 out, err = dec.Decompress4X(remain, len(data))
141 if err != nil {
142 t.Error(err)
143 }
144 if !bytes.Equal(out, data) {
145 t.Error("decompression 4x with reuse mismatch")
146 }
147
148 enc.Reuse = ReusePolicyNone
149 comp, reUsed, err = Compress4X(data, &enc)
150 if err == ErrIncompressible || err == ErrUseRLE || err == ErrTooBig {
151 return 0
152 }
153 if err != nil {
154 panic(err)
155 }
156 if reUsed {
157 panic("reused when asked not to")
158 }
159 if len(comp) >= len(data)-len(data)>>enc.WantLogLess {
160 panic(fmt.Errorf("too large output provided. got %d, but should be < %d", len(comp), len(data)-len(data)>>enc.WantLogLess))
161 }
162
163 dec, remain, err = ReadTable(comp, dec)
164 if err != nil {
165 panic(err)
166 }
167 out, err = dec.Decompress4X(remain, len(data))
168 if err != nil {
169 t.Error(err)
170 }
171 if !bytes.Equal(out, data) {
172 t.Error("decompression 4x mismatch")
173 }
174
175
176 dec.Reuse = ReusePolicyAllow
177 comp, reUsed, err = Compress1X(data, &enc)
178 if err == ErrIncompressible || err == ErrUseRLE || err == ErrTooBig {
179 return 0
180 }
181 if err != nil {
182 panic(err)
183 }
184 if len(comp) >= len(data)-len(data)>>enc.WantLogLess {
185 panic(fmt.Errorf("too large output provided. got %d, but should be < %d", len(comp), len(data)-len(data)>>enc.WantLogLess))
186 }
187
188 remain = comp
189 if !reUsed {
190 dec, remain, err = ReadTable(comp, dec)
191 if err != nil {
192 panic(err)
193 }
194 }
195 out, err = dec.Decompress1X(remain)
196 if err != nil {
197 t.Error(err)
198 }
199 if !bytes.Equal(out, data) {
200 t.Error("decompression 1x with reuse mismatch")
201 }
202 return 1
203 }
204 for _, test := range testfiles {
205 t.Run(test.name, func(t *testing.T) {
206 buf0, err := test.fn()
207 if err != nil {
208 t.Fatal(err)
209 }
210 testInput(t, buf0)
211 })
212 }
213 for _, test := range testfilesExtended {
214 t.Run(test.name, func(t *testing.T) {
215 buf0, err := test.fn()
216 if err != nil {
217 t.Fatal(err)
218 }
219 testInput(t, buf0)
220 })
221 }
222 }
223
224 func TestCompress1X(t *testing.T) {
225 for _, test := range testfiles {
226 t.Run(test.name, func(t *testing.T) {
227 var s Scratch
228 buf0, err := test.fn()
229 if err != nil {
230 t.Fatal(err)
231 }
232 if len(buf0) > BlockSizeMax {
233 buf0 = buf0[:BlockSizeMax]
234 }
235 tbSz, dSz, reSz, _ := EstimateSizes(buf0, &s)
236 b, re, err := Compress1X(buf0, &s)
237 if err != test.err1X {
238 t.Errorf("want error %v (%T), got %v (%T)", test.err1X, test.err1X, err, err)
239 }
240 if err != nil {
241 t.Log(test.name, err.Error())
242 return
243 }
244 if b == nil {
245 t.Error("got no output")
246 return
247 }
248 min := s.minSize(len(buf0))
249 if len(s.OutData) < min {
250 t.Errorf("output data length (%d) below shannon limit (%d)", len(s.OutData), min)
251 }
252 if len(s.OutTable) == 0 {
253 t.Error("got no table definition")
254 }
255 if re {
256 t.Error("claimed to have re-used.")
257 }
258 if len(s.OutData) == 0 {
259 t.Error("got no data output")
260 }
261 t.Logf("Estimate: table %d, got %d, data %d, got %d, reuse: %d", tbSz, len(s.OutTable), dSz, len(s.OutData), reSz)
262 t.Logf("%s: %d -> %d bytes (%.2f:1) re:%t (table: %d bytes)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable))
263 s.Out = nil
264 bRe, _, err := Compress1X(b, &s)
265 if err == nil {
266 t.Log("Could re-compress to", len(bRe))
267 }
268 })
269 }
270 }
271
272 func TestCompress1XMustReuse(t *testing.T) {
273 for _, test := range testfiles {
274 t.Run(test.name, func(t *testing.T) {
275 var s Scratch
276 buf0, err := test.fn()
277 if err != nil {
278 t.Fatal(err)
279 }
280 if len(buf0) > BlockSizeMax {
281 buf0 = buf0[:BlockSizeMax]
282 }
283 b, re, err := Compress1X(buf0, &s)
284 if err != test.err1X {
285 t.Errorf("want error %v (%T), got %v (%T)", test.err1X, test.err1X, err, err)
286 }
287 if err != nil {
288 t.Log(test.name, err.Error())
289 return
290 }
291 if b == nil {
292 t.Error("got no output")
293 return
294 }
295
296 min := s.minSize(len(buf0))
297 if len(s.OutData) < min {
298 t.Errorf("output data length (%d) below shannon limit (%d)", len(s.OutData), min)
299 }
300 if len(s.OutTable) == 0 {
301 t.Error("got no table definition")
302 }
303 if re {
304 t.Error("claimed to have re-used.")
305 }
306 if len(s.OutData) == 0 {
307 t.Error("got no data output")
308 }
309 t.Logf("%s: %d -> %d bytes (%.2f:1) re:%t (table: %d bytes)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable))
310 table := s.OutTable
311 prevTable := s.prevTable
312 for i, v := range prevTable {
313
314 if v.nBits == 0 {
315 prevTable[i].val = 0
316 }
317 }
318 b = s.OutData
319 actl := s.actualTableLog
320
321
322 s = Scratch{}
323 s2 := &s
324 s.Reuse = ReusePolicyMust
325 s2, _, err = ReadTable(table, s2)
326 if err != nil {
327 t.Error("Could not read table", err)
328 return
329 }
330 if !reflect.DeepEqual(prevTable, s2.prevTable) {
331 t.Errorf("prevtable mismatch.\ngot %v\nwant %v", s2.prevTable, prevTable)
332 }
333 if actl != s.actualTableLog {
334 t.Errorf("tablelog mismatch, want %d, got %d", actl, s.actualTableLog)
335 }
336 b2, reused, err := Compress1X(buf0, s2)
337 if err != nil {
338 t.Error("Could not re-compress with prev table", err)
339 }
340 if !reused {
341 t.Error("didn't reuse...")
342 return
343 }
344 if len(b2) != len(b) {
345 t.Errorf("recompressed to different size, want %d, got %d", len(b), len(b2))
346 return
347 }
348
349 if !bytes.Equal(b, b2) {
350 for i := range b {
351 if b[i] != b2[i] {
352 t.Errorf("recompressed to different output. First mismatch at byte %d, (want %x != got %x)", i, b[i], b2[i])
353 return
354 }
355 }
356 }
357 })
358 }
359 }
360
361 func TestCompress4X(t *testing.T) {
362 for _, test := range testfiles {
363 t.Run(test.name, func(t *testing.T) {
364 var s Scratch
365 buf0, err := test.fn()
366 if err != nil {
367 t.Fatal(err)
368 }
369 if len(buf0) > BlockSizeMax {
370 buf0 = buf0[:BlockSizeMax]
371 }
372 b, re, err := Compress4X(buf0, &s)
373 if err != test.err4X {
374 t.Errorf("want error %v (%T), got %v (%T)", test.err1X, test.err4X, err, err)
375 }
376 if err != nil {
377 t.Log(test.name, err.Error())
378 return
379 }
380 if b == nil {
381 t.Error("got no output")
382 return
383 }
384 if len(s.OutTable) == 0 {
385 t.Error("got no table definition")
386 }
387 if re {
388 t.Error("claimed to have re-used.")
389 }
390 if len(s.OutData) == 0 {
391 t.Error("got no data output")
392 }
393
394 t.Logf("%s: %d -> %d bytes (%.2f:1) %t (table: %d bytes)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable))
395 })
396 }
397 }
398
399 func TestCompress4XReuse(t *testing.T) {
400 rng := rand.NewSource(0x1337)
401 var s Scratch
402 s.Reuse = ReusePolicyAllow
403 for i := 0; i < 255; i++ {
404 if testing.Short() && i > 10 {
405 break
406 }
407 t.Run(fmt.Sprint("test-", i), func(t *testing.T) {
408 buf0 := make([]byte, BlockSizeMax)
409 for j := range buf0 {
410 buf0[j] = byte(int64(i) + (rng.Int63() & 3))
411 }
412 tbSz, dSz, reSz, _ := EstimateSizes(buf0, &s)
413 b, re, err := Compress4X(buf0, &s)
414 if err != nil {
415 t.Fatal(err)
416 }
417 if b == nil {
418 t.Error("got no output")
419 return
420 }
421 if len(s.OutData) == 0 {
422 t.Error("got no data output")
423 }
424 if re {
425 t.Error("claimed to have re-used. Unlikely.")
426 }
427 t.Logf("Estimate: table %d, got %d, data %d, got %d, reuse: %d", tbSz, len(s.OutTable), dSz, len(s.OutData), reSz)
428 t.Logf("%s: %d -> %d bytes (%.2f:1) %t (table: %d bytes)", t.Name(), len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable))
429 })
430 }
431 }
432
433 func TestCompress4XReuseActually(t *testing.T) {
434 rng := rand.NewSource(0x1337)
435 var s Scratch
436 s.Reuse = ReusePolicyAllow
437 for i := 0; i < 255; i++ {
438 if testing.Short() && i > 10 {
439 break
440 }
441 t.Run(fmt.Sprint("test-", i), func(t *testing.T) {
442 buf0 := make([]byte, BlockSizeMax)
443 for j := range buf0 {
444 buf0[j] = byte(rng.Int63() & 7)
445 }
446
447 tbSz, dSz, reSz, _ := EstimateSizes(buf0, &s)
448 b, re, err := Compress4X(buf0, &s)
449 if err != nil {
450 t.Fatal(err)
451 }
452 if b == nil {
453 t.Error("got no output")
454 return
455 }
456 if len(s.OutData) == 0 {
457 t.Error("got no data output")
458 }
459 if re && i == 0 {
460 t.Error("Claimed to have re-used on first loop.")
461 }
462 if !re && i > 0 {
463 t.Error("Expected table to be reused")
464 }
465 t.Logf("Estimate: table %d, got %d, data %d, got %d, reuse: %d", tbSz, len(s.OutTable), dSz, len(s.OutData), reSz)
466 t.Logf("%s: %d -> %d bytes (%.2f:1) %t (table: %d bytes)", t.Name(), len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable))
467 })
468 }
469 }
470 func TestCompress1XReuse(t *testing.T) {
471 for _, test := range testfiles {
472 t.Run(test.name, func(t *testing.T) {
473 var s Scratch
474 buf0, err := test.fn()
475 if err != nil {
476 t.Fatal(err)
477 }
478 if len(buf0) > BlockSizeMax {
479 buf0 = buf0[:BlockSizeMax]
480 }
481 b, _, err := Compress1X(buf0, &s)
482 if err != test.err1X {
483 t.Errorf("want error %v (%T), got %v (%T)", test.err1X, test.err1X, err, err)
484 }
485 if err != nil {
486 t.Log(test.name, err.Error())
487 return
488 }
489 if b == nil {
490 t.Error("got no output")
491 return
492 }
493 firstData := len(s.OutData)
494 s.Reuse = ReusePolicyAllow
495 tbSz, dSz, reSz, _ := EstimateSizes(buf0, &s)
496 b, re, err := Compress1X(buf0, &s)
497 if err != nil {
498 t.Errorf("got secondary error %v (%T)", err, err)
499 return
500 }
501 if !re {
502 t.Error("Didn't re-use even if data was the same")
503 }
504 if len(s.OutTable) != 0 {
505 t.Error("got table definition, don't want any")
506 }
507 if len(s.OutData) == 0 {
508 t.Error("got no data output")
509 }
510 if len(b) != firstData {
511 t.Errorf("data length did not match first: %d, second:%d", firstData, len(b))
512 }
513 t.Logf("Estimate: table %d, got %d, data %d, got %d, reuse: %d", tbSz, len(s.OutTable), dSz, len(s.OutData), reSz)
514 t.Logf("%s: %d -> %d bytes (%.2f:1) %t", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re)
515 })
516 }
517 }
518
519 func BenchmarkDeflate(b *testing.B) {
520 for _, tt := range testfiles {
521 test := tt
522 if test.err1X != nil {
523 continue
524 }
525 b.Run(test.name, func(b *testing.B) {
526 dec, err := flate.NewWriter(io.Discard, flate.HuffmanOnly)
527 if err != nil {
528 b.Fatal(err)
529 }
530 if test.err1X != nil {
531 b.Skip("skipping")
532 }
533 buf0, err := test.fn()
534 if err != nil {
535 b.Fatal(err)
536 }
537 if len(buf0) > BlockSizeMax {
538 buf0 = buf0[:BlockSizeMax]
539 }
540 b.ResetTimer()
541 b.ReportAllocs()
542 b.SetBytes(int64(len(buf0)))
543 for i := 0; i < b.N; i++ {
544 dec.Reset(io.Discard)
545 n, err := dec.Write(buf0)
546 if err != nil {
547 b.Fatal(err)
548 }
549 if n != len(buf0) {
550 b.Fatal("mismatch", n, len(buf0))
551 }
552 dec.Close()
553 }
554 })
555 }
556 }
557
558 func BenchmarkCompress1XReuseNone(b *testing.B) {
559 for _, tt := range testfiles {
560 test := tt
561 if test.err1X != nil {
562 continue
563 }
564 b.Run(test.name, func(b *testing.B) {
565 var s Scratch
566 s.Reuse = ReusePolicyNone
567 buf0, err := test.fn()
568 if err != nil {
569 b.Fatal(err)
570 }
571 if len(buf0) > BlockSizeMax {
572 buf0 = buf0[:BlockSizeMax]
573 }
574 _, _, err = Compress1X(buf0, &s)
575 if err != test.err1X {
576 b.Fatal("unexpected error:", err)
577 }
578 b.ResetTimer()
579 b.ReportAllocs()
580 b.SetBytes(int64(len(buf0)))
581 for i := 0; i < b.N; i++ {
582 _, re, _ := Compress1X(buf0, &s)
583 if re {
584 b.Fatal("reused")
585 }
586 }
587 })
588 }
589 }
590
591 func BenchmarkCompress1XReuseAllow(b *testing.B) {
592 for _, tt := range testfiles {
593 test := tt
594 if test.err1X != nil {
595 continue
596 }
597 b.Run(test.name, func(b *testing.B) {
598 var s Scratch
599 s.Reuse = ReusePolicyAllow
600 buf0, err := test.fn()
601 if err != nil {
602 b.Fatal(err)
603 }
604 if len(buf0) > BlockSizeMax {
605 buf0 = buf0[:BlockSizeMax]
606 }
607 _, _, err = Compress1X(buf0, &s)
608 if err != test.err1X {
609 b.Fatal("unexpected error:", err)
610 }
611 b.ResetTimer()
612 b.ReportAllocs()
613 b.SetBytes(int64(len(buf0)))
614 for i := 0; i < b.N; i++ {
615 _, re, _ := Compress1X(buf0, &s)
616 if !re {
617 b.Fatal("not reused")
618 }
619 }
620 })
621 }
622 }
623
624 func BenchmarkCompress1XReusePrefer(b *testing.B) {
625 for _, tt := range testfiles {
626 test := tt
627 if test.err1X != nil {
628 continue
629 }
630 b.Run(test.name, func(b *testing.B) {
631 var s Scratch
632 s.Reuse = ReusePolicyPrefer
633 buf0, err := test.fn()
634 if err != nil {
635 b.Fatal(err)
636 }
637 if len(buf0) > BlockSizeMax {
638 buf0 = buf0[:BlockSizeMax]
639 }
640 _, _, err = Compress1X(buf0, &s)
641 if err != test.err1X {
642 b.Fatal("unexpected error:", err)
643 }
644 b.ResetTimer()
645 b.ReportAllocs()
646 b.SetBytes(int64(len(buf0)))
647 for i := 0; i < b.N; i++ {
648 _, re, _ := Compress1X(buf0, &s)
649 if !re {
650 b.Fatal("not reused")
651 }
652 }
653 })
654 }
655 }
656
657 func BenchmarkCompress4XReuseNone(b *testing.B) {
658 for _, tt := range testfiles {
659 test := tt
660 if test.err4X != nil {
661 continue
662 }
663 b.Run(test.name, func(b *testing.B) {
664 var s Scratch
665 s.Reuse = ReusePolicyNone
666 buf0, err := test.fn()
667 if err != nil {
668 b.Fatal(err)
669 }
670 if len(buf0) > BlockSizeMax {
671 buf0 = buf0[:BlockSizeMax]
672 }
673 _, _, err = Compress4X(buf0, &s)
674 if err != test.err1X {
675 b.Fatal("unexpected error:", err)
676 }
677 b.ResetTimer()
678 b.ReportAllocs()
679 b.SetBytes(int64(len(buf0)))
680 for i := 0; i < b.N; i++ {
681 _, re, _ := Compress4X(buf0, &s)
682 if re {
683 b.Fatal("reused")
684 }
685 }
686 })
687 }
688 }
689
690 func BenchmarkCompress4XReuseAllow(b *testing.B) {
691 for _, tt := range testfiles {
692 test := tt
693 if test.err4X != nil {
694 continue
695 }
696 b.Run(test.name, func(b *testing.B) {
697 var s Scratch
698 s.Reuse = ReusePolicyAllow
699 buf0, err := test.fn()
700 if err != nil {
701 b.Fatal(err)
702 }
703 if len(buf0) > BlockSizeMax {
704 buf0 = buf0[:BlockSizeMax]
705 }
706 _, _, err = Compress4X(buf0, &s)
707 if err != test.err1X {
708 b.Fatal("unexpected error:", err)
709 }
710 b.ResetTimer()
711 b.ReportAllocs()
712 b.SetBytes(int64(len(buf0)))
713 for i := 0; i < b.N; i++ {
714 _, re, _ := Compress4X(buf0, &s)
715 if !re {
716 b.Fatal("not reused")
717 }
718 }
719 })
720 }
721 }
722
723 func BenchmarkCompress4XReusePrefer(b *testing.B) {
724 for _, tt := range testfiles {
725 test := tt
726 if test.err4X != nil {
727 continue
728 }
729 b.Run(test.name, func(b *testing.B) {
730 var s Scratch
731 s.Reuse = ReusePolicyPrefer
732 buf0, err := test.fn()
733 if err != nil {
734 b.Fatal(err)
735 }
736 if len(buf0) > BlockSizeMax {
737 buf0 = buf0[:BlockSizeMax]
738 }
739 _, _, err = Compress4X(buf0, &s)
740 if err != test.err4X {
741 b.Fatal("unexpected error:", err)
742 }
743 b.ResetTimer()
744 b.ReportAllocs()
745 b.SetBytes(int64(len(buf0)))
746 for i := 0; i < b.N; i++ {
747 _, re, _ := Compress4X(buf0, &s)
748 if !re {
749 b.Fatal("not reused")
750 }
751 }
752 })
753 }
754 }
755
756 func BenchmarkCompress1XSizes(b *testing.B) {
757 test := testfiles[0]
758 sizes := []int{1e2, 2e2, 5e2, 1e3, 5e3, 1e4, 5e4}
759 for _, size := range sizes {
760 b.Run(test.name+"-"+fmt.Sprint(size), func(b *testing.B) {
761 var s Scratch
762 s.Reuse = ReusePolicyNone
763 buf0, err := test.fn()
764 if err != nil {
765 b.Fatal(err)
766 }
767 buf0 = buf0[:size]
768 _, _, err = Compress1X(buf0, &s)
769 if err != test.err1X {
770 b.Fatal("unexpected error:", err)
771 }
772
773 b.ResetTimer()
774 b.ReportAllocs()
775 b.SetBytes(int64(len(buf0)))
776 for i := 0; i < b.N; i++ {
777 _, re, _ := Compress1X(buf0, &s)
778 if re {
779 b.Fatal("reused")
780 }
781 }
782 })
783 }
784 }
785
786 func BenchmarkCompress4XSizes(b *testing.B) {
787 test := testfiles[0]
788 sizes := []int{1e2, 2e2, 5e2, 1e3, 5e3, 1e4, 5e4}
789 for _, size := range sizes {
790 b.Run(test.name+"-"+fmt.Sprint(size), func(b *testing.B) {
791 var s Scratch
792 s.Reuse = ReusePolicyNone
793 buf0, err := test.fn()
794 if err != nil {
795 b.Fatal(err)
796 }
797 buf0 = buf0[:size]
798 _, _, err = Compress4X(buf0, &s)
799 if err != test.err1X {
800 b.Fatal("unexpected error:", err)
801 }
802
803 b.ResetTimer()
804 b.ReportAllocs()
805 b.SetBytes(int64(len(buf0)))
806 for i := 0; i < b.N; i++ {
807 _, re, _ := Compress4X(buf0, &s)
808 if re {
809 b.Fatal("reused")
810 }
811 }
812 })
813 }
814 }
815
View as plain text