summaryrefslogtreecommitdiffstats
path: root/src/compress/bzip2/bzip2_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/compress/bzip2/bzip2_test.go')
-rw-r--r--src/compress/bzip2/bzip2_test.go240
1 files changed, 240 insertions, 0 deletions
diff --git a/src/compress/bzip2/bzip2_test.go b/src/compress/bzip2/bzip2_test.go
new file mode 100644
index 0000000..e6065cb
--- /dev/null
+++ b/src/compress/bzip2/bzip2_test.go
@@ -0,0 +1,240 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bzip2
+
+import (
+ "bytes"
+ "encoding/hex"
+ "fmt"
+ "io"
+ "os"
+ "testing"
+)
+
+func mustDecodeHex(s string) []byte {
+ b, err := hex.DecodeString(s)
+ if err != nil {
+ panic(err)
+ }
+ return b
+}
+
+func mustLoadFile(f string) []byte {
+ b, err := os.ReadFile(f)
+ if err != nil {
+ panic(err)
+ }
+ return b
+}
+
+func trim(b []byte) string {
+ const limit = 1024
+ if len(b) < limit {
+ return fmt.Sprintf("%q", b)
+ }
+ return fmt.Sprintf("%q...", b[:limit])
+}
+
+func TestReader(t *testing.T) {
+ var vectors = []struct {
+ desc string
+ input []byte
+ output []byte
+ fail bool
+ }{{
+ desc: "hello world",
+ input: mustDecodeHex("" +
+ "425a68393141592653594eece83600000251800010400006449080200031064c" +
+ "4101a7a9a580bb9431f8bb9229c28482776741b0",
+ ),
+ output: []byte("hello world\n"),
+ }, {
+ desc: "concatenated files",
+ input: mustDecodeHex("" +
+ "425a68393141592653594eece83600000251800010400006449080200031064c" +
+ "4101a7a9a580bb9431f8bb9229c28482776741b0425a68393141592653594eec" +
+ "e83600000251800010400006449080200031064c4101a7a9a580bb9431f8bb92" +
+ "29c28482776741b0",
+ ),
+ output: []byte("hello world\nhello world\n"),
+ }, {
+ desc: "32B zeros",
+ input: mustDecodeHex("" +
+ "425a6839314159265359b5aa5098000000600040000004200021008283177245" +
+ "385090b5aa5098",
+ ),
+ output: make([]byte, 32),
+ }, {
+ desc: "1MiB zeros",
+ input: mustDecodeHex("" +
+ "425a683931415926535938571ce50008084000c0040008200030cc0529a60806" +
+ "c4201e2ee48a70a12070ae39ca",
+ ),
+ output: make([]byte, 1<<20),
+ }, {
+ desc: "random data",
+ input: mustLoadFile("testdata/pass-random1.bz2"),
+ output: mustLoadFile("testdata/pass-random1.bin"),
+ }, {
+ desc: "random data - full symbol range",
+ input: mustLoadFile("testdata/pass-random2.bz2"),
+ output: mustLoadFile("testdata/pass-random2.bin"),
+ }, {
+ desc: "random data - uses RLE1 stage",
+ input: mustDecodeHex("" +
+ "425a6839314159265359d992d0f60000137dfe84020310091c1e280e100e0428" +
+ "01099210094806c0110002e70806402000546034000034000000f28300000320" +
+ "00d3403264049270eb7a9280d308ca06ad28f6981bee1bf8160727c7364510d7" +
+ "3a1e123083421b63f031f63993a0f40051fbf177245385090d992d0f60",
+ ),
+ output: mustDecodeHex("" +
+ "92d5652616ac444a4a04af1a8a3964aca0450d43d6cf233bd03233f4ba92f871" +
+ "9e6c2a2bd4f5f88db07ecd0da3a33b263483db9b2c158786ad6363be35d17335" +
+ "ba",
+ ),
+ }, {
+ desc: "1MiB sawtooth",
+ input: mustLoadFile("testdata/pass-sawtooth.bz2"),
+ output: func() []byte {
+ b := make([]byte, 1<<20)
+ for i := range b {
+ b[i] = byte(i)
+ }
+ return b
+ }(),
+ }, {
+ desc: "RLE2 buffer overrun - issue 5747",
+ input: mustLoadFile("testdata/fail-issue5747.bz2"),
+ fail: true,
+ }, {
+ desc: "out-of-range selector - issue 8363",
+ input: mustDecodeHex("" +
+ "425a68393141592653594eece83600000251800010400006449080200031064c" +
+ "4101a7a9a580bb943117724538509000000000",
+ ),
+ fail: true,
+ }, {
+ desc: "bad block size - issue 13941",
+ input: mustDecodeHex("" +
+ "425a683131415926535936dc55330063ffc0006000200020a40830008b0008b8" +
+ "bb9229c28481b6e2a998",
+ ),
+ fail: true,
+ }, {
+ desc: "bad huffman delta",
+ input: mustDecodeHex("" +
+ "425a6836314159265359b1f7404b000000400040002000217d184682ee48a70a" +
+ "12163ee80960",
+ ),
+ fail: true,
+ }}
+
+ for i, v := range vectors {
+ rd := NewReader(bytes.NewReader(v.input))
+ buf, err := io.ReadAll(rd)
+
+ if fail := bool(err != nil); fail != v.fail {
+ if fail {
+ t.Errorf("test %d (%s), unexpected failure: %v", i, v.desc, err)
+ } else {
+ t.Errorf("test %d (%s), unexpected success", i, v.desc)
+ }
+ }
+ if !v.fail && !bytes.Equal(buf, v.output) {
+ t.Errorf("test %d (%s), output mismatch:\ngot %s\nwant %s", i, v.desc, trim(buf), trim(v.output))
+ }
+ }
+}
+
+func TestBitReader(t *testing.T) {
+ var vectors = []struct {
+ nbits uint // Number of bits to read
+ value int // Expected output value (0 for error)
+ fail bool // Expected operation failure?
+ }{
+ {nbits: 1, value: 1},
+ {nbits: 1, value: 0},
+ {nbits: 1, value: 1},
+ {nbits: 5, value: 11},
+ {nbits: 32, value: 0x12345678},
+ {nbits: 15, value: 14495},
+ {nbits: 3, value: 6},
+ {nbits: 6, value: 13},
+ {nbits: 1, fail: true},
+ }
+
+ rd := bytes.NewReader([]byte{0xab, 0x12, 0x34, 0x56, 0x78, 0x71, 0x3f, 0x8d})
+ br := newBitReader(rd)
+ for i, v := range vectors {
+ val := br.ReadBits(v.nbits)
+ if fail := bool(br.err != nil); fail != v.fail {
+ if fail {
+ t.Errorf("test %d, unexpected failure: ReadBits(%d) = %v", i, v.nbits, br.err)
+ } else {
+ t.Errorf("test %d, unexpected success: ReadBits(%d) = nil", i, v.nbits)
+ }
+ }
+ if !v.fail && val != v.value {
+ t.Errorf("test %d, mismatching value: ReadBits(%d) = %d, want %d", i, v.nbits, val, v.value)
+ }
+ }
+}
+
+func TestMTF(t *testing.T) {
+ var vectors = []struct {
+ idx int // Input index
+ sym uint8 // Expected output symbol
+ }{
+ {idx: 1, sym: 1}, // [1 0 2 3 4]
+ {idx: 0, sym: 1}, // [1 0 2 3 4]
+ {idx: 1, sym: 0}, // [0 1 2 3 4]
+ {idx: 4, sym: 4}, // [4 0 1 2 3]
+ {idx: 1, sym: 0}, // [0 4 1 2 3]
+ }
+
+ mtf := newMTFDecoderWithRange(5)
+ for i, v := range vectors {
+ sym := mtf.Decode(v.idx)
+ t.Log(mtf)
+ if sym != v.sym {
+ t.Errorf("test %d, symbol mismatch: Decode(%d) = %d, want %d", i, v.idx, sym, v.sym)
+ }
+ }
+}
+
+func TestZeroRead(t *testing.T) {
+ b := mustDecodeHex("425a6839314159265359b5aa5098000000600040000004200021008283177245385090b5aa5098")
+ r := NewReader(bytes.NewReader(b))
+ if n, err := r.Read(nil); n != 0 || err != nil {
+ t.Errorf("Read(nil) = (%d, %v), want (0, nil)", n, err)
+ }
+}
+
+var (
+ digits = mustLoadFile("testdata/e.txt.bz2")
+ newton = mustLoadFile("testdata/Isaac.Newton-Opticks.txt.bz2")
+ random = mustLoadFile("testdata/random.data.bz2")
+)
+
+func benchmarkDecode(b *testing.B, compressed []byte) {
+ // Determine the uncompressed size of testfile.
+ uncompressedSize, err := io.Copy(io.Discard, NewReader(bytes.NewReader(compressed)))
+ if err != nil {
+ b.Fatal(err)
+ }
+
+ b.SetBytes(uncompressedSize)
+ b.ReportAllocs()
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ r := bytes.NewReader(compressed)
+ io.Copy(io.Discard, NewReader(r))
+ }
+}
+
+func BenchmarkDecodeDigits(b *testing.B) { benchmarkDecode(b, digits) }
+func BenchmarkDecodeNewton(b *testing.B) { benchmarkDecode(b, newton) }
+func BenchmarkDecodeRand(b *testing.B) { benchmarkDecode(b, random) }