writer_test.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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. package flate
  5. import (
  6. "bytes"
  7. "fmt"
  8. "io"
  9. "math/rand"
  10. "runtime"
  11. "testing"
  12. )
  13. func BenchmarkEncode(b *testing.B) {
  14. doBench(b, func(b *testing.B, buf0 []byte, level, n int) {
  15. b.StopTimer()
  16. b.SetBytes(int64(n))
  17. buf1 := make([]byte, n)
  18. for i := 0; i < n; i += len(buf0) {
  19. if len(buf0) > n-i {
  20. buf0 = buf0[:n-i]
  21. }
  22. copy(buf1[i:], buf0)
  23. }
  24. buf0 = nil
  25. w, err := NewWriter(io.Discard, level)
  26. if err != nil {
  27. b.Fatal(err)
  28. }
  29. runtime.GC()
  30. b.StartTimer()
  31. for i := 0; i < b.N; i++ {
  32. w.Reset(io.Discard)
  33. w.Write(buf1)
  34. w.Close()
  35. }
  36. })
  37. }
  38. // errorWriter is a writer that fails after N writes.
  39. type errorWriter struct {
  40. N int
  41. }
  42. func (e *errorWriter) Write(b []byte) (int, error) {
  43. if e.N <= 0 {
  44. return 0, io.ErrClosedPipe
  45. }
  46. e.N--
  47. return len(b), nil
  48. }
  49. // Test if errors from the underlying writer is passed upwards.
  50. func TestWriteError(t *testing.T) {
  51. t.Parallel()
  52. buf := new(bytes.Buffer)
  53. n := 65536
  54. if !testing.Short() {
  55. n *= 4
  56. }
  57. for i := 0; i < n; i++ {
  58. fmt.Fprintf(buf, "asdasfasf%d%dfghfgujyut%dyutyu\n", i, i, i)
  59. }
  60. in := buf.Bytes()
  61. // We create our own buffer to control number of writes.
  62. copyBuffer := make([]byte, 128)
  63. for l := 0; l < 10; l++ {
  64. for fail := 1; fail <= 256; fail *= 2 {
  65. // Fail after 'fail' writes
  66. ew := &errorWriter{N: fail}
  67. w, err := NewWriter(ew, l)
  68. if err != nil {
  69. t.Fatalf("NewWriter: level %d: %v", l, err)
  70. }
  71. n, err := io.CopyBuffer(w, struct{ io.Reader }{bytes.NewBuffer(in)}, copyBuffer)
  72. if err == nil {
  73. t.Fatalf("Level %d: Expected an error, writer was %#v", l, ew)
  74. }
  75. n2, err := w.Write([]byte{1, 2, 2, 3, 4, 5})
  76. if n2 != 0 {
  77. t.Fatal("Level", l, "Expected 0 length write, got", n)
  78. }
  79. if err == nil {
  80. t.Fatal("Level", l, "Expected an error")
  81. }
  82. err = w.Flush()
  83. if err == nil {
  84. t.Fatal("Level", l, "Expected an error on flush")
  85. }
  86. err = w.Close()
  87. if err == nil {
  88. t.Fatal("Level", l, "Expected an error on close")
  89. }
  90. w.Reset(io.Discard)
  91. n2, err = w.Write([]byte{1, 2, 3, 4, 5, 6})
  92. if err != nil {
  93. t.Fatal("Level", l, "Got unexpected error after reset:", err)
  94. }
  95. if n2 == 0 {
  96. t.Fatal("Level", l, "Got 0 length write, expected > 0")
  97. }
  98. if testing.Short() {
  99. return
  100. }
  101. }
  102. }
  103. }
  104. // Test if two runs produce identical results
  105. // even when writing different sizes to the Writer.
  106. func TestDeterministic(t *testing.T) {
  107. t.Parallel()
  108. for i := 0; i <= 9; i++ {
  109. t.Run(fmt.Sprint("L", i), func(t *testing.T) { testDeterministic(i, t) })
  110. }
  111. t.Run("LM2", func(t *testing.T) { testDeterministic(-2, t) })
  112. }
  113. func testDeterministic(i int, t *testing.T) {
  114. t.Parallel()
  115. // Test so much we cross a good number of block boundaries.
  116. var length = maxStoreBlockSize*30 + 500
  117. if testing.Short() {
  118. length /= 10
  119. }
  120. // Create a random, but compressible stream.
  121. rng := rand.New(rand.NewSource(1))
  122. t1 := make([]byte, length)
  123. for i := range t1 {
  124. t1[i] = byte(rng.Int63() & 7)
  125. }
  126. // Do our first encode.
  127. var b1 bytes.Buffer
  128. br := bytes.NewBuffer(t1)
  129. w, err := NewWriter(&b1, i)
  130. if err != nil {
  131. t.Fatal(err)
  132. }
  133. // Use a very small prime sized buffer.
  134. cbuf := make([]byte, 787)
  135. _, err = io.CopyBuffer(w, struct{ io.Reader }{br}, cbuf)
  136. if err != nil {
  137. t.Fatal(err)
  138. }
  139. w.Close()
  140. // We choose a different buffer size,
  141. // bigger than a maximum block, and also a prime.
  142. var b2 bytes.Buffer
  143. cbuf = make([]byte, 81761)
  144. br2 := bytes.NewBuffer(t1)
  145. w2, err := NewWriter(&b2, i)
  146. if err != nil {
  147. t.Fatal(err)
  148. }
  149. _, err = io.CopyBuffer(w2, struct{ io.Reader }{br2}, cbuf)
  150. if err != nil {
  151. t.Fatal(err)
  152. }
  153. w2.Close()
  154. b1b := b1.Bytes()
  155. b2b := b2.Bytes()
  156. if !bytes.Equal(b1b, b2b) {
  157. t.Errorf("level %d did not produce deterministic result, result mismatch, len(a) = %d, len(b) = %d", i, len(b1b), len(b2b))
  158. }
  159. }
  160. // TestDeflateFast_Reset will test that encoding is consistent
  161. // across a warparound of the table offset.
  162. // See https://github.com/golang/go/issues/34121
  163. func TestDeflateFast_Reset(t *testing.T) {
  164. buf := new(bytes.Buffer)
  165. n := 65536
  166. for i := 0; i < n; i++ {
  167. fmt.Fprintf(buf, "asdfasdfasdfasdf%d%dfghfgujyut%dyutyu\n", i, i, i)
  168. }
  169. // This is specific to level 1.
  170. const level = 1
  171. in := buf.Bytes()
  172. offset := 1
  173. if testing.Short() {
  174. offset = 256
  175. }
  176. // We do an encode with a clean buffer to compare.
  177. var want bytes.Buffer
  178. w, err := NewWriter(&want, level)
  179. if err != nil {
  180. t.Fatalf("NewWriter: level %d: %v", level, err)
  181. }
  182. // Output written 3 times.
  183. w.Write(in)
  184. w.Write(in)
  185. w.Write(in)
  186. w.Close()
  187. for ; offset <= 256; offset *= 2 {
  188. w, err := NewWriter(io.Discard, level)
  189. if err != nil {
  190. t.Fatalf("NewWriter: level %d: %v", level, err)
  191. }
  192. // Reset until we are right before the wraparound.
  193. // Each reset adds maxMatchOffset to the offset.
  194. for i := 0; i < (bufferReset-len(in)-offset-maxMatchOffset)/maxMatchOffset; i++ {
  195. // skip ahead to where we are close to wrap around...
  196. w.d.reset(nil)
  197. }
  198. var got bytes.Buffer
  199. w.Reset(&got)
  200. // Write 3 times, close.
  201. for i := 0; i < 3; i++ {
  202. _, err = w.Write(in)
  203. if err != nil {
  204. t.Fatal(err)
  205. }
  206. }
  207. err = w.Close()
  208. if err != nil {
  209. t.Fatal(err)
  210. }
  211. if !bytes.Equal(got.Bytes(), want.Bytes()) {
  212. t.Fatalf("output did not match at wraparound, len(want) = %d, len(got) = %d", want.Len(), got.Len())
  213. }
  214. }
  215. }