-
Notifications
You must be signed in to change notification settings - Fork 1
/
lzw_test.go
146 lines (124 loc) · 3.78 KB
/
lzw_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Derived from compress/lzw in order to implement
// Adobe's PDF lzw compression as defined for the LZWDecode filter.
// See https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf
// and https://github.com/golang/go/issues/25409.
//
// It is also compatible with the TIFF file format.
//
// 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 lzw_test
import (
"bytes"
"encoding/hex"
"io/ioutil"
"io"
"os"
"testing"
"github.com/hhrutter/lzw"
)
func compareToGolden(t *testing.T, b []byte, fileName string) {
t.Helper()
golden, err := os.Open(fileName)
if err != nil {
t.Errorf("%s: %v", fileName, err)
return
}
defer golden.Close()
g, err := ioutil.ReadAll(golden)
if err != nil {
t.Errorf("%s: %v", fileName, err)
return
}
if len(b) != len(g) {
t.Errorf("%s: length mismatch after compression %d != %d", fileName, len(b), len(g))
t.Logf("encodedBytes:\n%s\n", hex.Dump(b))
t.Logf("goldenBytes:\n%s\n", hex.Dump(g))
return
}
for i := 0; i < len(b); i++ {
if b[i] != g[i] {
t.Errorf("%s: mismatch at %d(0x%02x), 0x%02x != 0x%02x\n", fileName, i, i, b[i], g[i])
t.Logf("encodedBytes:\n%s\n", hex.Dump(b))
t.Logf("goldenBytes:\n%s\n", hex.Dump(g))
return
}
}
}
// testFile tests that encoding and subsequent decoding of a given file
// yields byte streams that correspond to a golden file content at each stage.
func testFile(t *testing.T, filePrefix string, earlyChange bool) {
t.Helper()
t.Logf("testFile: %s\n", filePrefix)
rawFileName := filePrefix + "Raw.lzw" // The golden file for decoded lzw.
encFileName := filePrefix + "Enc.lzw" // The golden file for encoded lzw.
// Read in some decompressed bytes.
raw, err := os.Open(rawFileName)
if err != nil {
t.Errorf("%s: %v", rawFileName, err)
return
}
defer raw.Close()
// Compress.
var b bytes.Buffer
wc := lzw.NewWriter(&b, earlyChange)
_, err = io.Copy(wc, raw)
if err != nil {
t.Errorf("%s: %v", rawFileName, err)
return
}
wc.Close()
// The available test data implies some PDF Writers
// do not write the final bits after eof during Close().
// This is why we do not compare these compressed results to known compressed bytes.
// See extra step below.
//
// Compare compressed bytes with the corresponding golden files content.
// compareToGolden(t, b.Bytes(), encFileName)
// Decompress.
rc := lzw.NewReader(&b, earlyChange)
defer rc.Close()
var dec bytes.Buffer
written, err := io.Copy(&dec, rc)
if err != nil {
t.Errorf("%s: %v", encFileName, err)
return
}
t.Logf("%s: decompressed bytes:%d(%d)\n", encFileName, written, dec.Len())
// Compare decompressed bytes with the corresponding golden files content.
compareToGolden(t, dec.Bytes(), rawFileName)
// The available test data implies some PDF Writers
// do not write the final bits after eof during Close().
// Here we take an extra step and decode known compressed bytes
// and compare the result to known uncompressed bytes.
// Read in encoded
enc, err := os.Open(encFileName)
if err != nil {
t.Errorf("%s: %v", encFileName, err)
return
}
defer enc.Close()
// Decompress.
rc = lzw.NewReader(&b, earlyChange)
written, err = io.Copy(&dec, rc)
if err != nil {
t.Errorf("%s: %v", encFileName, err)
return
}
t.Logf("%s: decompressed bytes:%d(%d)\n", encFileName, written, dec.Len())
// Compare raw/decoded bytes with the corresponding golden files content.
compareToGolden(t, dec.Bytes(), rawFileName)
}
func TestLZW(t *testing.T) {
for _, tt := range []struct {
fileNamePrefix string
earlyChange bool
}{
{"testdata/earlyChange0", false},
{"testdata/earlyChange1", true},
{"testdata/earlyChangeDefault", true},
} {
testFile(t, tt.fileNamePrefix, tt.earlyChange)
}
}