1
2
3
4
5 package gzip
6
7 import (
8 "bufio"
9 "bytes"
10 "io"
11 "reflect"
12 "testing"
13 "time"
14 )
15
16
17 func TestEmpty(t *testing.T) {
18 buf := new(bytes.Buffer)
19
20 if err := NewWriter(buf).Close(); err != nil {
21 t.Fatalf("Writer.Close: %v", err)
22 }
23
24 r, err := NewReader(buf)
25 if err != nil {
26 t.Fatalf("NewReader: %v", err)
27 }
28 if want := (Header{OS: 255}); !reflect.DeepEqual(r.Header, want) {
29 t.Errorf("Header mismatch:\ngot %#v\nwant %#v", r.Header, want)
30 }
31 b, err := io.ReadAll(r)
32 if err != nil {
33 t.Fatalf("ReadAll: %v", err)
34 }
35 if len(b) != 0 {
36 t.Fatalf("got %d bytes, want 0", len(b))
37 }
38 if err := r.Close(); err != nil {
39 t.Fatalf("Reader.Close: %v", err)
40 }
41 }
42
43
44
45 func TestRoundTrip(t *testing.T) {
46 buf := new(bytes.Buffer)
47
48 w := NewWriter(buf)
49 w.Comment = "comment"
50 w.Extra = []byte("extra")
51 w.ModTime = time.Unix(1e8, 0)
52 w.Name = "name"
53 if _, err := w.Write([]byte("payload")); err != nil {
54 t.Fatalf("Write: %v", err)
55 }
56 if err := w.Close(); err != nil {
57 t.Fatalf("Writer.Close: %v", err)
58 }
59
60 r, err := NewReader(buf)
61 if err != nil {
62 t.Fatalf("NewReader: %v", err)
63 }
64 b, err := io.ReadAll(r)
65 if err != nil {
66 t.Fatalf("ReadAll: %v", err)
67 }
68 if string(b) != "payload" {
69 t.Fatalf("payload is %q, want %q", string(b), "payload")
70 }
71 if r.Comment != "comment" {
72 t.Fatalf("comment is %q, want %q", r.Comment, "comment")
73 }
74 if string(r.Extra) != "extra" {
75 t.Fatalf("extra is %q, want %q", r.Extra, "extra")
76 }
77 if r.ModTime.Unix() != 1e8 {
78 t.Fatalf("mtime is %d, want %d", r.ModTime.Unix(), uint32(1e8))
79 }
80 if r.Name != "name" {
81 t.Fatalf("name is %q, want %q", r.Name, "name")
82 }
83 if err := r.Close(); err != nil {
84 t.Fatalf("Reader.Close: %v", err)
85 }
86 }
87
88
89 func TestLatin1(t *testing.T) {
90 latin1 := []byte{0xc4, 'u', 0xdf, 'e', 'r', 'u', 'n', 'g', 0}
91 utf8 := "Äußerung"
92 z := Reader{r: bufio.NewReader(bytes.NewReader(latin1))}
93 s, err := z.readString()
94 if err != nil {
95 t.Fatalf("readString: %v", err)
96 }
97 if s != utf8 {
98 t.Fatalf("read latin-1: got %q, want %q", s, utf8)
99 }
100
101 buf := bytes.NewBuffer(make([]byte, 0, len(latin1)))
102 c := Writer{w: buf}
103 if err = c.writeString(utf8); err != nil {
104 t.Fatalf("writeString: %v", err)
105 }
106 s = buf.String()
107 if s != string(latin1) {
108 t.Fatalf("write utf-8: got %q, want %q", s, string(latin1))
109 }
110 }
111
112
113
114 func TestLatin1RoundTrip(t *testing.T) {
115 testCases := []struct {
116 name string
117 ok bool
118 }{
119 {"", true},
120 {"ASCII is OK", true},
121 {"unless it contains a NUL\x00", false},
122 {"no matter where \x00 occurs", false},
123 {"\x00\x00\x00", false},
124 {"Látin-1 also passes (U+00E1)", true},
125 {"but LĀtin Extended-A (U+0100) does not", false},
126 {"neither does 日本語", false},
127 {"invalid UTF-8 also \xffails", false},
128 {"\x00 as does Látin-1 with NUL", false},
129 }
130 for _, tc := range testCases {
131 buf := new(bytes.Buffer)
132
133 w := NewWriter(buf)
134 w.Name = tc.name
135 err := w.Close()
136 if (err == nil) != tc.ok {
137 t.Errorf("Writer.Close: name = %q, err = %v", tc.name, err)
138 continue
139 }
140 if !tc.ok {
141 continue
142 }
143
144 r, err := NewReader(buf)
145 if err != nil {
146 t.Errorf("NewReader: %v", err)
147 continue
148 }
149 _, err = io.ReadAll(r)
150 if err != nil {
151 t.Errorf("ReadAll: %v", err)
152 continue
153 }
154 if r.Name != tc.name {
155 t.Errorf("name is %q, want %q", r.Name, tc.name)
156 continue
157 }
158 if err := r.Close(); err != nil {
159 t.Errorf("Reader.Close: %v", err)
160 continue
161 }
162 }
163 }
164
165 func TestWriterFlush(t *testing.T) {
166 buf := new(bytes.Buffer)
167
168 w := NewWriter(buf)
169 w.Comment = "comment"
170 w.Extra = []byte("extra")
171 w.ModTime = time.Unix(1e8, 0)
172 w.Name = "name"
173
174 n0 := buf.Len()
175 if n0 != 0 {
176 t.Fatalf("buffer size = %d before writes; want 0", n0)
177 }
178
179 if err := w.Flush(); err != nil {
180 t.Fatal(err)
181 }
182
183 n1 := buf.Len()
184 if n1 == 0 {
185 t.Fatal("no data after first flush")
186 }
187
188 w.Write([]byte("x"))
189
190 n2 := buf.Len()
191 if n1 != n2 {
192 t.Fatalf("after writing a single byte, size changed from %d to %d; want no change", n1, n2)
193 }
194
195 if err := w.Flush(); err != nil {
196 t.Fatal(err)
197 }
198
199 n3 := buf.Len()
200 if n2 == n3 {
201 t.Fatal("Flush didn't flush any data")
202 }
203 }
204
205
206 func TestConcat(t *testing.T) {
207 var buf bytes.Buffer
208 w := NewWriter(&buf)
209 w.Write([]byte("hello "))
210 w.Close()
211 w = NewWriter(&buf)
212 w.Write([]byte("world\n"))
213 w.Close()
214
215 r, err := NewReader(&buf)
216 if err != nil {
217 t.Fatal(err)
218 }
219 data, err := io.ReadAll(r)
220 if string(data) != "hello world\n" || err != nil {
221 t.Fatalf("ReadAll = %q, %v, want %q, nil", data, err, "hello world")
222 }
223 }
224
225 func TestWriterReset(t *testing.T) {
226 buf := new(bytes.Buffer)
227 buf2 := new(bytes.Buffer)
228 z := NewWriter(buf)
229 msg := []byte("hello world")
230 z.Write(msg)
231 z.Close()
232 z.Reset(buf2)
233 z.Write(msg)
234 z.Close()
235 if buf.String() != buf2.String() {
236 t.Errorf("buf2 %q != original buf of %q", buf2.String(), buf.String())
237 }
238 }
239
240 type limitedWriter struct {
241 N int
242 }
243
244 func (l *limitedWriter) Write(p []byte) (n int, err error) {
245 if n := l.N; n < len(p) {
246 l.N = 0
247 return n, io.ErrShortWrite
248 }
249 l.N -= len(p)
250 return len(p), nil
251 }
252
253
254 func TestLimitedWrite(t *testing.T) {
255 msg := []byte("a")
256
257 for lim := 2; lim < 20; lim++ {
258 z := NewWriter(&limitedWriter{lim})
259 if n, _ := z.Write(msg); n > len(msg) {
260 t.Errorf("Write() = %d, want %d or less", n, len(msg))
261 }
262
263 z.Reset(&limitedWriter{lim})
264 z.Header = Header{
265 Comment: "comment",
266 Extra: []byte("extra"),
267 ModTime: time.Now(),
268 Name: "name",
269 OS: 1,
270 }
271 if n, _ := z.Write(msg); n > len(msg) {
272 t.Errorf("Write() = %d, want %d or less", n, len(msg))
273 }
274 }
275 }
276
View as plain text