zstd.scm 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. ;;; Guile-zstd --- GNU Guile bindings to the zstd compression library.
  2. ;;; Copyright © 2019 Pierre Neidhardt <mail@ambrevar.xyz>
  3. ;;; Copyright © 2020 Mathieu Othacehe <othacehe@gnu.org>
  4. ;;; Copyright © 2020 Ludovic Courtès <ludo@gnu.org>
  5. ;;;
  6. ;;; This file is part of Guile-zstd.
  7. ;;;
  8. ;;; Guile-zstd is free software; you can redistribute it and/or modify it
  9. ;;; under the terms of the GNU General Public License as published by
  10. ;;; the Free Software Foundation; either version 3 of the License, or (at
  11. ;;; your option) any later version.
  12. ;;;
  13. ;;; Guile-zstd is distributed in the hope that it will be useful, but
  14. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ;;; GNU General Public License for more details.
  17. ;;;
  18. ;;; You should have received a copy of the GNU General Public License
  19. ;;; along with Guile-zstd. If not, see <http://www.gnu.org/licenses/>.
  20. (define-module (test-zstd)
  21. #:use-module (zstd)
  22. #:use-module (srfi srfi-1)
  23. #:use-module (srfi srfi-11)
  24. #:use-module (srfi srfi-64)
  25. #:use-module (rnrs bytevectors)
  26. #:use-module (rnrs io ports)
  27. #:use-module (ice-9 match))
  28. (define (random-seed)
  29. (logxor (getpid) (car (gettimeofday))))
  30. (define %seed
  31. (let ((seed (random-seed)))
  32. (format (current-error-port) "random seed for tests: ~a~%"
  33. seed)
  34. (seed->random-state seed)))
  35. (define (random-bytevector n)
  36. "Return a random bytevector of N bytes."
  37. (let ((bv (make-bytevector n)))
  38. (let loop ((i 0))
  39. (if (< i n)
  40. (begin
  41. (bytevector-u8-set! bv i (random 256 %seed))
  42. (loop (1+ i)))
  43. bv))))
  44. (define* (compressed-data data #:key (level %default-compression-level))
  45. (let-values (((port get) (open-bytevector-output-port)))
  46. (call-with-zstd-output-port port
  47. (lambda (port)
  48. (put-bytevector port data)))
  49. (get)))
  50. (define* (compress-and-decompress data
  51. #:key (level %default-compression-level))
  52. (bytevector=? (let ((compressed (compressed-data data #:level level)))
  53. (call-with-zstd-input-port
  54. (open-bytevector-input-port compressed)
  55. (lambda (port)
  56. (match (get-bytevector-all port)
  57. ((? eof-object?) #vu8())
  58. (bv bv)))))
  59. data))
  60. (define stream-compression-input-size
  61. (@@ (zstd) stream-compression-input-size))
  62. (test-begin "zstd")
  63. (test-assert "empty bytevector"
  64. (compress-and-decompress #vu8()))
  65. (test-assert "random bytevector"
  66. (compress-and-decompress (random-bytevector (+ (random 100000)
  67. (* 20 1024)))))
  68. (test-assert "small bytevector"
  69. (compress-and-decompress (random-bytevector 127)))
  70. (test-assert "one byte"
  71. (compress-and-decompress (random-bytevector 1)))
  72. (test-assert "bytevector of size equal to Zstd internal buffers"
  73. (compress-and-decompress (random-bytevector (stream-compression-input-size))))
  74. (test-assert "bytevector of size equal to Zstd internal buffers -1"
  75. (compress-and-decompress (random-bytevector (1- (stream-compression-input-size)))))
  76. (test-assert "bytevector of size relative to Zstd internal buffers +1"
  77. (compress-and-decompress (random-bytevector (1+ (stream-compression-input-size)))))
  78. (test-assert "bytevector of 1MiB"
  79. (compress-and-decompress (random-bytevector (* 1024 1024))))
  80. (test-assert "bytevector of 1MiB-1"
  81. (compress-and-decompress (random-bytevector (1- (* 1024 1024)))))
  82. (test-assert "bytevector of 1MiB+1"
  83. (compress-and-decompress (random-bytevector (1+ (* 1024 1024)))))
  84. (test-assert "bytevector of 2MiB, all compression levels"
  85. (let ((data (random-bytevector (* 2 1024 1024))))
  86. (every (lambda (level)
  87. (compress-and-decompress data #:level level))
  88. (iota 9 1))))
  89. (test-equal "truncated compressed stream"
  90. '(zstd-error decompress!)
  91. (let* ((compressed (compressed-data (random-bytevector 7777)))
  92. (size (- (bytevector-length compressed) 142))
  93. (truncated (make-bytevector size)))
  94. (bytevector-copy! compressed 0 truncated 0 size)
  95. (catch 'zstd-error
  96. (lambda ()
  97. (call-with-zstd-input-port (open-bytevector-input-port truncated)
  98. get-bytevector-all))
  99. (lambda (key proc . _)
  100. (list key proc)))))
  101. (test-equal "corrupt compressed stream"
  102. '(zstd-error decompress! "Restored data doesn't match checksum")
  103. (let ((compressed (compressed-data (random-bytevector 7777))))
  104. (bytevector-u8-set! compressed 42
  105. (logxor (bytevector-u8-ref compressed 42)
  106. #xff))
  107. (catch 'zstd-error
  108. (lambda ()
  109. (call-with-zstd-input-port (open-bytevector-input-port compressed)
  110. get-bytevector-all))
  111. (lambda (key proc error . _)
  112. (list key proc (error-name error))))))
  113. (test-end)