github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/src/compress/flate/writer_test.go (about) 1 // Copyright 2012 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 "math/rand" 13 "runtime" 14 "testing" 15 ) 16 17 func BenchmarkEncode(b *testing.B) { 18 doBench(b, func(b *testing.B, buf0 []byte, level, n int) { 19 b.StopTimer() 20 b.SetBytes(int64(n)) 21 22 buf1 := make([]byte, n) 23 for i := 0; i < n; i += len(buf0) { 24 if len(buf0) > n-i { 25 buf0 = buf0[:n-i] 26 } 27 copy(buf1[i:], buf0) 28 } 29 buf0 = nil 30 w, err := NewWriter(ioutil.Discard, level) 31 if err != nil { 32 b.Fatal(err) 33 } 34 runtime.GC() 35 b.StartTimer() 36 for i := 0; i < b.N; i++ { 37 w.Reset(ioutil.Discard) 38 w.Write(buf1) 39 w.Close() 40 } 41 }) 42 } 43 44 // errorWriter is a writer that fails after N writes. 45 type errorWriter struct { 46 N int 47 } 48 49 func (e *errorWriter) Write(b []byte) (int, error) { 50 if e.N <= 0 { 51 return 0, io.ErrClosedPipe 52 } 53 e.N-- 54 return len(b), nil 55 } 56 57 // Test if errors from the underlying writer is passed upwards. 58 func TestWriteError(t *testing.T) { 59 t.Parallel() 60 buf := new(bytes.Buffer) 61 n := 65536 62 if !testing.Short() { 63 n *= 4 64 } 65 for i := 0; i < n; i++ { 66 fmt.Fprintf(buf, "asdasfasf%d%dfghfgujyut%dyutyu\n", i, i, i) 67 } 68 in := buf.Bytes() 69 // We create our own buffer to control number of writes. 70 copyBuffer := make([]byte, 128) 71 for l := 0; l < 10; l++ { 72 for fail := 1; fail <= 256; fail *= 2 { 73 // Fail after 'fail' writes 74 ew := &errorWriter{N: fail} 75 w, err := NewWriter(ew, l) 76 if err != nil { 77 t.Fatalf("NewWriter: level %d: %v", l, err) 78 } 79 n, err := io.CopyBuffer(w, struct{ io.Reader }{bytes.NewBuffer(in)}, copyBuffer) 80 if err == nil { 81 t.Fatalf("Level %d: Expected an error, writer was %#v", l, ew) 82 } 83 n2, err := w.Write([]byte{1, 2, 2, 3, 4, 5}) 84 if n2 != 0 { 85 t.Fatal("Level", l, "Expected 0 length write, got", n) 86 } 87 if err == nil { 88 t.Fatal("Level", l, "Expected an error") 89 } 90 err = w.Flush() 91 if err == nil { 92 t.Fatal("Level", l, "Expected an error on flush") 93 } 94 err = w.Close() 95 if err == nil { 96 t.Fatal("Level", l, "Expected an error on close") 97 } 98 99 w.Reset(ioutil.Discard) 100 n2, err = w.Write([]byte{1, 2, 3, 4, 5, 6}) 101 if err != nil { 102 t.Fatal("Level", l, "Got unexpected error after reset:", err) 103 } 104 if n2 == 0 { 105 t.Fatal("Level", l, "Got 0 length write, expected > 0") 106 } 107 if testing.Short() { 108 return 109 } 110 } 111 } 112 } 113 114 // Test if two runs produce identical results 115 // even when writing different sizes to the Writer. 116 func TestDeterministic(t *testing.T) { 117 t.Parallel() 118 for i := 0; i <= 9; i++ { 119 t.Run(fmt.Sprint("L", i), func(t *testing.T) { testDeterministic(i, t) }) 120 } 121 t.Run("LM2", func(t *testing.T) { testDeterministic(-2, t) }) 122 } 123 124 func testDeterministic(i int, t *testing.T) { 125 t.Parallel() 126 // Test so much we cross a good number of block boundaries. 127 var length = maxStoreBlockSize*30 + 500 128 if testing.Short() { 129 length /= 10 130 } 131 132 // Create a random, but compressible stream. 133 rng := rand.New(rand.NewSource(1)) 134 t1 := make([]byte, length) 135 for i := range t1 { 136 t1[i] = byte(rng.Int63() & 7) 137 } 138 139 // Do our first encode. 140 var b1 bytes.Buffer 141 br := bytes.NewBuffer(t1) 142 w, err := NewWriter(&b1, i) 143 if err != nil { 144 t.Fatal(err) 145 } 146 // Use a very small prime sized buffer. 147 cbuf := make([]byte, 787) 148 _, err = io.CopyBuffer(w, struct{ io.Reader }{br}, cbuf) 149 if err != nil { 150 t.Fatal(err) 151 } 152 w.Close() 153 154 // We choose a different buffer size, 155 // bigger than a maximum block, and also a prime. 156 var b2 bytes.Buffer 157 cbuf = make([]byte, 81761) 158 br2 := bytes.NewBuffer(t1) 159 w2, err := NewWriter(&b2, i) 160 if err != nil { 161 t.Fatal(err) 162 } 163 _, err = io.CopyBuffer(w2, struct{ io.Reader }{br2}, cbuf) 164 if err != nil { 165 t.Fatal(err) 166 } 167 w2.Close() 168 169 b1b := b1.Bytes() 170 b2b := b2.Bytes() 171 172 if !bytes.Equal(b1b, b2b) { 173 t.Errorf("level %d did not produce deterministic result, result mismatch, len(a) = %d, len(b) = %d", i, len(b1b), len(b2b)) 174 } 175 }