github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/src/compress/flate/deflate_test.go (about) 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 "errors" 10 "fmt" 11 "internal/testenv" 12 "io" 13 "io/ioutil" 14 "reflect" 15 "runtime/debug" 16 "sync" 17 "testing" 18 ) 19 20 type deflateTest struct { 21 in []byte 22 level int 23 out []byte 24 } 25 26 type deflateInflateTest struct { 27 in []byte 28 } 29 30 type reverseBitsTest struct { 31 in uint16 32 bitCount uint8 33 out uint16 34 } 35 36 var deflateTests = []*deflateTest{ 37 {[]byte{}, 0, []byte{1, 0, 0, 255, 255}}, 38 {[]byte{0x11}, -1, []byte{18, 4, 4, 0, 0, 255, 255}}, 39 {[]byte{0x11}, DefaultCompression, []byte{18, 4, 4, 0, 0, 255, 255}}, 40 {[]byte{0x11}, 4, []byte{18, 4, 4, 0, 0, 255, 255}}, 41 42 {[]byte{0x11}, 0, []byte{0, 1, 0, 254, 255, 17, 1, 0, 0, 255, 255}}, 43 {[]byte{0x11, 0x12}, 0, []byte{0, 2, 0, 253, 255, 17, 18, 1, 0, 0, 255, 255}}, 44 {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 0, 45 []byte{0, 8, 0, 247, 255, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0, 0, 255, 255}, 46 }, 47 {[]byte{}, 2, []byte{1, 0, 0, 255, 255}}, 48 {[]byte{0x11}, 2, []byte{18, 4, 4, 0, 0, 255, 255}}, 49 {[]byte{0x11, 0x12}, 2, []byte{18, 20, 2, 4, 0, 0, 255, 255}}, 50 {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 2, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}}, 51 {[]byte{}, 9, []byte{1, 0, 0, 255, 255}}, 52 {[]byte{0x11}, 9, []byte{18, 4, 4, 0, 0, 255, 255}}, 53 {[]byte{0x11, 0x12}, 9, []byte{18, 20, 2, 4, 0, 0, 255, 255}}, 54 {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 9, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}}, 55 } 56 57 var deflateInflateTests = []*deflateInflateTest{ 58 {[]byte{}}, 59 {[]byte{0x11}}, 60 {[]byte{0x11, 0x12}}, 61 {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}}, 62 {[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}}, 63 {largeDataChunk()}, 64 } 65 66 var reverseBitsTests = []*reverseBitsTest{ 67 {1, 1, 1}, 68 {1, 2, 2}, 69 {1, 3, 4}, 70 {1, 4, 8}, 71 {1, 5, 16}, 72 {17, 5, 17}, 73 {257, 9, 257}, 74 {29, 5, 23}, 75 } 76 77 func largeDataChunk() []byte { 78 result := make([]byte, 100000) 79 for i := range result { 80 result[i] = byte(i * i & 0xFF) 81 } 82 return result 83 } 84 85 func TestBulkHash4(t *testing.T) { 86 for _, x := range deflateTests { 87 y := x.out 88 if len(y) < minMatchLength { 89 continue 90 } 91 y = append(y, y...) 92 for j := 4; j < len(y); j++ { 93 y := y[:j] 94 dst := make([]uint32, len(y)-minMatchLength+1) 95 for i := range dst { 96 dst[i] = uint32(i + 100) 97 } 98 bulkHash4(y, dst) 99 for i, got := range dst { 100 want := hash4(y[i:]) 101 if got != want && got == uint32(i)+100 { 102 t.Errorf("Len:%d Index:%d, want 0x%08x but not modified", len(y), i, want) 103 } else if got != want { 104 t.Errorf("Len:%d Index:%d, got 0x%08x want:0x%08x", len(y), i, got, want) 105 } 106 } 107 } 108 } 109 } 110 111 func TestDeflate(t *testing.T) { 112 for _, h := range deflateTests { 113 var buf bytes.Buffer 114 w, err := NewWriter(&buf, h.level) 115 if err != nil { 116 t.Errorf("NewWriter: %v", err) 117 continue 118 } 119 w.Write(h.in) 120 w.Close() 121 if !bytes.Equal(buf.Bytes(), h.out) { 122 t.Errorf("Deflate(%d, %x) = \n%#v, want \n%#v", h.level, h.in, buf.Bytes(), h.out) 123 } 124 } 125 } 126 127 // A sparseReader returns a stream consisting of 0s followed by 1<<16 1s. 128 // This tests missing hash references in a very large input. 129 type sparseReader struct { 130 l int64 131 cur int64 132 } 133 134 func (r *sparseReader) Read(b []byte) (n int, err error) { 135 if r.cur >= r.l { 136 return 0, io.EOF 137 } 138 n = len(b) 139 cur := r.cur + int64(n) 140 if cur > r.l { 141 n -= int(cur - r.l) 142 cur = r.l 143 } 144 for i := range b[0:n] { 145 if r.cur+int64(i) >= r.l-1<<16 { 146 b[i] = 1 147 } else { 148 b[i] = 0 149 } 150 } 151 r.cur = cur 152 return 153 } 154 155 func TestVeryLongSparseChunk(t *testing.T) { 156 if testing.Short() { 157 t.Skip("skipping sparse chunk during short test") 158 } 159 w, err := NewWriter(ioutil.Discard, 1) 160 if err != nil { 161 t.Errorf("NewWriter: %v", err) 162 return 163 } 164 if _, err = io.Copy(w, &sparseReader{l: 23E8}); err != nil { 165 t.Errorf("Compress failed: %v", err) 166 return 167 } 168 } 169 170 type syncBuffer struct { 171 buf bytes.Buffer 172 mu sync.RWMutex 173 closed bool 174 ready chan bool 175 } 176 177 func newSyncBuffer() *syncBuffer { 178 return &syncBuffer{ready: make(chan bool, 1)} 179 } 180 181 func (b *syncBuffer) Read(p []byte) (n int, err error) { 182 for { 183 b.mu.RLock() 184 n, err = b.buf.Read(p) 185 b.mu.RUnlock() 186 if n > 0 || b.closed { 187 return 188 } 189 <-b.ready 190 } 191 } 192 193 func (b *syncBuffer) signal() { 194 select { 195 case b.ready <- true: 196 default: 197 } 198 } 199 200 func (b *syncBuffer) Write(p []byte) (n int, err error) { 201 n, err = b.buf.Write(p) 202 b.signal() 203 return 204 } 205 206 func (b *syncBuffer) WriteMode() { 207 b.mu.Lock() 208 } 209 210 func (b *syncBuffer) ReadMode() { 211 b.mu.Unlock() 212 b.signal() 213 } 214 215 func (b *syncBuffer) Close() error { 216 b.closed = true 217 b.signal() 218 return nil 219 } 220 221 func testSync(t *testing.T, level int, input []byte, name string) { 222 if len(input) == 0 { 223 return 224 } 225 226 t.Logf("--testSync %d, %d, %s", level, len(input), name) 227 buf := newSyncBuffer() 228 buf1 := new(bytes.Buffer) 229 buf.WriteMode() 230 w, err := NewWriter(io.MultiWriter(buf, buf1), level) 231 if err != nil { 232 t.Errorf("NewWriter: %v", err) 233 return 234 } 235 r := NewReader(buf) 236 237 // Write half the input and read back. 238 for i := 0; i < 2; i++ { 239 var lo, hi int 240 if i == 0 { 241 lo, hi = 0, (len(input)+1)/2 242 } else { 243 lo, hi = (len(input)+1)/2, len(input) 244 } 245 t.Logf("#%d: write %d-%d", i, lo, hi) 246 if _, err := w.Write(input[lo:hi]); err != nil { 247 t.Errorf("testSync: write: %v", err) 248 return 249 } 250 if i == 0 { 251 if err := w.Flush(); err != nil { 252 t.Errorf("testSync: flush: %v", err) 253 return 254 } 255 } else { 256 if err := w.Close(); err != nil { 257 t.Errorf("testSync: close: %v", err) 258 } 259 } 260 buf.ReadMode() 261 out := make([]byte, hi-lo+1) 262 m, err := io.ReadAtLeast(r, out, hi-lo) 263 t.Logf("#%d: read %d", i, m) 264 if m != hi-lo || err != nil { 265 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()) 266 return 267 } 268 if !bytes.Equal(input[lo:hi], out[:hi-lo]) { 269 t.Errorf("testSync/%d: read wrong bytes: %x vs %x", i, input[lo:hi], out[:hi-lo]) 270 return 271 } 272 // This test originally checked that after reading 273 // the first half of the input, there was nothing left 274 // in the read buffer (buf.buf.Len() != 0) but that is 275 // not necessarily the case: the write Flush may emit 276 // some extra framing bits that are not necessary 277 // to process to obtain the first half of the uncompressed 278 // data. The test ran correctly most of the time, because 279 // the background goroutine had usually read even 280 // those extra bits by now, but it's not a useful thing to 281 // check. 282 buf.WriteMode() 283 } 284 buf.ReadMode() 285 out := make([]byte, 10) 286 if n, err := r.Read(out); n > 0 || err != io.EOF { 287 t.Errorf("testSync (%d, %d, %s): final Read: %d, %v (hex: %x)", level, len(input), name, n, err, out[0:n]) 288 } 289 if buf.buf.Len() != 0 { 290 t.Errorf("testSync (%d, %d, %s): extra data at end", level, len(input), name) 291 } 292 r.Close() 293 294 // stream should work for ordinary reader too 295 r = NewReader(buf1) 296 out, err = ioutil.ReadAll(r) 297 if err != nil { 298 t.Errorf("testSync: read: %s", err) 299 return 300 } 301 r.Close() 302 if !bytes.Equal(input, out) { 303 t.Errorf("testSync: decompress(compress(data)) != data: level=%d input=%s", level, name) 304 } 305 } 306 307 func testToFromWithLevelAndLimit(t *testing.T, level int, input []byte, name string, limit int) { 308 var buffer bytes.Buffer 309 w, err := NewWriter(&buffer, level) 310 if err != nil { 311 t.Errorf("NewWriter: %v", err) 312 return 313 } 314 w.Write(input) 315 w.Close() 316 if limit > 0 && buffer.Len() > limit { 317 t.Errorf("level: %d, len(compress(data)) = %d > limit = %d", level, buffer.Len(), limit) 318 return 319 } 320 if limit > 0 { 321 t.Logf("level: %d, size:%.2f%%, %d b\n", level, float64(buffer.Len()*100)/float64(limit), buffer.Len()) 322 } 323 r := NewReader(&buffer) 324 out, err := ioutil.ReadAll(r) 325 if err != nil { 326 t.Errorf("read: %s", err) 327 return 328 } 329 r.Close() 330 if !bytes.Equal(input, out) { 331 t.Errorf("decompress(compress(data)) != data: level=%d input=%s", level, name) 332 return 333 } 334 testSync(t, level, input, name) 335 } 336 337 func testToFromWithLimit(t *testing.T, input []byte, name string, limit [11]int) { 338 for i := 0; i < 10; i++ { 339 testToFromWithLevelAndLimit(t, i, input, name, limit[i]) 340 } 341 // Test HuffmanCompression 342 testToFromWithLevelAndLimit(t, -2, input, name, limit[10]) 343 } 344 345 func TestDeflateInflate(t *testing.T) { 346 t.Parallel() 347 for i, h := range deflateInflateTests { 348 testToFromWithLimit(t, h.in, fmt.Sprintf("#%d", i), [11]int{}) 349 } 350 } 351 352 func TestReverseBits(t *testing.T) { 353 for _, h := range reverseBitsTests { 354 if v := reverseBits(h.in, h.bitCount); v != h.out { 355 t.Errorf("reverseBits(%v,%v) = %v, want %v", 356 h.in, h.bitCount, v, h.out) 357 } 358 } 359 } 360 361 type deflateInflateStringTest struct { 362 filename string 363 label string 364 limit [11]int 365 } 366 367 var deflateInflateStringTests = []deflateInflateStringTest{ 368 { 369 "../testdata/e.txt", 370 "2.718281828...", 371 [...]int{100018, 50650, 50960, 51150, 50930, 50790, 50790, 50790, 50790, 50790, 43683}, 372 }, 373 { 374 "../testdata/Mark.Twain-Tom.Sawyer.txt", 375 "Mark.Twain-Tom.Sawyer", 376 [...]int{407330, 187598, 180361, 172974, 169160, 163476, 160936, 160506, 160295, 160295, 233460}, 377 }, 378 } 379 380 func TestDeflateInflateString(t *testing.T) { 381 t.Parallel() 382 if testing.Short() && testenv.Builder() == "" { 383 t.Skip("skipping in short mode") 384 } 385 for _, test := range deflateInflateStringTests { 386 gold, err := ioutil.ReadFile(test.filename) 387 if err != nil { 388 t.Error(err) 389 } 390 testToFromWithLimit(t, gold, test.label, test.limit) 391 if testing.Short() { 392 break 393 } 394 } 395 } 396 397 func TestReaderDict(t *testing.T) { 398 const ( 399 dict = "hello world" 400 text = "hello again world" 401 ) 402 var b bytes.Buffer 403 w, err := NewWriter(&b, 5) 404 if err != nil { 405 t.Fatalf("NewWriter: %v", err) 406 } 407 w.Write([]byte(dict)) 408 w.Flush() 409 b.Reset() 410 w.Write([]byte(text)) 411 w.Close() 412 413 r := NewReaderDict(&b, []byte(dict)) 414 data, err := ioutil.ReadAll(r) 415 if err != nil { 416 t.Fatal(err) 417 } 418 if string(data) != "hello again world" { 419 t.Fatalf("read returned %q want %q", string(data), text) 420 } 421 } 422 423 func TestWriterDict(t *testing.T) { 424 const ( 425 dict = "hello world" 426 text = "hello again world" 427 ) 428 var b bytes.Buffer 429 w, err := NewWriter(&b, 5) 430 if err != nil { 431 t.Fatalf("NewWriter: %v", err) 432 } 433 w.Write([]byte(dict)) 434 w.Flush() 435 b.Reset() 436 w.Write([]byte(text)) 437 w.Close() 438 439 var b1 bytes.Buffer 440 w, _ = NewWriterDict(&b1, 5, []byte(dict)) 441 w.Write([]byte(text)) 442 w.Close() 443 444 if !bytes.Equal(b1.Bytes(), b.Bytes()) { 445 t.Fatalf("writer wrote %q want %q", b1.Bytes(), b.Bytes()) 446 } 447 } 448 449 // See https://golang.org/issue/2508 450 func TestRegression2508(t *testing.T) { 451 if testing.Short() { 452 t.Logf("test disabled with -short") 453 return 454 } 455 w, err := NewWriter(ioutil.Discard, 1) 456 if err != nil { 457 t.Fatalf("NewWriter: %v", err) 458 } 459 buf := make([]byte, 1024) 460 for i := 0; i < 131072; i++ { 461 if _, err := w.Write(buf); err != nil { 462 t.Fatalf("writer failed: %v", err) 463 } 464 } 465 w.Close() 466 } 467 468 func TestWriterReset(t *testing.T) { 469 t.Parallel() 470 for level := 0; level <= 9; level++ { 471 if testing.Short() && level > 1 { 472 break 473 } 474 w, err := NewWriter(ioutil.Discard, level) 475 if err != nil { 476 t.Fatalf("NewWriter: %v", err) 477 } 478 buf := []byte("hello world") 479 n := 1024 480 if testing.Short() { 481 n = 10 482 } 483 for i := 0; i < n; i++ { 484 w.Write(buf) 485 } 486 w.Reset(ioutil.Discard) 487 488 wref, err := NewWriter(ioutil.Discard, level) 489 if err != nil { 490 t.Fatalf("NewWriter: %v", err) 491 } 492 493 // DeepEqual doesn't compare functions. 494 w.d.fill, wref.d.fill = nil, nil 495 w.d.step, wref.d.step = nil, nil 496 w.d.bulkHasher, wref.d.bulkHasher = nil, nil 497 w.d.bestSpeed, wref.d.bestSpeed = nil, nil 498 // hashMatch is always overwritten when used. 499 copy(w.d.hashMatch[:], wref.d.hashMatch[:]) 500 if len(w.d.tokens) != 0 { 501 t.Errorf("level %d Writer not reset after Reset. %d tokens were present", level, len(w.d.tokens)) 502 } 503 // As long as the length is 0, we don't care about the content. 504 w.d.tokens = wref.d.tokens 505 506 // We don't care if there are values in the window, as long as it is at d.index is 0 507 w.d.window = wref.d.window 508 if !reflect.DeepEqual(w, wref) { 509 t.Errorf("level %d Writer not reset after Reset", level) 510 } 511 } 512 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, NoCompression) }) 513 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, DefaultCompression) }) 514 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, BestCompression) }) 515 dict := []byte("we are the world") 516 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, NoCompression, dict) }) 517 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, DefaultCompression, dict) }) 518 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, BestCompression, dict) }) 519 } 520 521 func testResetOutput(t *testing.T, newWriter func(w io.Writer) (*Writer, error)) { 522 buf := new(bytes.Buffer) 523 w, err := newWriter(buf) 524 if err != nil { 525 t.Fatalf("NewWriter: %v", err) 526 } 527 b := []byte("hello world") 528 for i := 0; i < 1024; i++ { 529 w.Write(b) 530 } 531 w.Close() 532 out1 := buf.Bytes() 533 534 buf2 := new(bytes.Buffer) 535 w.Reset(buf2) 536 for i := 0; i < 1024; i++ { 537 w.Write(b) 538 } 539 w.Close() 540 out2 := buf2.Bytes() 541 542 if len(out1) != len(out2) { 543 t.Errorf("got %d, expected %d bytes", len(out2), len(out1)) 544 return 545 } 546 if !bytes.Equal(out1, out2) { 547 mm := 0 548 for i, b := range out1[:len(out2)] { 549 if b != out2[i] { 550 t.Errorf("mismatch index %d: %#02x, expected %#02x", i, out2[i], b) 551 } 552 mm++ 553 if mm == 10 { 554 t.Fatal("Stopping") 555 } 556 } 557 } 558 t.Logf("got %d bytes", len(out1)) 559 } 560 561 // TestBestSpeed tests that round-tripping through deflate and then inflate 562 // recovers the original input. The Write sizes are near the thresholds in the 563 // compressor.encSpeed method (0, 16, 128), as well as near maxStoreBlockSize 564 // (65535). 565 func TestBestSpeed(t *testing.T) { 566 t.Parallel() 567 abc := make([]byte, 128) 568 for i := range abc { 569 abc[i] = byte(i) 570 } 571 abcabc := bytes.Repeat(abc, 131072/len(abc)) 572 var want []byte 573 574 testCases := [][]int{ 575 {65536, 0}, 576 {65536, 1}, 577 {65536, 1, 256}, 578 {65536, 1, 65536}, 579 {65536, 14}, 580 {65536, 15}, 581 {65536, 16}, 582 {65536, 16, 256}, 583 {65536, 16, 65536}, 584 {65536, 127}, 585 {65536, 128}, 586 {65536, 128, 256}, 587 {65536, 128, 65536}, 588 {65536, 129}, 589 {65536, 65536, 256}, 590 {65536, 65536, 65536}, 591 } 592 593 for i, tc := range testCases { 594 for _, firstN := range []int{1, 65534, 65535, 65536, 65537, 131072} { 595 tc[0] = firstN 596 outer: 597 for _, flush := range []bool{false, true} { 598 buf := new(bytes.Buffer) 599 want = want[:0] 600 601 w, err := NewWriter(buf, BestSpeed) 602 if err != nil { 603 t.Errorf("i=%d, firstN=%d, flush=%t: NewWriter: %v", i, firstN, flush, err) 604 continue 605 } 606 for _, n := range tc { 607 want = append(want, abcabc[:n]...) 608 if _, err := w.Write(abcabc[:n]); err != nil { 609 t.Errorf("i=%d, firstN=%d, flush=%t: Write: %v", i, firstN, flush, err) 610 continue outer 611 } 612 if !flush { 613 continue 614 } 615 if err := w.Flush(); err != nil { 616 t.Errorf("i=%d, firstN=%d, flush=%t: Flush: %v", i, firstN, flush, err) 617 continue outer 618 } 619 } 620 if err := w.Close(); err != nil { 621 t.Errorf("i=%d, firstN=%d, flush=%t: Close: %v", i, firstN, flush, err) 622 continue 623 } 624 625 r := NewReader(buf) 626 got, err := ioutil.ReadAll(r) 627 if err != nil { 628 t.Errorf("i=%d, firstN=%d, flush=%t: ReadAll: %v", i, firstN, flush, err) 629 continue 630 } 631 r.Close() 632 633 if !bytes.Equal(got, want) { 634 t.Errorf("i=%d, firstN=%d, flush=%t: corruption during deflate-then-inflate", i, firstN, flush) 635 continue 636 } 637 } 638 } 639 } 640 } 641 642 var errIO = errors.New("IO error") 643 644 // failWriter fails with errIO exactly at the nth call to Write. 645 type failWriter struct{ n int } 646 647 func (w *failWriter) Write(b []byte) (int, error) { 648 w.n-- 649 if w.n == -1 { 650 return 0, errIO 651 } 652 return len(b), nil 653 } 654 655 func TestWriterPersistentError(t *testing.T) { 656 t.Parallel() 657 d, err := ioutil.ReadFile("../testdata/Mark.Twain-Tom.Sawyer.txt") 658 if err != nil { 659 t.Fatalf("ReadFile: %v", err) 660 } 661 d = d[:10000] // Keep this test short 662 663 zw, err := NewWriter(nil, DefaultCompression) 664 if err != nil { 665 t.Fatalf("NewWriter: %v", err) 666 } 667 668 // Sweep over the threshold at which an error is returned. 669 // The variable i makes it such that the ith call to failWriter.Write will 670 // return errIO. Since failWriter errors are not persistent, we must ensure 671 // that flate.Writer errors are persistent. 672 for i := 0; i < 1000; i++ { 673 fw := &failWriter{i} 674 zw.Reset(fw) 675 676 _, werr := zw.Write(d) 677 cerr := zw.Close() 678 if werr != errIO && werr != nil { 679 t.Errorf("test %d, mismatching Write error: got %v, want %v", i, werr, errIO) 680 } 681 if cerr != errIO && fw.n < 0 { 682 t.Errorf("test %d, mismatching Close error: got %v, want %v", i, cerr, errIO) 683 } 684 if fw.n >= 0 { 685 // At this point, the failure threshold was sufficiently high enough 686 // that we wrote the whole stream without any errors. 687 return 688 } 689 } 690 } 691 692 func TestBestSpeedMatch(t *testing.T) { 693 t.Parallel() 694 cases := []struct { 695 previous, current []byte 696 t, s, want int32 697 }{{ 698 previous: []byte{0, 0, 0, 1, 2}, 699 current: []byte{3, 4, 5, 0, 1, 2, 3, 4, 5}, 700 t: -3, 701 s: 3, 702 want: 6, 703 }, { 704 previous: []byte{0, 0, 0, 1, 2}, 705 current: []byte{2, 4, 5, 0, 1, 2, 3, 4, 5}, 706 t: -3, 707 s: 3, 708 want: 3, 709 }, { 710 previous: []byte{0, 0, 0, 1, 1}, 711 current: []byte{3, 4, 5, 0, 1, 2, 3, 4, 5}, 712 t: -3, 713 s: 3, 714 want: 2, 715 }, { 716 previous: []byte{0, 0, 0, 1, 2}, 717 current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5}, 718 t: -1, 719 s: 0, 720 want: 4, 721 }, { 722 previous: []byte{0, 0, 0, 1, 2, 3, 4, 5, 2, 2}, 723 current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5}, 724 t: -7, 725 s: 4, 726 want: 5, 727 }, { 728 previous: []byte{9, 9, 9, 9, 9}, 729 current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5}, 730 t: -1, 731 s: 0, 732 want: 0, 733 }, { 734 previous: []byte{9, 9, 9, 9, 9}, 735 current: []byte{9, 2, 2, 2, 1, 2, 3, 4, 5}, 736 t: 0, 737 s: 1, 738 want: 0, 739 }, { 740 previous: []byte{}, 741 current: []byte{9, 2, 2, 2, 1, 2, 3, 4, 5}, 742 t: -5, 743 s: 1, 744 want: 0, 745 }, { 746 previous: []byte{}, 747 current: []byte{9, 2, 2, 2, 1, 2, 3, 4, 5}, 748 t: -1, 749 s: 1, 750 want: 0, 751 }, { 752 previous: []byte{}, 753 current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5}, 754 t: 0, 755 s: 1, 756 want: 3, 757 }, { 758 previous: []byte{3, 4, 5}, 759 current: []byte{3, 4, 5}, 760 t: -3, 761 s: 0, 762 want: 3, 763 }, { 764 previous: make([]byte, 1000), 765 current: make([]byte, 1000), 766 t: -1000, 767 s: 0, 768 want: maxMatchLength - 4, 769 }, { 770 previous: make([]byte, 200), 771 current: make([]byte, 500), 772 t: -200, 773 s: 0, 774 want: maxMatchLength - 4, 775 }, { 776 previous: make([]byte, 200), 777 current: make([]byte, 500), 778 t: 0, 779 s: 1, 780 want: maxMatchLength - 4, 781 }, { 782 previous: make([]byte, maxMatchLength-4), 783 current: make([]byte, 500), 784 t: -(maxMatchLength - 4), 785 s: 0, 786 want: maxMatchLength - 4, 787 }, { 788 previous: make([]byte, 200), 789 current: make([]byte, 500), 790 t: -200, 791 s: 400, 792 want: 100, 793 }, { 794 previous: make([]byte, 10), 795 current: make([]byte, 500), 796 t: 200, 797 s: 400, 798 want: 100, 799 }} 800 for i, c := range cases { 801 e := deflateFast{prev: c.previous} 802 got := e.matchLen(c.s, c.t, c.current) 803 if got != c.want { 804 t.Errorf("Test %d: match length, want %d, got %d", i, c.want, got) 805 } 806 } 807 } 808 809 func TestBestSpeedMaxMatchOffset(t *testing.T) { 810 t.Parallel() 811 const abc, xyz = "abcdefgh", "stuvwxyz" 812 for _, matchBefore := range []bool{false, true} { 813 for _, extra := range []int{0, inputMargin - 1, inputMargin, inputMargin + 1, 2 * inputMargin} { 814 for offsetAdj := -5; offsetAdj <= +5; offsetAdj++ { 815 report := func(desc string, err error) { 816 t.Errorf("matchBefore=%t, extra=%d, offsetAdj=%d: %s%v", 817 matchBefore, extra, offsetAdj, desc, err) 818 } 819 820 offset := maxMatchOffset + offsetAdj 821 822 // Make src to be a []byte of the form 823 // "%s%s%s%s%s" % (abc, zeros0, xyzMaybe, abc, zeros1) 824 // where: 825 // zeros0 is approximately maxMatchOffset zeros. 826 // xyzMaybe is either xyz or the empty string. 827 // zeros1 is between 0 and 30 zeros. 828 // The difference between the two abc's will be offset, which 829 // is maxMatchOffset plus or minus a small adjustment. 830 src := make([]byte, offset+len(abc)+extra) 831 copy(src, abc) 832 if !matchBefore { 833 copy(src[offset-len(xyz):], xyz) 834 } 835 copy(src[offset:], abc) 836 837 buf := new(bytes.Buffer) 838 w, err := NewWriter(buf, BestSpeed) 839 if err != nil { 840 report("NewWriter: ", err) 841 continue 842 } 843 if _, err := w.Write(src); err != nil { 844 report("Write: ", err) 845 continue 846 } 847 if err := w.Close(); err != nil { 848 report("Writer.Close: ", err) 849 continue 850 } 851 852 r := NewReader(buf) 853 dst, err := ioutil.ReadAll(r) 854 r.Close() 855 if err != nil { 856 report("ReadAll: ", err) 857 continue 858 } 859 860 if !bytes.Equal(dst, src) { 861 report("", fmt.Errorf("bytes differ after round-tripping")) 862 continue 863 } 864 } 865 } 866 } 867 } 868 869 func TestMaxStackSize(t *testing.T) { 870 // This test must not run in parallel with other tests as debug.SetMaxStack 871 // affects all goroutines. 872 n := debug.SetMaxStack(1 << 16) 873 defer debug.SetMaxStack(n) 874 875 var wg sync.WaitGroup 876 defer wg.Wait() 877 878 b := make([]byte, 1<<20) 879 for level := HuffmanOnly; level <= BestCompression; level++ { 880 // Run in separate goroutine to increase probability of stack regrowth. 881 wg.Add(1) 882 go func(level int) { 883 defer wg.Done() 884 zw, err := NewWriter(ioutil.Discard, level) 885 if err != nil { 886 t.Errorf("level %d, NewWriter() = %v, want nil", level, err) 887 } 888 if n, err := zw.Write(b); n != len(b) || err != nil { 889 t.Errorf("level %d, Write() = (%d, %v), want (%d, nil)", level, n, err, len(b)) 890 } 891 if err := zw.Close(); err != nil { 892 t.Errorf("level %d, Close() = %v, want nil", level, err) 893 } 894 zw.Reset(ioutil.Discard) 895 }(level) 896 } 897 }