records.test 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. ;;;; records.test --- Test suite for Guile's records. -*- mode: scheme; coding: utf-8 -*-
  2. ;;;;
  3. ;;;; Copyright (C) 2009-2010, 2019 Free Software Foundation, Inc.
  4. ;;;;
  5. ;;;; This library is free software; you can redistribute it and/or
  6. ;;;; modify it under the terms of the GNU Lesser General Public
  7. ;;;; License as published by the Free Software Foundation; either
  8. ;;;; version 3 of the License, or (at your option) any later version.
  9. ;;;;
  10. ;;;; This library is distributed in the hope that it will be useful,
  11. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. ;;;; Lesser General Public License for more details.
  14. ;;;;
  15. ;;;; You should have received a copy of the GNU Lesser General Public
  16. ;;;; License along with this library; if not, write to the Free Software
  17. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. (define-module (test-records)
  19. #:use-module (ice-9 format)
  20. #:use-module (test-suite lib))
  21. ;; ascii names and symbols, custom printer
  22. (define rtd-foo (make-record-type 'foo '(x y)
  23. (lambda (s p)
  24. (display "#<it is a foo>" p))))
  25. (define make-foo (record-constructor rtd-foo))
  26. (define foo? (record-predicate rtd-foo))
  27. (define get-foo-x (record-accessor rtd-foo 'x))
  28. (define get-foo-y (record-accessor rtd-foo 'y))
  29. (define set-foo-x! (record-modifier rtd-foo 'x))
  30. (define set-foo-y! (record-modifier rtd-foo 'y))
  31. ;; non-Latin-1 names and symbols, default printer
  32. (define rtd-fŏŏ (make-record-type 'fŏŏ '(x ȳ)))
  33. (define make-fŏŏ (record-constructor rtd-fŏŏ))
  34. (define fŏŏ? (record-predicate rtd-fŏŏ))
  35. (define get-fŏŏ-x (record-accessor rtd-fŏŏ 'x))
  36. (define get-fŏŏ-ȳ (record-accessor rtd-fŏŏ 'ȳ))
  37. (define set-fŏŏ-x! (record-modifier rtd-fŏŏ 'x))
  38. (define set-fŏŏ-ȳ! (record-modifier rtd-fŏŏ 'ȳ))
  39. (with-test-prefix "records"
  40. (with-test-prefix "constructor"
  41. (pass-if-exception "0 args (2 required)" exception:wrong-num-args
  42. (make-foo))
  43. (pass-if-exception "1 arg (2 required)" exception:wrong-num-args
  44. (make-foo 1))
  45. (pass-if "2 args (2 required)" exception:wrong-num-args
  46. (foo? (make-foo 1 2)))
  47. (pass-if "non-latin-1" exception:wrong-num-args
  48. (fŏŏ? (make-fŏŏ 1 2))))
  49. (with-test-prefix "modifier and getter"
  50. (pass-if "set"
  51. (let ((r (make-foo 1 2)))
  52. (set-foo-x! r 3)
  53. (eqv? (get-foo-x r) 3)))
  54. (pass-if "set 2"
  55. (let ((r (make-fŏŏ 1 2)))
  56. (set-fŏŏ-ȳ! r 3)
  57. (eqv? (get-fŏŏ-ȳ r) 3))))
  58. (with-test-prefix "record type name"
  59. (pass-if "foo"
  60. (string=? "foo" (symbol->string (record-type-name rtd-foo))))
  61. (pass-if "fŏŏ"
  62. (string=? "fŏŏ" (symbol->string (record-type-name rtd-fŏŏ)))))
  63. (with-test-prefix "printer"
  64. (pass-if "foo"
  65. (string=? "#<it is a foo>"
  66. (with-output-to-string
  67. (lambda () (display (make-foo 1 2))))))
  68. (pass-if "fŏŏ"
  69. (with-locale "en_US.utf8"
  70. (string-prefix? "#<fŏŏ"
  71. (with-output-to-string
  72. (lambda () (display (make-fŏŏ 1 2))))))))
  73. (with-test-prefix "subtyping"
  74. (let ()
  75. (define a (make-record-type 'a '(s t)))
  76. (define b (make-record-type 'b '(u v) #:extensible? #t))
  77. (define c (make-record-type 'c '(w x) #:parent b))
  78. (pass-if (not (record-type-extensible? a)))
  79. (pass-if (record-type-extensible? b))
  80. (pass-if (not (record-type-extensible? c)))
  81. (pass-if-exception "subtyping final: a" '(misc-error . "final")
  82. (make-record-type 'd '(y x) #:parent a))
  83. (pass-if-exception "subtyping final: c" '(misc-error . "final")
  84. (make-record-type 'd '(y x) #:parent c))
  85. (pass-if-equal "fields of subtype" '(u v w x)
  86. (record-type-fields c))
  87. (pass-if "final predicate: a? a"
  88. ((record-predicate a) ((record-constructor a) 1 2)))
  89. (pass-if "final predicate: a? b"
  90. (not ((record-predicate a) ((record-constructor b) 1 2))))
  91. (pass-if "non-final predicate: b? a"
  92. (not ((record-predicate b) ((record-constructor a) 1 2))))
  93. (pass-if "non-final predicate: b? b"
  94. ((record-predicate b) ((record-constructor b) 1 2)))
  95. (pass-if "non-final predicate: b? c"
  96. ((record-predicate b) ((record-constructor c) 1 2 3 4)))
  97. (pass-if "final predicate: c? a"
  98. (not ((record-predicate c) ((record-constructor a) 1 2))))
  99. (pass-if "final predicate: c? b"
  100. (not ((record-predicate c) ((record-constructor b) 1 2))))
  101. (pass-if "final predicate: c? c"
  102. ((record-predicate c) ((record-constructor c) 1 2 3 4)))
  103. (pass-if-equal "b accessor on b" 1
  104. ((record-accessor b 'u) ((record-constructor b) 1 2)))
  105. (pass-if-equal "b accessor on c" 1
  106. ((record-accessor b 'u) ((record-constructor c) 1 2 3 4)))
  107. (pass-if-equal "c accessor on c" 3
  108. ((record-accessor c 'w) ((record-constructor c) 1 2 3 4)))))
  109. (with-test-prefix "prefab types"
  110. (let ()
  111. (define uid 'ANhUpf2WpNnF2XIVLxq@IkavIc5wbqe8)
  112. (define a (make-record-type 'a '(s t) #:uid uid))
  113. (define b (make-record-type 'b '() #:extensible? #t))
  114. (pass-if (eq? a (make-record-type 'a '(s t) #:uid uid)))
  115. (pass-if-exception "different name" '(misc-error . "incompatible")
  116. (make-record-type 'b '(s t) #:uid uid))
  117. (pass-if-exception "different fields" '(misc-error . "incompatible")
  118. (make-record-type 'a '(u v) #:uid uid))
  119. (pass-if-exception "fewer fields" '(misc-error . "incompatible")
  120. (make-record-type 'a '(s) #:uid uid))
  121. (pass-if-exception "more fields" '(misc-error . "incompatible")
  122. (make-record-type 'a '(s t u) #:uid uid))
  123. (pass-if-exception "adding a parent" '(misc-error . "incompatible")
  124. (make-record-type 'a '(s t) #:parent b #:uid uid))
  125. (pass-if-exception "specifying a printer" '(misc-error . "incompatible")
  126. (make-record-type 'a '(s t) pk #:uid uid))
  127. (pass-if-exception "non-final" '(misc-error . "incompatible")
  128. (make-record-type 'a '(s t) #:extensible? #t #:uid uid))))
  129. (with-test-prefix "opaque types"
  130. (let ()
  131. (define a (make-record-type 'a '() #:extensible? #t #:opaque? #t))
  132. (define b (make-record-type 'b '()))
  133. (define c (make-record-type 'c '() #:parent a))
  134. (pass-if (record-type-opaque? a))
  135. (pass-if (not (record-type-opaque? b)))
  136. (pass-if (record-type-opaque? c))
  137. (pass-if-exception "non-opaque" '(misc-error . "opaque")
  138. (make-record-type 'd '() #:opaque? #f #:parent a))))
  139. (with-test-prefix "immutable fields"
  140. (let ()
  141. (define a (make-record-type 'a '(s t (mutable u) (immutable v))
  142. #:extensible? #t))
  143. (define b (make-record-type 'b '(w (immutable x)) #:parent a))
  144. (pass-if-exception "bad field" '(misc-error . "field")
  145. (make-record-type 'a '("foo")))
  146. (pass-if-exception "bad field" '(misc-error . "field")
  147. (make-record-type 'a '((mutable u x))))
  148. (pass-if-exception "bad field" '(misc-error . "field")
  149. (make-record-type 'a '((qux u))))
  150. (pass-if-equal (record-type-mutable-fields a) #b0111)
  151. (pass-if-equal (record-type-mutable-fields b) #b010111)
  152. (pass-if (procedure? (record-modifier a 's)))
  153. (pass-if (procedure? (record-modifier a 't)))
  154. (pass-if (procedure? (record-modifier a 'u)))
  155. (pass-if-exception "immutable" '(misc-error . "immutable")
  156. (record-modifier a 'v))
  157. (pass-if (procedure? (record-modifier b 's)))
  158. (pass-if (procedure? (record-modifier b 't)))
  159. (pass-if (procedure? (record-modifier b 'u)))
  160. (pass-if-exception "immutable" '(misc-error . "immutable")
  161. (record-modifier b 'v))
  162. (pass-if (procedure? (record-modifier b 'w)))
  163. (pass-if-exception "immutable" '(misc-error . "immutable")
  164. (record-modifier b 'x)))))