1
2
3
4
5 package bzip2
6
7 import (
8 "bytes"
9 "encoding/hex"
10 "fmt"
11 "internal/obscuretestdata"
12 "io"
13 "os"
14 "strings"
15 "testing"
16 )
17
18 func mustDecodeHex(s string) []byte {
19 b, err := hex.DecodeString(s)
20 if err != nil {
21 panic(err)
22 }
23 return b
24 }
25
26 func mustLoadFile(f string) []byte {
27 if strings.HasSuffix(f, ".base64") {
28 tf, err := obscuretestdata.DecodeToTempFile(f)
29 if err != nil {
30 panic(fmt.Sprintf("obscuretestdata.DecodeToTempFile(%s): %v", f, err))
31 }
32 f = tf
33 }
34
35 b, err := os.ReadFile(f)
36 if err != nil {
37 panic(err)
38 }
39 return b
40 }
41
42 func trim(b []byte) string {
43 const limit = 1024
44 if len(b) < limit {
45 return fmt.Sprintf("%q", b)
46 }
47 return fmt.Sprintf("%q...", b[:limit])
48 }
49
50 func TestReader(t *testing.T) {
51 var vectors = []struct {
52 desc string
53 input []byte
54 output []byte
55 fail bool
56 }{{
57 desc: "hello world",
58 input: mustDecodeHex("" +
59 "425a68393141592653594eece83600000251800010400006449080200031064c" +
60 "4101a7a9a580bb9431f8bb9229c28482776741b0",
61 ),
62 output: []byte("hello world\n"),
63 }, {
64 desc: "concatenated files",
65 input: mustDecodeHex("" +
66 "425a68393141592653594eece83600000251800010400006449080200031064c" +
67 "4101a7a9a580bb9431f8bb9229c28482776741b0425a68393141592653594eec" +
68 "e83600000251800010400006449080200031064c4101a7a9a580bb9431f8bb92" +
69 "29c28482776741b0",
70 ),
71 output: []byte("hello world\nhello world\n"),
72 }, {
73 desc: "32B zeros",
74 input: mustDecodeHex("" +
75 "425a6839314159265359b5aa5098000000600040000004200021008283177245" +
76 "385090b5aa5098",
77 ),
78 output: make([]byte, 32),
79 }, {
80 desc: "1MiB zeros",
81 input: mustDecodeHex("" +
82 "425a683931415926535938571ce50008084000c0040008200030cc0529a60806" +
83 "c4201e2ee48a70a12070ae39ca",
84 ),
85 output: make([]byte, 1<<20),
86 }, {
87 desc: "random data",
88 input: mustLoadFile("testdata/pass-random1.bz2"),
89 output: mustLoadFile("testdata/pass-random1.bin"),
90 }, {
91 desc: "random data - full symbol range",
92 input: mustLoadFile("testdata/pass-random2.bz2"),
93 output: mustLoadFile("testdata/pass-random2.bin"),
94 }, {
95 desc: "random data - uses RLE1 stage",
96 input: mustDecodeHex("" +
97 "425a6839314159265359d992d0f60000137dfe84020310091c1e280e100e0428" +
98 "01099210094806c0110002e70806402000546034000034000000f28300000320" +
99 "00d3403264049270eb7a9280d308ca06ad28f6981bee1bf8160727c7364510d7" +
100 "3a1e123083421b63f031f63993a0f40051fbf177245385090d992d0f60",
101 ),
102 output: mustDecodeHex("" +
103 "92d5652616ac444a4a04af1a8a3964aca0450d43d6cf233bd03233f4ba92f871" +
104 "9e6c2a2bd4f5f88db07ecd0da3a33b263483db9b2c158786ad6363be35d17335" +
105 "ba",
106 ),
107 }, {
108 desc: "1MiB sawtooth",
109 input: mustLoadFile("testdata/pass-sawtooth.bz2"),
110 output: func() []byte {
111 b := make([]byte, 1<<20)
112 for i := range b {
113 b[i] = byte(i)
114 }
115 return b
116 }(),
117 }, {
118 desc: "RLE2 buffer overrun - issue 5747",
119 input: mustLoadFile("testdata/fail-issue5747.bz2.base64"),
120 fail: true,
121 }, {
122 desc: "out-of-range selector - issue 8363",
123 input: mustDecodeHex("" +
124 "425a68393141592653594eece83600000251800010400006449080200031064c" +
125 "4101a7a9a580bb943117724538509000000000",
126 ),
127 fail: true,
128 }, {
129 desc: "bad block size - issue 13941",
130 input: mustDecodeHex("" +
131 "425a683131415926535936dc55330063ffc0006000200020a40830008b0008b8" +
132 "bb9229c28481b6e2a998",
133 ),
134 fail: true,
135 }, {
136 desc: "bad huffman delta",
137 input: mustDecodeHex("" +
138 "425a6836314159265359b1f7404b000000400040002000217d184682ee48a70a" +
139 "12163ee80960",
140 ),
141 fail: true,
142 }}
143
144 for i, v := range vectors {
145 rd := NewReader(bytes.NewReader(v.input))
146 buf, err := io.ReadAll(rd)
147
148 if fail := bool(err != nil); fail != v.fail {
149 if fail {
150 t.Errorf("test %d (%s), unexpected failure: %v", i, v.desc, err)
151 } else {
152 t.Errorf("test %d (%s), unexpected success", i, v.desc)
153 }
154 }
155 if !v.fail && !bytes.Equal(buf, v.output) {
156 t.Errorf("test %d (%s), output mismatch:\ngot %s\nwant %s", i, v.desc, trim(buf), trim(v.output))
157 }
158 }
159 }
160
161 func TestBitReader(t *testing.T) {
162 var vectors = []struct {
163 nbits uint
164 value int
165 fail bool
166 }{
167 {nbits: 1, value: 1},
168 {nbits: 1, value: 0},
169 {nbits: 1, value: 1},
170 {nbits: 5, value: 11},
171 {nbits: 32, value: 0x12345678},
172 {nbits: 15, value: 14495},
173 {nbits: 3, value: 6},
174 {nbits: 6, value: 13},
175 {nbits: 1, fail: true},
176 }
177
178 rd := bytes.NewReader([]byte{0xab, 0x12, 0x34, 0x56, 0x78, 0x71, 0x3f, 0x8d})
179 br := newBitReader(rd)
180 for i, v := range vectors {
181 val := br.ReadBits(v.nbits)
182 if fail := bool(br.err != nil); fail != v.fail {
183 if fail {
184 t.Errorf("test %d, unexpected failure: ReadBits(%d) = %v", i, v.nbits, br.err)
185 } else {
186 t.Errorf("test %d, unexpected success: ReadBits(%d) = nil", i, v.nbits)
187 }
188 }
189 if !v.fail && val != v.value {
190 t.Errorf("test %d, mismatching value: ReadBits(%d) = %d, want %d", i, v.nbits, val, v.value)
191 }
192 }
193 }
194
195 func TestMTF(t *testing.T) {
196 var vectors = []struct {
197 idx int
198 sym uint8
199 }{
200 {idx: 1, sym: 1},
201 {idx: 0, sym: 1},
202 {idx: 1, sym: 0},
203 {idx: 4, sym: 4},
204 {idx: 1, sym: 0},
205 }
206
207 mtf := newMTFDecoderWithRange(5)
208 for i, v := range vectors {
209 sym := mtf.Decode(v.idx)
210 t.Log(mtf)
211 if sym != v.sym {
212 t.Errorf("test %d, symbol mismatch: Decode(%d) = %d, want %d", i, v.idx, sym, v.sym)
213 }
214 }
215 }
216
217 func TestZeroRead(t *testing.T) {
218 b := mustDecodeHex("425a6839314159265359b5aa5098000000600040000004200021008283177245385090b5aa5098")
219 r := NewReader(bytes.NewReader(b))
220 if n, err := r.Read(nil); n != 0 || err != nil {
221 t.Errorf("Read(nil) = (%d, %v), want (0, nil)", n, err)
222 }
223 }
224
225 var (
226 digits = mustLoadFile("testdata/e.txt.bz2")
227 newton = mustLoadFile("testdata/Isaac.Newton-Opticks.txt.bz2")
228 random = mustLoadFile("testdata/random.data.bz2")
229 )
230
231 func benchmarkDecode(b *testing.B, compressed []byte) {
232
233 uncompressedSize, err := io.Copy(io.Discard, NewReader(bytes.NewReader(compressed)))
234 if err != nil {
235 b.Fatal(err)
236 }
237
238 b.SetBytes(uncompressedSize)
239 b.ReportAllocs()
240 b.ResetTimer()
241
242 for i := 0; i < b.N; i++ {
243 r := bytes.NewReader(compressed)
244 io.Copy(io.Discard, NewReader(r))
245 }
246 }
247
248 func BenchmarkDecodeDigits(b *testing.B) { benchmarkDecode(b, digits) }
249 func BenchmarkDecodeNewton(b *testing.B) { benchmarkDecode(b, newton) }
250 func BenchmarkDecodeRand(b *testing.B) { benchmarkDecode(b, random) }
251
View as plain text