1 package lz4_test
2
3 import (
4 "archive/tar"
5 "bytes"
6 "fmt"
7 "io"
8 "io/ioutil"
9 "os"
10 "reflect"
11 "strings"
12 "testing"
13
14 "github.com/pierrec/lz4/v4"
15 "github.com/pierrec/lz4/v4/internal/lz4block"
16 )
17
18 func TestWriter(t *testing.T) {
19 goldenFiles := []string{
20 "testdata/empty.txt",
21 "testdata/e.txt",
22 "testdata/gettysburg.txt",
23 "testdata/Mark.Twain-Tom.Sawyer.txt",
24 "testdata/Mark.Twain-Tom.Sawyer_long.txt",
25 "testdata/pg1661.txt",
26 "testdata/pi.txt",
27 "testdata/random.data",
28 "testdata/repeat.txt",
29 "testdata/issue102.data",
30 }
31
32 for _, fname := range goldenFiles {
33 for _, option := range []lz4.Option{
34 lz4.ConcurrencyOption(1),
35 lz4.BlockChecksumOption(true),
36 lz4.SizeOption(123),
37 lz4.ConcurrencyOption(4),
38 } {
39 label := fmt.Sprintf("%s/%s", fname, option)
40 t.Run(label, func(t *testing.T) {
41 fname := fname
42 option := option
43 t.Parallel()
44
45 raw, err := ioutil.ReadFile(fname)
46 if err != nil {
47 t.Fatal(err)
48 }
49 r := bytes.NewReader(raw)
50
51
52 zout := new(bytes.Buffer)
53 zw := lz4.NewWriter(zout)
54 if err := zw.Apply(option, lz4.CompressionLevelOption(lz4.Level1)); err != nil {
55 t.Fatal(err)
56 }
57 _, err = io.Copy(zw, r)
58 if err != nil {
59 t.Fatal(err)
60 }
61 err = zw.Close()
62 if err != nil {
63 t.Fatal(err)
64 }
65
66
67 out := new(bytes.Buffer)
68 zr := lz4.NewReader(zout)
69 n, err := io.Copy(out, zr)
70 if err != nil {
71 t.Fatal(err)
72 }
73
74
75 if got, want := int(n), len(raw); got != want {
76 t.Errorf("invalid sizes: got %d; want %d", got, want)
77 }
78
79 if got, want := out.Bytes(), raw; !bytes.Equal(got, want) {
80 t.Fatal("uncompressed data does not match original")
81 }
82
83 if strings.Contains(option.String(), "SizeOption") {
84 if got, want := zr.Size(), 123; got != want {
85 t.Errorf("invalid sizes: got %d; want %d", got, want)
86 }
87 }
88 })
89 }
90 }
91 }
92
93 func TestWriter_Reset(t *testing.T) {
94 data := pg1661
95 buf := new(bytes.Buffer)
96 src := bytes.NewReader(data)
97 zw := lz4.NewWriter(buf)
98
99
100 _, _ = io.CopyN(zw, src, int64(len(data))/2)
101
102 buf.Reset()
103 src.Reset(data)
104 zw.Reset(buf)
105 zw.Reset(buf)
106
107 if _, err := io.Copy(zw, src); err != nil {
108 t.Fatal(err)
109 }
110 if err := zw.Close(); err != nil {
111 t.Fatal(err)
112 }
113
114 out := new(bytes.Buffer)
115 if _, err := io.Copy(out, lz4.NewReader(buf)); err != nil {
116 t.Fatal(err)
117 }
118 if !reflect.DeepEqual(out.Bytes(), data) {
119 t.Fatal("result does not match original")
120 }
121 }
122
123 func TestIssue41(t *testing.T) {
124 r, w := io.Pipe()
125 zw := lz4.NewWriter(w)
126 zr := lz4.NewReader(r)
127
128 data := "x"
129 go func() {
130 _, _ = fmt.Fprint(zw, data)
131 _ = zw.Close()
132 _ = w.Close()
133 }()
134 var buf bytes.Buffer
135 _, _ = buf.ReadFrom(zr)
136 if got, want := buf.String(), data; got != want {
137 t.Fatal("uncompressed data does not match original")
138 }
139 }
140
141 func TestIssue43(t *testing.T) {
142 r, w := io.Pipe()
143 go func() {
144 defer w.Close()
145
146 f, err := os.Open("testdata/issue43.data")
147 if err != nil {
148 panic(err)
149 }
150 defer f.Close()
151
152 zw := lz4.NewWriter(w)
153 defer zw.Close()
154
155 _, err = io.Copy(zw, f)
156 if err != nil {
157 panic(err)
158 }
159 }()
160 _, err := io.Copy(ioutil.Discard, lz4.NewReader(r))
161 if err != nil {
162 t.Fatal(err)
163 }
164 }
165
166 func TestIssue51(t *testing.T) {
167 data, err := ioutil.ReadFile("testdata/issue51.data")
168 if err != nil {
169 t.Fatal(err)
170 }
171
172 zbuf := make([]byte, 8192)
173
174 n, err := lz4block.CompressBlock(data, zbuf)
175 if err != nil {
176 t.Fatal(err)
177 }
178 zbuf = zbuf[:n]
179
180 buf := make([]byte, 8192)
181 n, err = lz4block.UncompressBlock(zbuf, buf, nil)
182 if err != nil {
183 t.Fatal(err)
184 }
185 buf = buf[:n]
186 if !bytes.Equal(data, buf) {
187 t.Fatal("processed data does not match input")
188 }
189 }
190
191 func TestIssue167(t *testing.T) {
192 src := []byte("\xe300000000000000\t\x00\x00")
193 dst := make([]byte, 18)
194 _, err := lz4.UncompressBlock(src, dst)
195 if err == nil {
196 t.Fatal("expected buffer too short error")
197 }
198 }
199
200 func TestIssue71(t *testing.T) {
201 for _, tc := range []string{
202 "abc",
203 "abcdefghijklmnopq",
204 } {
205 t.Run(tc, func(t *testing.T) {
206 src := []byte(tc)
207 bound := lz4block.CompressBlockBound(len(tc))
208
209
210 zSmall := make([]byte, bound-1)
211 n, err := lz4block.CompressBlock(src, zSmall)
212 if err != nil {
213 t.Fatal(err)
214 }
215 if n != 0 {
216 t.Fatal("should be incompressible")
217 }
218
219
220 zLarge := make([]byte, bound)
221 n, err = lz4block.CompressBlock(src, zLarge)
222 if err != nil {
223 t.Fatal(err)
224 }
225 if n == 0 {
226 t.Fatal("should be compressible")
227 }
228 })
229 }
230 }
231
232 func TestWriterFlush(t *testing.T) {
233 out := new(bytes.Buffer)
234 zw := lz4.NewWriter(out)
235 if err := zw.Apply(); err != nil {
236 t.Fatal(err)
237 }
238 data := strings.Repeat("0123456789", 100)
239 if _, err := zw.Write([]byte(data)); err != nil {
240 t.Fatal(err)
241 }
242
243 if got, want := out.Len(), 7; got != want {
244 t.Fatalf("got %d, want %d", got, want)
245 }
246 if err := zw.Flush(); err != nil {
247 t.Fatal(err)
248 }
249
250 if got, want := out.Len(), 7; got == want {
251 t.Fatalf("got %d, want %d", got, want)
252 }
253 }
254
255 func TestWriterLegacy(t *testing.T) {
256 goldenFiles := []string{
257 "testdata/vmlinux_LZ4_19377",
258 "testdata/bzImage_lz4_isolated",
259 }
260
261 for _, fname := range goldenFiles {
262 t.Run(fname, func(t *testing.T) {
263 fname := fname
264 t.Parallel()
265
266 src, err := ioutil.ReadFile(fname)
267 if err != nil {
268 t.Fatal(err)
269 }
270
271 out := new(bytes.Buffer)
272 zw := lz4.NewWriter(out)
273 if err := zw.Apply(lz4.LegacyOption(true), lz4.CompressionLevelOption(lz4.Fast)); err != nil {
274 t.Fatal(err)
275 }
276 if _, err := io.Copy(zw, bytes.NewReader(src)); err != nil {
277 t.Fatal(err)
278 }
279 if err := zw.Close(); err != nil {
280 t.Fatal(err)
281 }
282
283 out2 := new(bytes.Buffer)
284 zr := lz4.NewReader(out)
285 if _, err := io.Copy(out2, zr); err != nil {
286 t.Fatal(err)
287 }
288 if !bytes.Equal(out2.Bytes(), src) {
289 t.Fatal("uncompressed compressed output different from source")
290 }
291 })
292 }
293 }
294
295 func TestWriterConcurrency(t *testing.T) {
296 const someGiantFile = "testdata/vmlinux_LZ4_19377"
297
298 out := new(bytes.Buffer)
299 zw := lz4.NewWriter(out)
300 if err := zw.Apply(
301 lz4.ConcurrencyOption(4),
302 lz4.BlockSizeOption(lz4.Block4Mb),
303 lz4.ChecksumOption(true)); err != nil {
304 t.Fatal(err)
305 }
306
307
308 tw := tar.NewWriter(zw)
309 stat, err := os.Stat(someGiantFile)
310 if err != nil {
311 t.Fatal(err)
312 }
313 header, err := tar.FileInfoHeader(stat, "")
314 if err != nil {
315 t.Fatal(err)
316 }
317 if err := tw.WriteHeader(header); err != nil {
318 t.Fatal(err)
319 }
320 src, err := os.Open(someGiantFile)
321 if err != nil {
322 t.Fatal(err)
323 }
324 copyBuf := make([]byte, 16<<20)
325 if _, err := io.CopyBuffer(tw, src, copyBuf); err != nil {
326 t.Fatal(err)
327 }
328 if err := tw.Close(); err != nil {
329 t.Fatal(err)
330 }
331 if err := zw.Close(); err != nil {
332 t.Fatal(err)
333 }
334
335 zr := lz4.NewReader(out)
336 if _, err := io.Copy(ioutil.Discard, zr); err != nil {
337 t.Fatal(err)
338 }
339 }
340
View as plain text