github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/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 if testing.Short() && len(h.in) > 10000 { 349 continue 350 } 351 testToFromWithLimit(t, h.in, fmt.Sprintf("#%d", i), [11]int{}) 352 } 353 } 354 355 func TestReverseBits(t *testing.T) { 356 for _, h := range reverseBitsTests { 357 if v := reverseBits(h.in, h.bitCount); v != h.out { 358 t.Errorf("reverseBits(%v,%v) = %v, want %v", 359 h.in, h.bitCount, v, h.out) 360 } 361 } 362 } 363 364 type deflateInflateStringTest struct { 365 filename string 366 label string 367 limit [11]int 368 } 369 370 var deflateInflateStringTests = []deflateInflateStringTest{ 371 { 372 "../testdata/e.txt", 373 "2.718281828...", 374 [...]int{100018, 50650, 50960, 51150, 50930, 50790, 50790, 50790, 50790, 50790, 43683}, 375 }, 376 { 377 "testdata/Isaac.Newton-Opticks.txt", 378 "Isaac.Newton-Opticks", 379 [...]int{567248, 218338, 198211, 193152, 181100, 175427, 175427, 173597, 173422, 173422, 325240}, 380 }, 381 } 382 383 func TestDeflateInflateString(t *testing.T) { 384 t.Parallel() 385 if testing.Short() && testenv.Builder() == "" { 386 t.Skip("skipping in short mode") 387 } 388 for _, test := range deflateInflateStringTests { 389 gold, err := ioutil.ReadFile(test.filename) 390 if err != nil { 391 t.Error(err) 392 } 393 testToFromWithLimit(t, gold, test.label, test.limit) 394 if testing.Short() { 395 break 396 } 397 } 398 } 399 400 func TestReaderDict(t *testing.T) { 401 const ( 402 dict = "hello world" 403 text = "hello again world" 404 ) 405 var b bytes.Buffer 406 w, err := NewWriter(&b, 5) 407 if err != nil { 408 t.Fatalf("NewWriter: %v", err) 409 } 410 w.Write([]byte(dict)) 411 w.Flush() 412 b.Reset() 413 w.Write([]byte(text)) 414 w.Close() 415 416 r := NewReaderDict(&b, []byte(dict)) 417 data, err := ioutil.ReadAll(r) 418 if err != nil { 419 t.Fatal(err) 420 } 421 if string(data) != "hello again world" { 422 t.Fatalf("read returned %q want %q", string(data), text) 423 } 424 } 425 426 func TestWriterDict(t *testing.T) { 427 const ( 428 dict = "hello world" 429 text = "hello again world" 430 ) 431 var b bytes.Buffer 432 w, err := NewWriter(&b, 5) 433 if err != nil { 434 t.Fatalf("NewWriter: %v", err) 435 } 436 w.Write([]byte(dict)) 437 w.Flush() 438 b.Reset() 439 w.Write([]byte(text)) 440 w.Close() 441 442 var b1 bytes.Buffer 443 w, _ = NewWriterDict(&b1, 5, []byte(dict)) 444 w.Write([]byte(text)) 445 w.Close() 446 447 if !bytes.Equal(b1.Bytes(), b.Bytes()) { 448 t.Fatalf("writer wrote %q want %q", b1.Bytes(), b.Bytes()) 449 } 450 } 451 452 // See https://golang.org/issue/2508 453 func TestRegression2508(t *testing.T) { 454 if testing.Short() { 455 t.Logf("test disabled with -short") 456 return 457 } 458 w, err := NewWriter(ioutil.Discard, 1) 459 if err != nil { 460 t.Fatalf("NewWriter: %v", err) 461 } 462 buf := make([]byte, 1024) 463 for i := 0; i < 131072; i++ { 464 if _, err := w.Write(buf); err != nil { 465 t.Fatalf("writer failed: %v", err) 466 } 467 } 468 w.Close() 469 } 470 471 func TestWriterReset(t *testing.T) { 472 t.Parallel() 473 for level := 0; level <= 9; level++ { 474 if testing.Short() && level > 1 { 475 break 476 } 477 w, err := NewWriter(ioutil.Discard, level) 478 if err != nil { 479 t.Fatalf("NewWriter: %v", err) 480 } 481 buf := []byte("hello world") 482 n := 1024 483 if testing.Short() { 484 n = 10 485 } 486 for i := 0; i < n; i++ { 487 w.Write(buf) 488 } 489 w.Reset(ioutil.Discard) 490 491 wref, err := NewWriter(ioutil.Discard, level) 492 if err != nil { 493 t.Fatalf("NewWriter: %v", err) 494 } 495 496 // DeepEqual doesn't compare functions. 497 w.d.fill, wref.d.fill = nil, nil 498 w.d.step, wref.d.step = nil, nil 499 w.d.bulkHasher, wref.d.bulkHasher = nil, nil 500 w.d.bestSpeed, wref.d.bestSpeed = nil, nil 501 // hashMatch is always overwritten when used. 502 copy(w.d.hashMatch[:], wref.d.hashMatch[:]) 503 if len(w.d.tokens) != 0 { 504 t.Errorf("level %d Writer not reset after Reset. %d tokens were present", level, len(w.d.tokens)) 505 } 506 // As long as the length is 0, we don't care about the content. 507 w.d.tokens = wref.d.tokens 508 509 // We don't care if there are values in the window, as long as it is at d.index is 0 510 w.d.window = wref.d.window 511 if !reflect.DeepEqual(w, wref) { 512 t.Errorf("level %d Writer not reset after Reset", level) 513 } 514 } 515 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, NoCompression) }) 516 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, DefaultCompression) }) 517 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, BestCompression) }) 518 dict := []byte("we are the world") 519 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, NoCompression, dict) }) 520 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, DefaultCompression, dict) }) 521 testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, BestCompression, dict) }) 522 } 523 524 func testResetOutput(t *testing.T, newWriter func(w io.Writer) (*Writer, error)) { 525 buf := new(bytes.Buffer) 526 w, err := newWriter(buf) 527 if err != nil { 528 t.Fatalf("NewWriter: %v", err) 529 } 530 b := []byte("hello world") 531 for i := 0; i < 1024; i++ { 532 w.Write(b) 533 } 534 w.Close() 535 out1 := buf.Bytes() 536 537 buf2 := new(bytes.Buffer) 538 w.Reset(buf2) 539 for i := 0; i < 1024; i++ { 540 w.Write(b) 541 } 542 w.Close() 543 out2 := buf2.Bytes() 544 545 if len(out1) != len(out2) { 546 t.Errorf("got %d, expected %d bytes", len(out2), len(out1)) 547 return 548 } 549 if !bytes.Equal(out1, out2) { 550 mm := 0 551 for i, b := range out1[:len(out2)] { 552 if b != out2[i] { 553 t.Errorf("mismatch index %d: %#02x, expected %#02x", i, out2[i], b) 554 } 555 mm++ 556 if mm == 10 { 557 t.Fatal("Stopping") 558 } 559 } 560 } 561 t.Logf("got %d bytes", len(out1)) 562 } 563 564 // TestBestSpeed tests that round-tripping through deflate and then inflate 565 // recovers the original input. The Write sizes are near the thresholds in the 566 // compressor.encSpeed method (0, 16, 128), as well as near maxStoreBlockSize 567 // (65535). 568 func TestBestSpeed(t *testing.T) { 569 t.Parallel() 570 abc := make([]byte, 128) 571 for i := range abc { 572 abc[i] = byte(i) 573 } 574 abcabc := bytes.Repeat(abc, 131072/len(abc)) 575 var want []byte 576 577 testCases := [][]int{ 578 {65536, 0}, 579 {65536, 1}, 580 {65536, 1, 256}, 581 {65536, 1, 65536}, 582 {65536, 14}, 583 {65536, 15}, 584 {65536, 16}, 585 {65536, 16, 256}, 586 {65536, 16, 65536}, 587 {65536, 127}, 588 {65536, 128}, 589 {65536, 128, 256}, 590 {65536, 128, 65536}, 591 {65536, 129}, 592 {65536, 65536, 256}, 593 {65536, 65536, 65536}, 594 } 595 596 for i, tc := range testCases { 597 if i >= 3 && testing.Short() { 598 break 599 } 600 for _, firstN := range []int{1, 65534, 65535, 65536, 65537, 131072} { 601 tc[0] = firstN 602 outer: 603 for _, flush := range []bool{false, true} { 604 buf := new(bytes.Buffer) 605 want = want[:0] 606 607 w, err := NewWriter(buf, BestSpeed) 608 if err != nil { 609 t.Errorf("i=%d, firstN=%d, flush=%t: NewWriter: %v", i, firstN, flush, err) 610 continue 611 } 612 for _, n := range tc { 613 want = append(want, abcabc[:n]...) 614 if _, err := w.Write(abcabc[:n]); err != nil { 615 t.Errorf("i=%d, firstN=%d, flush=%t: Write: %v", i, firstN, flush, err) 616 continue outer 617 } 618 if !flush { 619 continue 620 } 621 if err := w.Flush(); err != nil { 622 t.Errorf("i=%d, firstN=%d, flush=%t: Flush: %v", i, firstN, flush, err) 623 continue outer 624 } 625 } 626 if err := w.Close(); err != nil { 627 t.Errorf("i=%d, firstN=%d, flush=%t: Close: %v", i, firstN, flush, err) 628 continue 629 } 630 631 r := NewReader(buf) 632 got, err := ioutil.ReadAll(r) 633 if err != nil { 634 t.Errorf("i=%d, firstN=%d, flush=%t: ReadAll: %v", i, firstN, flush, err) 635 continue 636 } 637 r.Close() 638 639 if !bytes.Equal(got, want) { 640 t.Errorf("i=%d, firstN=%d, flush=%t: corruption during deflate-then-inflate", i, firstN, flush) 641 continue 642 } 643 } 644 } 645 } 646 } 647 648 var errIO = errors.New("IO error") 649 650 // failWriter fails with errIO exactly at the nth call to Write. 651 type failWriter struct{ n int } 652 653 func (w *failWriter) Write(b []byte) (int, error) { 654 w.n-- 655 if w.n == -1 { 656 return 0, errIO 657 } 658 return len(b), nil 659 } 660 661 func TestWriterPersistentError(t *testing.T) { 662 t.Parallel() 663 d, err := ioutil.ReadFile("testdata/Isaac.Newton-Opticks.txt") 664 if err != nil { 665 t.Fatalf("ReadFile: %v", err) 666 } 667 d = d[:10000] // Keep this test short 668 669 zw, err := NewWriter(nil, DefaultCompression) 670 if err != nil { 671 t.Fatalf("NewWriter: %v", err) 672 } 673 674 // Sweep over the threshold at which an error is returned. 675 // The variable i makes it such that the ith call to failWriter.Write will 676 // return errIO. Since failWriter errors are not persistent, we must ensure 677 // that flate.Writer errors are persistent. 678 for i := 0; i < 1000; i++ { 679 fw := &failWriter{i} 680 zw.Reset(fw) 681 682 _, werr := zw.Write(d) 683 cerr := zw.Close() 684 if werr != errIO && werr != nil { 685 t.Errorf("test %d, mismatching Write error: got %v, want %v", i, werr, errIO) 686 } 687 if cerr != errIO && fw.n < 0 { 688 t.Errorf("test %d, mismatching Close error: got %v, want %v", i, cerr, errIO) 689 } 690 if fw.n >= 0 { 691 // At this point, the failure threshold was sufficiently high enough 692 // that we wrote the whole stream without any errors. 693 return 694 } 695 } 696 } 697 698 func TestBestSpeedMatch(t *testing.T) { 699 t.Parallel() 700 cases := []struct { 701 previous, current []byte 702 t, s, want int32 703 }{{ 704 previous: []byte{0, 0, 0, 1, 2}, 705 current: []byte{3, 4, 5, 0, 1, 2, 3, 4, 5}, 706 t: -3, 707 s: 3, 708 want: 6, 709 }, { 710 previous: []byte{0, 0, 0, 1, 2}, 711 current: []byte{2, 4, 5, 0, 1, 2, 3, 4, 5}, 712 t: -3, 713 s: 3, 714 want: 3, 715 }, { 716 previous: []byte{0, 0, 0, 1, 1}, 717 current: []byte{3, 4, 5, 0, 1, 2, 3, 4, 5}, 718 t: -3, 719 s: 3, 720 want: 2, 721 }, { 722 previous: []byte{0, 0, 0, 1, 2}, 723 current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5}, 724 t: -1, 725 s: 0, 726 want: 4, 727 }, { 728 previous: []byte{0, 0, 0, 1, 2, 3, 4, 5, 2, 2}, 729 current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5}, 730 t: -7, 731 s: 4, 732 want: 5, 733 }, { 734 previous: []byte{9, 9, 9, 9, 9}, 735 current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5}, 736 t: -1, 737 s: 0, 738 want: 0, 739 }, { 740 previous: []byte{9, 9, 9, 9, 9}, 741 current: []byte{9, 2, 2, 2, 1, 2, 3, 4, 5}, 742 t: 0, 743 s: 1, 744 want: 0, 745 }, { 746 previous: []byte{}, 747 current: []byte{9, 2, 2, 2, 1, 2, 3, 4, 5}, 748 t: -5, 749 s: 1, 750 want: 0, 751 }, { 752 previous: []byte{}, 753 current: []byte{9, 2, 2, 2, 1, 2, 3, 4, 5}, 754 t: -1, 755 s: 1, 756 want: 0, 757 }, { 758 previous: []byte{}, 759 current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5}, 760 t: 0, 761 s: 1, 762 want: 3, 763 }, { 764 previous: []byte{3, 4, 5}, 765 current: []byte{3, 4, 5}, 766 t: -3, 767 s: 0, 768 want: 3, 769 }, { 770 previous: make([]byte, 1000), 771 current: make([]byte, 1000), 772 t: -1000, 773 s: 0, 774 want: maxMatchLength - 4, 775 }, { 776 previous: make([]byte, 200), 777 current: make([]byte, 500), 778 t: -200, 779 s: 0, 780 want: maxMatchLength - 4, 781 }, { 782 previous: make([]byte, 200), 783 current: make([]byte, 500), 784 t: 0, 785 s: 1, 786 want: maxMatchLength - 4, 787 }, { 788 previous: make([]byte, maxMatchLength-4), 789 current: make([]byte, 500), 790 t: -(maxMatchLength - 4), 791 s: 0, 792 want: maxMatchLength - 4, 793 }, { 794 previous: make([]byte, 200), 795 current: make([]byte, 500), 796 t: -200, 797 s: 400, 798 want: 100, 799 }, { 800 previous: make([]byte, 10), 801 current: make([]byte, 500), 802 t: 200, 803 s: 400, 804 want: 100, 805 }} 806 for i, c := range cases { 807 e := deflateFast{prev: c.previous} 808 got := e.matchLen(c.s, c.t, c.current) 809 if got != c.want { 810 t.Errorf("Test %d: match length, want %d, got %d", i, c.want, got) 811 } 812 } 813 } 814 815 func TestBestSpeedMaxMatchOffset(t *testing.T) { 816 t.Parallel() 817 const abc, xyz = "abcdefgh", "stuvwxyz" 818 for _, matchBefore := range []bool{false, true} { 819 for _, extra := range []int{0, inputMargin - 1, inputMargin, inputMargin + 1, 2 * inputMargin} { 820 for offsetAdj := -5; offsetAdj <= +5; offsetAdj++ { 821 report := func(desc string, err error) { 822 t.Errorf("matchBefore=%t, extra=%d, offsetAdj=%d: %s%v", 823 matchBefore, extra, offsetAdj, desc, err) 824 } 825 826 offset := maxMatchOffset + offsetAdj 827 828 // Make src to be a []byte of the form 829 // "%s%s%s%s%s" % (abc, zeros0, xyzMaybe, abc, zeros1) 830 // where: 831 // zeros0 is approximately maxMatchOffset zeros. 832 // xyzMaybe is either xyz or the empty string. 833 // zeros1 is between 0 and 30 zeros. 834 // The difference between the two abc's will be offset, which 835 // is maxMatchOffset plus or minus a small adjustment. 836 src := make([]byte, offset+len(abc)+extra) 837 copy(src, abc) 838 if !matchBefore { 839 copy(src[offset-len(xyz):], xyz) 840 } 841 copy(src[offset:], abc) 842 843 buf := new(bytes.Buffer) 844 w, err := NewWriter(buf, BestSpeed) 845 if err != nil { 846 report("NewWriter: ", err) 847 continue 848 } 849 if _, err := w.Write(src); err != nil { 850 report("Write: ", err) 851 continue 852 } 853 if err := w.Close(); err != nil { 854 report("Writer.Close: ", err) 855 continue 856 } 857 858 r := NewReader(buf) 859 dst, err := ioutil.ReadAll(r) 860 r.Close() 861 if err != nil { 862 report("ReadAll: ", err) 863 continue 864 } 865 866 if !bytes.Equal(dst, src) { 867 report("", fmt.Errorf("bytes differ after round-tripping")) 868 continue 869 } 870 } 871 } 872 } 873 } 874 875 func TestMaxStackSize(t *testing.T) { 876 // This test must not run in parallel with other tests as debug.SetMaxStack 877 // affects all goroutines. 878 n := debug.SetMaxStack(1 << 16) 879 defer debug.SetMaxStack(n) 880 881 var wg sync.WaitGroup 882 defer wg.Wait() 883 884 b := make([]byte, 1<<20) 885 for level := HuffmanOnly; level <= BestCompression; level++ { 886 // Run in separate goroutine to increase probability of stack regrowth. 887 wg.Add(1) 888 go func(level int) { 889 defer wg.Done() 890 zw, err := NewWriter(ioutil.Discard, level) 891 if err != nil { 892 t.Errorf("level %d, NewWriter() = %v, want nil", level, err) 893 } 894 if n, err := zw.Write(b); n != len(b) || err != nil { 895 t.Errorf("level %d, Write() = (%d, %v), want (%d, nil)", level, n, err, len(b)) 896 } 897 if err := zw.Close(); err != nil { 898 t.Errorf("level %d, Close() = %v, want nil", level, err) 899 } 900 zw.Reset(ioutil.Discard) 901 }(level) 902 } 903 }