cbrotli_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. // Copyright 2016 Google Inc. All Rights Reserved.
  2. //
  3. // Distributed under MIT license.
  4. // See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
  5. package cbrotli
  6. import (
  7. "bytes"
  8. "fmt"
  9. "io"
  10. "io/ioutil"
  11. "math"
  12. "math/rand"
  13. "testing"
  14. "time"
  15. )
  16. func checkCompressedData(compressedData, wantOriginalData []byte) error {
  17. uncompressed, err := Decode(compressedData)
  18. if err != nil {
  19. return fmt.Errorf("brotli decompress failed: %v", err)
  20. }
  21. if !bytes.Equal(uncompressed, wantOriginalData) {
  22. if len(wantOriginalData) != len(uncompressed) {
  23. return fmt.Errorf(""+
  24. "Data doesn't uncompress to the original value.\n"+
  25. "Length of original: %v\n"+
  26. "Length of uncompressed: %v",
  27. len(wantOriginalData), len(uncompressed))
  28. }
  29. for i := range wantOriginalData {
  30. if wantOriginalData[i] != uncompressed[i] {
  31. return fmt.Errorf(""+
  32. "Data doesn't uncompress to the original value.\n"+
  33. "Original at %v is %v\n"+
  34. "Uncompressed at %v is %v",
  35. i, wantOriginalData[i], i, uncompressed[i])
  36. }
  37. }
  38. }
  39. return nil
  40. }
  41. func TestEncoderNoWrite(t *testing.T) {
  42. out := bytes.Buffer{}
  43. e := NewWriter(&out, WriterOptions{Quality: 5})
  44. if err := e.Close(); err != nil {
  45. t.Errorf("Close()=%v, want nil", err)
  46. }
  47. // Check Write after close.
  48. if _, err := e.Write([]byte("hi")); err == nil {
  49. t.Errorf("No error after Close() + Write()")
  50. }
  51. }
  52. func TestEncoderEmptyWrite(t *testing.T) {
  53. out := bytes.Buffer{}
  54. e := NewWriter(&out, WriterOptions{Quality: 5})
  55. n, err := e.Write([]byte(""))
  56. if n != 0 || err != nil {
  57. t.Errorf("Write()=%v,%v, want 0, nil", n, err)
  58. }
  59. if err := e.Close(); err != nil {
  60. t.Errorf("Close()=%v, want nil", err)
  61. }
  62. }
  63. func TestWriter(t *testing.T) {
  64. // Test basic encoder usage.
  65. input := []byte("<html><body><H1>Hello world</H1></body></html>")
  66. out := bytes.Buffer{}
  67. e := NewWriter(&out, WriterOptions{Quality: 1})
  68. in := bytes.NewReader([]byte(input))
  69. n, err := io.Copy(e, in)
  70. if err != nil {
  71. t.Errorf("Copy Error: %v", err)
  72. }
  73. if int(n) != len(input) {
  74. t.Errorf("Copy() n=%v, want %v", n, len(input))
  75. }
  76. if err := e.Close(); err != nil {
  77. t.Errorf("Close Error after copied %d bytes: %v", n, err)
  78. }
  79. if err := checkCompressedData(out.Bytes(), input); err != nil {
  80. t.Error(err)
  81. }
  82. }
  83. func TestEncoderStreams(t *testing.T) {
  84. // Test that output is streamed.
  85. // Adjust window size to ensure the encoder outputs at least enough bytes
  86. // to fill the window.
  87. const lgWin = 16
  88. windowSize := int(math.Pow(2, lgWin))
  89. input := make([]byte, 8*windowSize)
  90. rand.Read(input)
  91. out := bytes.Buffer{}
  92. e := NewWriter(&out, WriterOptions{Quality: 11, LGWin: lgWin})
  93. halfInput := input[:len(input)/2]
  94. in := bytes.NewReader(halfInput)
  95. n, err := io.Copy(e, in)
  96. if err != nil {
  97. t.Errorf("Copy Error: %v", err)
  98. }
  99. // We've fed more data than the sliding window size. Check that some
  100. // compressed data has been output.
  101. if out.Len() == 0 {
  102. t.Errorf("Output length is 0 after %d bytes written", n)
  103. }
  104. if err := e.Close(); err != nil {
  105. t.Errorf("Close Error after copied %d bytes: %v", n, err)
  106. }
  107. if err := checkCompressedData(out.Bytes(), halfInput); err != nil {
  108. t.Error(err)
  109. }
  110. }
  111. func TestEncoderLargeInput(t *testing.T) {
  112. input := make([]byte, 1000000)
  113. rand.Read(input)
  114. out := bytes.Buffer{}
  115. e := NewWriter(&out, WriterOptions{Quality: 5})
  116. in := bytes.NewReader(input)
  117. n, err := io.Copy(e, in)
  118. if err != nil {
  119. t.Errorf("Copy Error: %v", err)
  120. }
  121. if int(n) != len(input) {
  122. t.Errorf("Copy() n=%v, want %v", n, len(input))
  123. }
  124. if err := e.Close(); err != nil {
  125. t.Errorf("Close Error after copied %d bytes: %v", n, err)
  126. }
  127. if err := checkCompressedData(out.Bytes(), input); err != nil {
  128. t.Error(err)
  129. }
  130. }
  131. func TestEncoderFlush(t *testing.T) {
  132. const payload = 32766 // Enough to force encoder emit 2 chunks
  133. input := make([]byte, payload)
  134. rand.Read(input)
  135. out := bytes.Buffer{}
  136. e := NewWriter(&out, WriterOptions{Quality: 5})
  137. in := bytes.NewReader(input)
  138. _, err := io.Copy(e, in)
  139. if err != nil {
  140. t.Fatalf("Copy Error: %v", err)
  141. }
  142. if err := e.Flush(); err != nil {
  143. t.Fatalf("Flush(): %v", err)
  144. }
  145. if out.Len() == 0 {
  146. t.Fatalf("0 bytes written after Flush()")
  147. }
  148. decompressed := make([]byte, payload)
  149. reader := NewReader(bytes.NewReader(out.Bytes()))
  150. n, err := reader.Read(decompressed)
  151. if n >= len(decompressed) || err != nil {
  152. t.Errorf("Expected {<%v, nil}, but got {%v, %v}", len(decompressed), n, err)
  153. }
  154. m, err := reader.Read(decompressed[n:])
  155. n += m
  156. if n != len(decompressed) || err != nil {
  157. t.Errorf("Expected {%v, nil}, but got {%v, %v}", len(decompressed), n, err)
  158. }
  159. reader.Close()
  160. if !bytes.Equal(decompressed, input) {
  161. t.Errorf(""+
  162. "Decompress after flush: %v\n"+
  163. "%q\n"+
  164. "want:\n%q",
  165. err, decompressed, input)
  166. }
  167. if err := e.Close(); err != nil {
  168. t.Errorf("Close(): %v", err)
  169. }
  170. }
  171. type readerWithTimeout struct {
  172. io.ReadCloser
  173. }
  174. func (r readerWithTimeout) Read(p []byte) (int, error) {
  175. type result struct {
  176. n int
  177. err error
  178. }
  179. ch := make(chan result)
  180. go func() {
  181. n, err := r.ReadCloser.Read(p)
  182. ch <- result{n, err}
  183. }()
  184. select {
  185. case result := <-ch:
  186. return result.n, result.err
  187. case <-time.After(5 * time.Second):
  188. return 0, fmt.Errorf("read timed out")
  189. }
  190. }
  191. func TestDecoderStreaming(t *testing.T) {
  192. pr, pw := io.Pipe()
  193. writer := NewWriter(pw, WriterOptions{Quality: 5, LGWin: 20})
  194. reader := readerWithTimeout{NewReader(pr)}
  195. defer func() {
  196. if err := reader.Close(); err != nil {
  197. t.Errorf("reader.Close: %v", err)
  198. }
  199. go ioutil.ReadAll(pr) // swallow the "EOF" token from writer.Close
  200. if err := writer.Close(); err != nil {
  201. t.Errorf("writer.Close: %v", err)
  202. }
  203. }()
  204. ch := make(chan []byte)
  205. errch := make(chan error)
  206. go func() {
  207. for {
  208. segment, ok := <-ch
  209. if !ok {
  210. return
  211. }
  212. if n, err := writer.Write(segment); err != nil || n != len(segment) {
  213. errch <- fmt.Errorf("write=%v,%v, want %v,%v", n, err, len(segment), nil)
  214. return
  215. }
  216. if err := writer.Flush(); err != nil {
  217. errch <- fmt.Errorf("flush: %v", err)
  218. return
  219. }
  220. }
  221. }()
  222. defer close(ch)
  223. segments := [...][]byte{
  224. []byte("first"),
  225. []byte("second"),
  226. []byte("third"),
  227. }
  228. for k, segment := range segments {
  229. t.Run(fmt.Sprintf("Segment%d", k), func(t *testing.T) {
  230. select {
  231. case ch <- segment:
  232. case err := <-errch:
  233. t.Fatalf("write: %v", err)
  234. case <-time.After(5 * time.Second):
  235. t.Fatalf("timed out")
  236. }
  237. wantLen := len(segment)
  238. got := make([]byte, wantLen)
  239. if n, err := reader.Read(got); err != nil || n != wantLen || !bytes.Equal(got, segment) {
  240. t.Fatalf("read[%d]=%q,%v,%v, want %q,%v,%v", k, got, n, err, segment, wantLen, nil)
  241. }
  242. })
  243. }
  244. }
  245. func TestReader(t *testing.T) {
  246. content := bytes.Repeat([]byte("hello world!"), 10000)
  247. encoded, _ := Encode(content, WriterOptions{Quality: 5})
  248. r := NewReader(bytes.NewReader(encoded))
  249. var decodedOutput bytes.Buffer
  250. n, err := io.Copy(&decodedOutput, r)
  251. if err != nil {
  252. t.Fatalf("Copy(): n=%v, err=%v", n, err)
  253. }
  254. if err := r.Close(); err != nil {
  255. t.Errorf("Close(): %v", err)
  256. }
  257. if got := decodedOutput.Bytes(); !bytes.Equal(got, content) {
  258. t.Errorf(""+
  259. "Reader output:\n"+
  260. "%q\n"+
  261. "want:\n"+
  262. "<%d bytes>",
  263. got, len(content))
  264. }
  265. buf := make([]byte, 4)
  266. if _, err := r.Read(buf); err != errReaderClosed {
  267. t.Errorf("Read-after-Close returned %v, expected %v", err, errReaderClosed)
  268. }
  269. }
  270. func TestDecode(t *testing.T) {
  271. content := bytes.Repeat([]byte("hello world!"), 10000)
  272. encoded, _ := Encode(content, WriterOptions{Quality: 5})
  273. decoded, err := Decode(encoded)
  274. if err != nil {
  275. t.Errorf("Decode: %v", err)
  276. }
  277. if !bytes.Equal(decoded, content) {
  278. t.Errorf(""+
  279. "Decode content:\n"+
  280. "%q\n"+
  281. "want:\n"+
  282. "<%d bytes>",
  283. decoded, len(content))
  284. }
  285. }
  286. func TestDecodeFuzz(t *testing.T) {
  287. // Test that the decoder terminates with corrupted input.
  288. content := bytes.Repeat([]byte("hello world!"), 100)
  289. src := rand.NewSource(0)
  290. encoded, err := Encode(content, WriterOptions{Quality: 5})
  291. if err != nil {
  292. t.Fatalf("Encode(<%d bytes>, _) = _, %s", len(content), err)
  293. }
  294. if len(encoded) == 0 {
  295. t.Fatalf("Encode(<%d bytes>, _) produced empty output", len(content))
  296. }
  297. for i := 0; i < 100; i++ {
  298. enc := append([]byte{}, encoded...)
  299. for j := 0; j < 5; j++ {
  300. enc[int(src.Int63())%len(enc)] = byte(src.Int63() % 256)
  301. }
  302. Decode(enc)
  303. }
  304. }
  305. func TestDecodeTrailingData(t *testing.T) {
  306. content := bytes.Repeat([]byte("hello world!"), 100)
  307. encoded, _ := Encode(content, WriterOptions{Quality: 5})
  308. _, err := Decode(append(encoded, 0))
  309. if err == nil {
  310. t.Errorf("Expected 'excessive input' error")
  311. }
  312. }
  313. func TestEncodeDecode(t *testing.T) {
  314. for _, test := range []struct {
  315. data []byte
  316. repeats int
  317. }{
  318. {nil, 0},
  319. {[]byte("A"), 1},
  320. {[]byte("<html><body><H1>Hello world</H1></body></html>"), 10},
  321. {[]byte("<html><body><H1>Hello world</H1></body></html>"), 1000},
  322. } {
  323. t.Logf("case %q x %d", test.data, test.repeats)
  324. input := bytes.Repeat(test.data, test.repeats)
  325. encoded, err := Encode(input, WriterOptions{Quality: 5})
  326. if err != nil {
  327. t.Errorf("Encode: %v", err)
  328. }
  329. // Inputs are compressible, but may be too small to compress.
  330. if maxSize := len(input)/2 + 20; len(encoded) >= maxSize {
  331. t.Errorf(""+
  332. "Encode returned %d bytes, want <%d\n"+
  333. "Encoded=%q",
  334. len(encoded), maxSize, encoded)
  335. }
  336. decoded, err := Decode(encoded)
  337. if err != nil {
  338. t.Errorf("Decode: %v", err)
  339. }
  340. if !bytes.Equal(decoded, input) {
  341. var want string
  342. if len(input) > 320 {
  343. want = fmt.Sprintf("<%d bytes>", len(input))
  344. } else {
  345. want = fmt.Sprintf("%q", input)
  346. }
  347. t.Errorf(""+
  348. "Decode content:\n"+
  349. "%q\n"+
  350. "want:\n"+
  351. "%s",
  352. decoded, want)
  353. }
  354. }
  355. }
  356. func TestEncodeDecodeWithDictionary(t *testing.T) {
  357. q := 5
  358. l := 4096
  359. input := make([]byte, l)
  360. for i := 0; i < l; i++ {
  361. input[i] = byte(i*7 + i*i*5)
  362. }
  363. // use dictionary same as input
  364. pd := NewPreparedDictionary(input, DtRaw, q)
  365. defer pd.Close()
  366. encoded, err := Encode(input, WriterOptions{Quality: q, Dictionary: pd})
  367. if err != nil {
  368. t.Errorf("Encode: %v", err)
  369. }
  370. limit := 20
  371. if len(encoded) > limit {
  372. t.Errorf("Output length exceeds expectations: %d > %d", len(encoded), limit)
  373. }
  374. decoded, err := DecodeWithRawDictionary(encoded, input)
  375. if err != nil {
  376. t.Errorf("Decode: %v", err)
  377. }
  378. if !bytes.Equal(decoded, input) {
  379. var want string
  380. if len(input) > 320 {
  381. want = fmt.Sprintf("<%d bytes>", len(input))
  382. } else {
  383. want = fmt.Sprintf("%q", input)
  384. }
  385. t.Errorf(""+
  386. "Decode content:\n"+
  387. "%q\n"+
  388. "want:\n"+
  389. "%s",
  390. decoded, want)
  391. }
  392. }