1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package flate 6 7 import ( 8 "bytes" 9 "fmt" 10 "io" 11 "io/ioutil" 12 "reflect" 13 "sync" 14 "testing" 15 ) 16 17 type deflateTest struct { 18 in []byte 19 level int 20 out []byte 21 } 22 23 type deflateInflateTest struct { 24 in []byte 25 } 26 27 type reverseBitsTest struct { 28 in uint16 29 bitCount uint8 30 out uint16 31 } 32 33 var deflateTests = []*deflateTest{ 34 {[]byte{}, 0, []byte{1, 0, 0, 255, 255}}, 35 {[]byte{0x11}, -1, []byte{18, 4, 4, 0, 0, 255, 255}}, 36 {[]byte{0x11}, DefaultCompression, []byte{18, 4, 4, 0, 0, 255, 255}}, 37 {[]byte{0x11}, 4, []byte{18, 4, 4, 0, 0, 255, 255}}, 38 39 {[]byte{0x11}, 0, []byte{0, 1, 0, 254, 255, 17, 1, 0, 0, 255, 255}}, 40 {[]byte{0x11, 0x12}, 0, []byte{0, 2, 0, 253, 255, 17, 18, 1, 0, 0, 255, 255}}, 41 {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 0, 42 []byte{0, 8, 0, 247, 255, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0, 0, 255, 255}, 43 }, 44 {[]byte{}, 1, []byte{1, 0, 0, 255, 255}}, 45 {[]byte{0x11}, 1, []byte{18, 4, 4, 0, 0, 255, 255}}, 46 {[]byte{0x11, 0x12}, 1, []byte{18, 20, 2, 4, 0, 0, 255, 255}}, 47 {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 1, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}}, 48 {[]byte{}, 9, []byte{1, 0, 0, 255, 255}}, 49 {[]byte{0x11}, 9, []byte{18, 4, 4, 0, 0, 255, 255}}, 50 {[]byte{0x11, 0x12}, 9, []byte{18, 20, 2, 4, 0, 0, 255, 255}}, 51 {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 9, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}}, 52 } 53 54 var deflateInflateTests = []*deflateInflateTest{ 55 {[]byte{}}, 56 {[]byte{0x11}}, 57 {[]byte{0x11, 0x12}}, 58 {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}}, 59 {[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}}, 60 {largeDataChunk()}, 61 } 62 63 var reverseBitsTests = []*reverseBitsTest{ 64 {1, 1, 1}, 65 {1, 2, 2}, 66 {1, 3, 4}, 67 {1, 4, 8}, 68 {1, 5, 16}, 69 {17, 5, 17}, 70 {257, 9, 257}, 71 {29, 5, 23}, 72 } 73 74 func largeDataChunk() []byte { 75 result := make([]byte, 100000) 76 for i := range result { 77 result[i] = byte(i * i & 0xFF) 78 } 79 return result 80 } 81 82 func TestDeflate(t *testing.T) { 83 for _, h := range deflateTests { 84 var buf bytes.Buffer 85 w, err := NewWriter(&buf, h.level) 86 if err != nil { 87 t.Errorf("NewWriter: %v", err) 88 continue 89 } 90 w.Write(h.in) 91 w.Close() 92 if !bytes.Equal(buf.Bytes(), h.out) { 93 t.Errorf("Deflate(%d, %x) = %x, want %x", h.level, h.in, buf.Bytes(), h.out) 94 } 95 } 96 } 97 98 // A sparseReader returns a stream consisting of 0s followed by 1<<16 1s. 99 // This tests missing hash references in a very large input. 100 type sparseReader struct { 101 l int64 102 cur int64 103 } 104 105 func (r *sparseReader) Read(b []byte) (n int, err error) { 106 if r.cur >= r.l { 107 return 0, io.EOF 108 } 109 n = len(b) 110 cur := r.cur + int64(n) 111 if cur > r.l { 112 n -= int(cur - r.l) 113 cur = r.l 114 } 115 for i := range b[0:n] { 116 if r.cur+int64(i) >= r.l-1<<16 { 117 b[i] = 1 118 } else { 119 b[i] = 0 120 } 121 } 122 r.cur = cur 123 return 124 } 125 126 func TestVeryLongSparseChunk(t *testing.T) { 127 if testing.Short() { 128 t.Skip("skipping sparse chunk during short test") 129 } 130 w, err := NewWriter(ioutil.Discard, 1) 131 if err != nil { 132 t.Errorf("NewWriter: %v", err) 133 return 134 } 135 if _, err = io.Copy(w, &sparseReader{l: 23E8}); err != nil { 136 t.Errorf("Compress failed: %v", err) 137 return 138 } 139 } 140 141 type syncBuffer struct { 142 buf bytes.Buffer 143 mu sync.RWMutex 144 closed bool 145 ready chan bool 146 } 147 148 func newSyncBuffer() *syncBuffer { 149 return &syncBuffer{ready: make(chan bool, 1)} 150 } 151 152 func (b *syncBuffer) Read(p []byte) (n int, err error) { 153 for { 154 b.mu.RLock() 155 n, err = b.buf.Read(p) 156 b.mu.RUnlock() 157 if n > 0 || b.closed { 158 return 159 } 160 <-b.ready 161 } 162 } 163 164 func (b *syncBuffer) signal() { 165 select { 166 case b.ready <- true: 167 default: 168 } 169 } 170 171 func (b *syncBuffer) Write(p []byte) (n int, err error) { 172 n, err = b.buf.Write(p) 173 b.signal() 174 return 175 } 176 177 func (b *syncBuffer) WriteMode() { 178 b.mu.Lock() 179 } 180 181 func (b *syncBuffer) ReadMode() { 182 b.mu.Unlock() 183 b.signal() 184 } 185 186 func (b *syncBuffer) Close() error { 187 b.closed = true 188 b.signal() 189 return nil 190 } 191 192 func testSync(t *testing.T, level int, input []byte, name string) { 193 if len(input) == 0 { 194 return 195 } 196 197 t.Logf("--testSync %d, %d, %s", level, len(input), name) 198 buf := newSyncBuffer() 199 buf1 := new(bytes.Buffer) 200 buf.WriteMode() 201 w, err := NewWriter(io.MultiWriter(buf, buf1), level) 202 if err != nil { 203 t.Errorf("NewWriter: %v", err) 204 return 205 } 206 r := NewReader(buf) 207 208 // Write half the input and read back. 209 for i := 0; i < 2; i++ { 210 var lo, hi int 211 if i == 0 { 212 lo, hi = 0, (len(input)+1)/2 213 } else { 214 lo, hi = (len(input)+1)/2, len(input) 215 } 216 t.Logf("#%d: write %d-%d", i, lo, hi) 217 if _, err := w.Write(input[lo:hi]); err != nil { 218 t.Errorf("testSync: write: %v", err) 219 return 220 } 221 if i == 0 { 222 if err := w.Flush(); err != nil { 223 t.Errorf("testSync: flush: %v", err) 224 return 225 } 226 } else { 227 if err := w.Close(); err != nil { 228 t.Errorf("testSync: close: %v", err) 229 } 230 } 231 buf.ReadMode() 232 out := make([]byte, hi-lo+1) 233 m, err := io.ReadAtLeast(r, out, hi-lo) 234 t.Logf("#%d: read %d", i, m) 235 if m != hi-lo || err != nil { 236 t.Errorf("testSync/%d (%d, %d, %s): read %d: %d, %v (%d left)", i, level, len(input), name, hi-lo, m, err, buf.buf.Len()) 237 return 238 } 239 if !bytes.Equal(input[lo:hi], out[:hi-lo]) { 240 t.Errorf("testSync/%d: read wrong bytes: %x vs %x", i, input[lo:hi], out[:hi-lo]) 241 return 242 } 243 // This test originally checked that after reading 244 // the first half of the input, there was nothing left 245 // in the read buffer (buf.buf.Len() != 0) but that is 246 // not necessarily the case: the write Flush may emit 247 // some extra framing bits that are not necessary 248 // to process to obtain the first half of the uncompressed 249 // data. The test ran correctly most of the time, because 250 // the background goroutine had usually read even 251 // those extra bits by now, but it's not a useful thing to 252 // check. 253 buf.WriteMode() 254 } 255 buf.ReadMode() 256 out := make([]byte, 10) 257 if n, err := r.Read(out); n > 0 || err != io.EOF { 258 t.Errorf("testSync (%d, %d, %s): final Read: %d, %v (hex: %x)", level, len(input), name, n, err, out[0:n]) 259 } 260 if buf.buf.Len() != 0 { 261 t.Errorf("testSync (%d, %d, %s): extra data at end", level, len(input), name) 262 } 263 r.Close() 264 265 // stream should work for ordinary reader too 266 r = NewReader(buf1) 267 out, err = ioutil.ReadAll(r) 268 if err != nil { 269 t.Errorf("testSync: read: %s", err) 270 return 271 } 272 r.Close() 273 if !bytes.Equal(input, out) { 274 t.Errorf("testSync: decompress(compress(data)) != data: level=%d input=%s", level, name) 275 } 276 } 277 278 func testToFromWithLevelAndLimit(t *testing.T, level int, input []byte, name string, limit int) { 279 var buffer bytes.Buffer 280 w, err := NewWriter(&buffer, level) 281 if err != nil { 282 t.Errorf("NewWriter: %v", err) 283 return 284 } 285 w.Write(input) 286 w.Close() 287 if limit > 0 && buffer.Len() > limit { 288 t.Errorf("level: %d, len(compress(data)) = %d > limit = %d", level, buffer.Len(), limit) 289 return 290 } 291 r := NewReader(&buffer) 292 out, err := ioutil.ReadAll(r) 293 if err != nil { 294 t.Errorf("read: %s", err) 295 return 296 } 297 r.Close() 298 if !bytes.Equal(input, out) { 299 t.Errorf("decompress(compress(data)) != data: level=%d input=%s", level, name) 300 return 301 } 302 testSync(t, level, input, name) 303 } 304 305 func testToFromWithLimit(t *testing.T, input []byte, name string, limit [10]int) { 306 for i := 0; i < 10; i++ { 307 testToFromWithLevelAndLimit(t, i, input, name, limit[i]) 308 } 309 } 310 311 func TestDeflateInflate(t *testing.T) { 312 for i, h := range deflateInflateTests { 313 testToFromWithLimit(t, h.in, fmt.Sprintf("#%d", i), [10]int{}) 314 } 315 } 316 317 func TestReverseBits(t *testing.T) { 318 for _, h := range reverseBitsTests { 319 if v := reverseBits(h.in, h.bitCount); v != h.out { 320 t.Errorf("reverseBits(%v,%v) = %v, want %v", 321 h.in, h.bitCount, v, h.out) 322 } 323 } 324 } 325 326 type deflateInflateStringTest struct { 327 filename string 328 label string 329 limit [10]int 330 } 331 332 var deflateInflateStringTests = []deflateInflateStringTest{ 333 { 334 "../testdata/e.txt", 335 "2.718281828...", 336 [...]int{100018, 50650, 50960, 51150, 50930, 50790, 50790, 50790, 50790, 50790}, 337 }, 338 { 339 "../testdata/Mark.Twain-Tom.Sawyer.txt", 340 "Mark.Twain-Tom.Sawyer", 341 [...]int{407330, 187598, 180361, 172974, 169160, 163476, 160936, 160506, 160295, 160295}, 342 }, 343 } 344 345 func TestDeflateInflateString(t *testing.T) { 346 for _, test := range deflateInflateStringTests { 347 gold, err := ioutil.ReadFile(test.filename) 348 if err != nil { 349 t.Error(err) 350 } 351 testToFromWithLimit(t, gold, test.label, test.limit) 352 if testing.Short() { 353 break 354 } 355 } 356 } 357 358 func TestReaderDict(t *testing.T) { 359 const ( 360 dict = "hello world" 361 text = "hello again world" 362 ) 363 var b bytes.Buffer 364 w, err := NewWriter(&b, 5) 365 if err != nil { 366 t.Fatalf("NewWriter: %v", err) 367 } 368 w.Write([]byte(dict)) 369 w.Flush() 370 b.Reset() 371 w.Write([]byte(text)) 372 w.Close() 373 374 r := NewReaderDict(&b, []byte(dict)) 375 data, err := ioutil.ReadAll(r) 376 if err != nil { 377 t.Fatal(err) 378 } 379 if string(data) != "hello again world" { 380 t.Fatalf("read returned %q want %q", string(data), text) 381 } 382 } 383 384 func TestWriterDict(t *testing.T) { 385 const ( 386 dict = "hello world" 387 text = "hello again world" 388 ) 389 var b bytes.Buffer 390 w, err := NewWriter(&b, 5) 391 if err != nil { 392 t.Fatalf("NewWriter: %v", err) 393 } 394 w.Write([]byte(dict)) 395 w.Flush() 396 b.Reset() 397 w.Write([]byte(text)) 398 w.Close() 399 400 var b1 bytes.Buffer 401 w, _ = NewWriterDict(&b1, 5, []byte(dict)) 402 w.Write([]byte(text)) 403 w.Close() 404 405 if !bytes.Equal(b1.Bytes(), b.Bytes()) { 406 t.Fatalf("writer wrote %q want %q", b1.Bytes(), b.Bytes()) 407 } 408 } 409 410 // See https://golang.org/issue/2508 411 func TestRegression2508(t *testing.T) { 412 if testing.Short() { 413 t.Logf("test disabled with -short") 414 return 415 } 416 w, err := NewWriter(ioutil.Discard, 1) 417 if err != nil { 418 t.Fatalf("NewWriter: %v", err) 419 } 420 buf := make([]byte, 1024) 421 for i := 0; i < 131072; i++ { 422 if _, err := w.Write(buf); err != nil { 423 t.Fatalf("writer failed: %v", err) 424 } 425 } 426 w.Close() 427 } 428 429 func TestWriterReset(t *testing.T) { 430 for level := 0; level <= 9; level++ { 431 if testing.Short() && level > 1 { 432 break 433 } 434 w, err := NewWriter(ioutil.Discard, level) 435 if err != nil { 436 t.Fatalf("NewWriter: %v", err) 437 } 438 buf := []byte("hello world") 439 for i := 0; i < 1024; i++ { 440 w.Write(buf) 441 } 442 w.Reset(ioutil.Discard) 443 444 wref, err := NewWriter(ioutil.Discard, level) 445 if err != nil { 446 t.Fatalf("NewWriter: %v", err) 447 } 448 449 // DeepEqual doesn't compare functions. 450 w.d.fill, wref.d.fill = nil, nil 451 w.d.step, wref.d.step = nil, nil 452 if !reflect.DeepEqual(w, wref) { 453 t.Errorf("level %d Writer not reset after Reset", level) 454 } 455 } 456 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, NoCompression) }) 457 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, DefaultCompression) }) 458 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, BestCompression) }) 459 dict := []byte("we are the world") 460 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, NoCompression, dict) }) 461 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, DefaultCompression, dict) }) 462 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, BestCompression, dict) }) 463 } 464 465 func testResetOutput(t *testing.T, newWriter func(w io.Writer) (*Writer, error)) { 466 buf := new(bytes.Buffer) 467 w, err := newWriter(buf) 468 if err != nil { 469 t.Fatalf("NewWriter: %v", err) 470 } 471 b := []byte("hello world") 472 for i := 0; i < 1024; i++ { 473 w.Write(b) 474 } 475 w.Close() 476 out1 := buf.String() 477 478 buf2 := new(bytes.Buffer) 479 w.Reset(buf2) 480 for i := 0; i < 1024; i++ { 481 w.Write(b) 482 } 483 w.Close() 484 out2 := buf2.String() 485 486 if out1 != out2 { 487 t.Errorf("got %q, expected %q", out2, out1) 488 } 489 t.Logf("got %d bytes", len(out1)) 490 } 491