octal.scm 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. ;;; Disarchive
  2. ;;; Copyright © 2020, 2021 Timothy Sample <samplet@ngyro.com>
  3. ;;;
  4. ;;; This file is part of Disarchive.
  5. ;;;
  6. ;;; Disarchive is free software: you can redistribute it and/or modify
  7. ;;; it under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation, either version 3 of the License, or
  9. ;;; (at your option) any later version.
  10. ;;;
  11. ;;; Disarchive is distributed in the hope that it will be useful,
  12. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with Disarchive. If not, see <http://www.gnu.org/licenses/>.
  18. (use-modules (disarchive kinds octal)
  19. (disarchive kinds zero-string)
  20. (disarchive serialization)
  21. (quickcheck)
  22. (quickcheck arbitrary)
  23. (quickcheck generator)
  24. (quickcheck property)
  25. (rnrs bytevectors)
  26. (srfi srfi-64)
  27. (tests kinds))
  28. (define (char-set->arbitrary cs)
  29. (arbitrary
  30. (gen (choose-char cs))
  31. (xform (lambda (chr gen)
  32. (generator-variant (char->integer chr) gen)))))
  33. (define char-set:octal (string->char-set "01234567"))
  34. (define $ascii-char
  35. (char-set->arbitrary char-set:ascii))
  36. (define $octal-char
  37. (char-set->arbitrary char-set:octal))
  38. (define $non-octal-ascii-char
  39. (let ((char-set:non-octal (char-set-complement char-set:octal)))
  40. (char-set->arbitrary (char-set-intersection char-set:non-octal
  41. char-set:ascii))))
  42. (configure-quickcheck
  43. ;; Perform 1000 tests per property...
  44. (stop? (lambda (success-count _)
  45. (>= success-count 1000)))
  46. ;; ...over input sizes from 0 to 10.
  47. (size (lambda (test-number)
  48. (if (zero? test-number)
  49. 0
  50. (1+ (quotient test-number 100)))))
  51. ;; XXX: Only give up if we hit a rate of 500 discards per success.
  52. ;; This is because the '$octal' generator is not precise enough.
  53. (give-up? (lambda (success-count discard-count)
  54. (>= (/ discard-count (max 1 success-count)) 500))))
  55. (define (string->octal str)
  56. (decode-octal (string->utf8 str)))
  57. (test-begin "kinds--octal")
  58. (test-equal "Recognizes a zero-padded 1"
  59. (make-padded-octal 1 6 #\0 "")
  60. (string->octal "000001"))
  61. (test-equal "Recognizes a space-padded 1"
  62. (make-padded-octal 1 6 #\space "")
  63. (string->octal " 1"))
  64. (test-equal "Recognizes a zero-padded 0"
  65. (make-padded-octal 0 6 #\0 "")
  66. (string->octal "000000"))
  67. (test-equal "Recognizes a space-padded 0"
  68. (make-padded-octal 0 6 #\space "")
  69. (string->octal " 0"))
  70. (test-equal "Padding defaults to 0"
  71. (make-padded-octal #o123 3 #\0 "")
  72. (string->octal "123"))
  73. (test-equal "Does not treat '111112' as padded"
  74. (make-padded-octal #o111112 6 #\0 "")
  75. (string->octal "111112"))
  76. (test-equal "Recognizes 'abc123' as unstructured"
  77. (make-unstructured-octal #o123 (make-zero-string "abc123" ""))
  78. (string->octal "abc123"))
  79. (test-equal "Recognizes 'abc123xyz' as unstructured"
  80. (make-unstructured-octal #o123 (make-zero-string "abc123xyz" ""))
  81. (string->octal "abc123xyz"))
  82. (test-equal "Recognizes '0x' as unstructured"
  83. (make-unstructured-octal 0 (make-zero-string "0x" ""))
  84. (string->octal "0x"))
  85. (test-assert "[prop] Reading is reversible"
  86. (quickcheck
  87. (property ((bv $bytevector))
  88. (let ((bv* (make-bytevector (bytevector-length bv))))
  89. (encode-octal (decode-octal bv) bv*)
  90. (equal? bv bv*)))))
  91. (test-assert "[prop] Reading produces a valid result"
  92. (quickcheck
  93. (property ((bv $bytevector))
  94. (valid-octal? (decode-octal bv)))))
  95. (test-assert "[prop] The first valid number is recognized"
  96. (quickcheck
  97. (property ((intro ($string $non-octal-ascii-char))
  98. (n $natural)
  99. (outro-delim $non-octal-ascii-char)
  100. (outro ($string $ascii-char)))
  101. (test-when (not (string-index intro #\nul))
  102. (let* ((number (number->string n 8))
  103. (str (string-append intro number (string outro-delim) outro))
  104. (octal (string->octal str)))
  105. (= n (octal-value octal)))))))
  106. (test-assert "[prop] Writing is reversible"
  107. (quickcheck
  108. (property ((octal $octal))
  109. (test-when (valid-octal? octal)
  110. (begin
  111. (equal? octal (decode-octal (encode-octal octal))))))))
  112. (test-assert "[prop] Serializing is reversible"
  113. (quickcheck
  114. (property ((octal $octal))
  115. (test-when (valid-octal? octal)
  116. (equal? octal (serdeser -octal- octal))))))
  117. (test-end "kinds--octal")