zstd.scm 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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. #:level level)
  50. (get)))
  51. (define* (compress-and-decompress data
  52. #:key (level %default-compression-level))
  53. (bytevector=? (let ((compressed (compressed-data data #:level level)))
  54. (call-with-zstd-input-port
  55. (open-bytevector-input-port compressed)
  56. (lambda (port)
  57. (match (get-bytevector-all port)
  58. ((? eof-object?) #vu8())
  59. (bv bv)))))
  60. data))
  61. (define stream-compression-input-size
  62. (@@ (zstd) stream-compression-input-size))
  63. (test-begin "zstd")
  64. (test-assert "empty bytevector"
  65. (compress-and-decompress #vu8()))
  66. (test-assert "random bytevector"
  67. (compress-and-decompress (random-bytevector (+ (random 100000)
  68. (* 20 1024)))))
  69. (test-assert "small bytevector"
  70. (compress-and-decompress (random-bytevector 127)))
  71. (test-assert "one byte"
  72. (compress-and-decompress (random-bytevector 1)))
  73. (test-assert "bytevector of size equal to Zstd internal buffers"
  74. (compress-and-decompress (random-bytevector (stream-compression-input-size))))
  75. (test-assert "bytevector of size equal to Zstd internal buffers -1"
  76. (compress-and-decompress (random-bytevector (1- (stream-compression-input-size)))))
  77. (test-assert "bytevector of size relative to Zstd internal buffers +1"
  78. (compress-and-decompress (random-bytevector (1+ (stream-compression-input-size)))))
  79. (test-assert "bytevector of 1MiB"
  80. (compress-and-decompress (random-bytevector (* 1024 1024))))
  81. (test-assert "bytevector of 1MiB-1"
  82. (compress-and-decompress (random-bytevector (1- (* 1024 1024)))))
  83. (test-assert "bytevector of 1MiB+1"
  84. (compress-and-decompress (random-bytevector (1+ (* 1024 1024)))))
  85. (test-assert "bytevector of 2MiB, all compression levels"
  86. (let ((data (random-bytevector (* 2 1024 1024))))
  87. (every (lambda (level)
  88. (compress-and-decompress data #:level level))
  89. (iota 9 1))))
  90. (test-equal "truncated compressed stream"
  91. '(zstd-error decompress!)
  92. (let* ((compressed (compressed-data (random-bytevector 7777)))
  93. (size (- (bytevector-length compressed) 142))
  94. (truncated (make-bytevector size)))
  95. (bytevector-copy! compressed 0 truncated 0 size)
  96. (catch 'zstd-error
  97. (lambda ()
  98. (call-with-zstd-input-port (open-bytevector-input-port truncated)
  99. get-bytevector-all))
  100. (lambda (key proc . _)
  101. (list key proc)))))
  102. (test-equal "corrupt compressed stream"
  103. '(zstd-error decompress! "Restored data doesn't match checksum")
  104. (let ((compressed (compressed-data (random-bytevector 7777))))
  105. (bytevector-u8-set! compressed 42
  106. (logxor (bytevector-u8-ref compressed 42)
  107. #xff))
  108. (catch 'zstd-error
  109. (lambda ()
  110. (call-with-zstd-input-port (open-bytevector-input-port compressed)
  111. get-bytevector-all))
  112. (lambda (key proc error . _)
  113. (list key proc (error-name error))))))
  114. (test-end)