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