inflate_test.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. // Copyright 2014 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. "crypto/rand"
  8. "io"
  9. "io/ioutil"
  10. "strconv"
  11. "strings"
  12. "testing"
  13. )
  14. func TestReset(t *testing.T) {
  15. ss := []string{
  16. "lorem ipsum izzle fo rizzle",
  17. "the quick brown fox jumped over",
  18. }
  19. deflated := make([]bytes.Buffer, 2)
  20. for i, s := range ss {
  21. w, _ := NewWriter(&deflated[i], 1)
  22. w.Write([]byte(s))
  23. w.Close()
  24. }
  25. inflated := make([]bytes.Buffer, 2)
  26. f := NewReader(&deflated[0])
  27. io.Copy(&inflated[0], f)
  28. f.(Resetter).Reset(&deflated[1], nil)
  29. io.Copy(&inflated[1], f)
  30. f.Close()
  31. for i, s := range ss {
  32. if s != inflated[i].String() {
  33. t.Errorf("inflated[%d]:\ngot %q\nwant %q", i, inflated[i], s)
  34. }
  35. }
  36. }
  37. func TestReaderTruncated(t *testing.T) {
  38. vectors := []struct{ input, output string }{
  39. {"\x00", ""},
  40. {"\x00\f", ""},
  41. {"\x00\f\x00", ""},
  42. {"\x00\f\x00\xf3\xff", ""},
  43. {"\x00\f\x00\xf3\xffhello", "hello"},
  44. {"\x00\f\x00\xf3\xffhello, world", "hello, world"},
  45. {"\x02", ""},
  46. {"\xf2H\xcd", "He"},
  47. {"\xf2H͙0a\u0084\t", "Hel\x90\x90\x90\x90\x90"},
  48. {"\xf2H͙0a\u0084\t\x00", "Hel\x90\x90\x90\x90\x90"},
  49. }
  50. for i, v := range vectors {
  51. r := strings.NewReader(v.input)
  52. zr := NewReader(r)
  53. b, err := ioutil.ReadAll(zr)
  54. if err != io.ErrUnexpectedEOF {
  55. t.Errorf("test %d, error mismatch: got %v, want io.ErrUnexpectedEOF", i, err)
  56. }
  57. if string(b) != v.output {
  58. t.Errorf("test %d, output mismatch: got %q, want %q", i, b, v.output)
  59. }
  60. }
  61. }
  62. func TestResetDict(t *testing.T) {
  63. dict := []byte("the lorem fox")
  64. ss := []string{
  65. "lorem ipsum izzle fo rizzle",
  66. "the quick brown fox jumped over",
  67. }
  68. deflated := make([]bytes.Buffer, len(ss))
  69. for i, s := range ss {
  70. w, _ := NewWriterDict(&deflated[i], DefaultCompression, dict)
  71. w.Write([]byte(s))
  72. w.Close()
  73. }
  74. inflated := make([]bytes.Buffer, len(ss))
  75. f := NewReader(nil)
  76. for i := range inflated {
  77. f.(Resetter).Reset(&deflated[i], dict)
  78. io.Copy(&inflated[i], f)
  79. }
  80. f.Close()
  81. for i, s := range ss {
  82. if s != inflated[i].String() {
  83. t.Errorf("inflated[%d]:\ngot %q\nwant %q", i, inflated[i], s)
  84. }
  85. }
  86. }
  87. // Tests ported from zlib/test/infcover.c
  88. type infTest struct {
  89. hex string
  90. id string
  91. n int
  92. }
  93. var infTests = []infTest{
  94. {"0 0 0 0 0", "invalid stored block lengths", 1},
  95. {"3 0", "fixed", 0},
  96. {"6", "invalid block type", 1},
  97. {"1 1 0 fe ff 0", "stored", 0},
  98. {"fc 0 0", "too many length or distance symbols", 1},
  99. {"4 0 fe ff", "invalid code lengths set", 1},
  100. {"4 0 24 49 0", "invalid bit length repeat", 1},
  101. {"4 0 24 e9 ff ff", "invalid bit length repeat", 1},
  102. {"4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1},
  103. {"4 80 49 92 24 49 92 24 71 ff ff 93 11 0", "invalid literal/lengths set", 1},
  104. {"4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1},
  105. {"4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1},
  106. {"2 7e ff ff", "invalid distance code", 1},
  107. {"c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1},
  108. // also trailer mismatch just in inflate()
  109. {"1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1},
  110. {"1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1", "incorrect length check", -1},
  111. {"5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0},
  112. {"5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f", "long code", 0},
  113. {"ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0},
  114. {"ed cf c1 b1 2c 47 10 c4 30 fa 6f 35 1d 1 82 59 3d fb be 2e 2a fc f c", "long distance and extra", 0},
  115. {"ed c0 81 0 0 0 0 80 a0 fd a9 17 a9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0},
  116. }
  117. func TestInflate(t *testing.T) {
  118. for _, test := range infTests {
  119. hex := strings.Split(test.hex, " ")
  120. data := make([]byte, len(hex))
  121. for i, h := range hex {
  122. b, _ := strconv.ParseInt(h, 16, 32)
  123. data[i] = byte(b)
  124. }
  125. buf := bytes.NewReader(data)
  126. r := NewReader(buf)
  127. _, err := io.Copy(ioutil.Discard, r)
  128. if (test.n == 0 && err == nil) || (test.n != 0 && err != nil) {
  129. t.Logf("%q: OK:", test.id)
  130. t.Logf(" - got %v", err)
  131. continue
  132. }
  133. if test.n == 0 && err != nil {
  134. t.Errorf("%q: Expected no error, but got %v", test.id, err)
  135. continue
  136. }
  137. if test.n != 0 && err == nil {
  138. t.Errorf("%q:Expected an error, but got none", test.id)
  139. continue
  140. }
  141. t.Fatal(test.n, err)
  142. }
  143. for _, test := range infOutTests {
  144. hex := strings.Split(test.hex, " ")
  145. data := make([]byte, len(hex))
  146. for i, h := range hex {
  147. b, _ := strconv.ParseInt(h, 16, 32)
  148. data[i] = byte(b)
  149. }
  150. buf := bytes.NewReader(data)
  151. r := NewReader(buf)
  152. _, err := io.Copy(ioutil.Discard, r)
  153. if test.err == (err != nil) {
  154. t.Logf("%q: OK:", test.id)
  155. t.Logf(" - got %v", err)
  156. continue
  157. }
  158. if test.err == false && err != nil {
  159. t.Errorf("%q: Expected no error, but got %v", test.id, err)
  160. continue
  161. }
  162. if test.err && err == nil {
  163. t.Errorf("%q: Expected an error, but got none", test.id)
  164. continue
  165. }
  166. t.Fatal(test.err, err)
  167. }
  168. }
  169. // Tests ported from zlib/test/infcover.c
  170. // Since zlib inflate is push (writer) instead of pull (reader)
  171. // some of the window size tests have been removed, since they
  172. // are irrelevant.
  173. type infOutTest struct {
  174. hex string
  175. id string
  176. step int
  177. win int
  178. length int
  179. err bool
  180. }
  181. var infOutTests = []infOutTest{
  182. {"2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258, false},
  183. {"63 18 5 40 c 0", "window wrap", 3, -8, 300, false},
  184. {"e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68 ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, true},
  185. {"25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258, true},
  186. {"3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258, true},
  187. {"1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258, true},
  188. {"d c7 1 ae eb 38 c 4 41 a0 87 72 de df fb 1f b8 36 b1 38 5d ff ff 0", "fast 2nd level codes and too far back", 0, -8, 258, true},
  189. {"63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, false},
  190. {"63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0", "contiguous and wrap around window", 6, -8, 259, false},
  191. {"63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259, false},
  192. {"1f 8b 0 0", "bad gzip method", 0, 31, 0, true},
  193. {"1f 8b 8 80", "bad gzip flags", 0, 31, 0, true},
  194. {"77 85", "bad zlib method", 0, 15, 0, true},
  195. {"78 9c", "bad zlib window size", 0, 8, 0, true},
  196. {"1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1, true},
  197. {"1f 8b 8 2 0 0 0 0 0 0 1d 26 3 0 0 0 0 0 0 0 0 0", "check gzip length", 0, 47, 0, true},
  198. {"78 90", "bad zlib header check", 0, 47, 0, true},
  199. {"8 b8 0 0 0 1", "need dictionary", 0, 8, 0, true},
  200. {"63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, false},
  201. {"3 0", "use fixed blocks", 0, -15, 1, false},
  202. {"", "bad window size", 0, 1, 0, true},
  203. }
  204. func TestWriteTo(t *testing.T) {
  205. input := make([]byte, 100000)
  206. n, err := rand.Read(input)
  207. if err != nil {
  208. t.Fatal(err)
  209. }
  210. if n != len(input) {
  211. t.Fatal("did not fill buffer")
  212. }
  213. compressed := &bytes.Buffer{}
  214. w, err := NewWriter(compressed, -2)
  215. if err != nil {
  216. t.Fatal(err)
  217. }
  218. n, err = w.Write(input)
  219. if err != nil {
  220. t.Fatal(err)
  221. }
  222. if n != len(input) {
  223. t.Fatal("did not fill buffer")
  224. }
  225. w.Close()
  226. buf := compressed.Bytes()
  227. dec := NewReader(bytes.NewBuffer(buf))
  228. // ReadAll does not use WriteTo, but we wrap it in a NopCloser to be sure.
  229. readall, err := ioutil.ReadAll(ioutil.NopCloser(dec))
  230. if err != nil {
  231. t.Fatal(err)
  232. }
  233. if len(readall) != len(input) {
  234. t.Fatal("did not decompress everything")
  235. }
  236. dec = NewReader(bytes.NewBuffer(buf))
  237. wtbuf := &bytes.Buffer{}
  238. written, err := dec.(io.WriterTo).WriteTo(wtbuf)
  239. if err != nil {
  240. t.Fatal(err)
  241. }
  242. if written != int64(len(input)) {
  243. t.Error("Returned length did not match, expected", len(input), "got", written)
  244. }
  245. if wtbuf.Len() != len(input) {
  246. t.Error("Actual Length did not match, expected", len(input), "got", wtbuf.Len())
  247. }
  248. if bytes.Compare(wtbuf.Bytes(), input) != 0 {
  249. t.Fatal("output did not match input")
  250. }
  251. }