structs.test 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. ;;;; structs.test --- Structures. -*- mode: scheme; coding: utf-8; -*-
  2. ;;;; Ludovic Courtès <ludo@gnu.org>, 2006-06-12.
  3. ;;;;
  4. ;;;; Copyright (C) 2006, 2007, 2009, 2010, 2012, 2017 Free Software Foundation, Inc.
  5. ;;;;
  6. ;;;; This library is free software; you can redistribute it and/or
  7. ;;;; modify it under the terms of the GNU Lesser General Public
  8. ;;;; License as published by the Free Software Foundation; either
  9. ;;;; version 3 of the License, or (at your option) any later version.
  10. ;;;;
  11. ;;;; This library 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 GNU
  14. ;;;; Lesser General Public License for more details.
  15. ;;;;
  16. ;;;; You should have received a copy of the GNU Lesser General Public
  17. ;;;; License along with this library; if not, write to the Free Software
  18. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. (define-module (test-suite test-structs)
  20. :use-module (test-suite lib))
  21. ;;;
  22. ;;; Struct example taken from the reference manual (by Tom Lord).
  23. ;;;
  24. (define ball-root
  25. (make-vtable (string-append standard-vtable-fields "pw") 0))
  26. (define (make-ball-type ball-color)
  27. (make-struct/no-tail ball-root
  28. (make-struct-layout "pw")
  29. (lambda (ball port)
  30. (format port "#<a ~A ball owned by ~A>"
  31. (color ball)
  32. (owner ball)))
  33. ball-color))
  34. (define (color ball) (struct-ref (struct-vtable ball) vtable-offset-user))
  35. (define (owner ball) (struct-ref ball 0))
  36. (define (set-owner! ball owner) (struct-set! ball 0 owner))
  37. (define red (make-ball-type 'red))
  38. (define green (make-ball-type 'green))
  39. (define (make-ball type owner) (make-struct/no-tail type owner))
  40. ;;;
  41. ;;; Test suite.
  42. ;;;
  43. (with-test-prefix "low-level struct procedures"
  44. (pass-if "constructors"
  45. (and (struct-vtable? ball-root)
  46. (struct-vtable? red)
  47. (struct-vtable? green)))
  48. (pass-if "vtables"
  49. (and (eq? (struct-vtable red) ball-root)
  50. (eq? (struct-vtable green) ball-root)
  51. (eq? (struct-vtable (make-ball red "Bob")) red)
  52. (eq? (struct-vtable ball-root) <standard-vtable>)
  53. ;; end of the vtable tower
  54. (eq? (struct-vtable <standard-vtable>) <standard-vtable>)))
  55. (pass-if "write"
  56. (set-owner! (make-ball red "Bob") "Fred")
  57. #t)
  58. (pass-if "struct-set!"
  59. (let ((ball (make-ball green "Bob")))
  60. (set-owner! ball "Bill")
  61. (string=? (owner ball) "Bill")))
  62. (pass-if "struct-ref"
  63. (let ((ball (make-ball red "Alice")))
  64. (equal? (struct-ref ball 0) "Alice")))
  65. (pass-if "struct-set!"
  66. (let* ((v (make-vtable "pw"))
  67. (s (make-struct/no-tail v))
  68. (r (struct-set! s 0 'a)))
  69. (eq? r
  70. (struct-ref s 0)
  71. 'a)))
  72. (pass-if-exception "struct-ref out-of-range"
  73. exception:out-of-range
  74. (let* ((v (make-vtable "pwpw"))
  75. (s (make-struct/no-tail v 'a 'b)))
  76. (struct-ref s 2)))
  77. (pass-if-exception "struct-set! out-of-range"
  78. exception:out-of-range
  79. (let* ((v (make-vtable "pwpw"))
  80. (s (make-struct/no-tail v 'a 'b)))
  81. (struct-set! s 2 'c))))
  82. (with-test-prefix "equal?"
  83. (pass-if "simple structs"
  84. (let* ((vtable (make-vtable "pw"))
  85. (s1 (make-struct/no-tail vtable "hello"))
  86. (s2 (make-struct/no-tail vtable "hello")))
  87. (equal? s1 s2)))
  88. (pass-if "more complex structs"
  89. (let ((first (make-ball red (string-copy "Bob")))
  90. (second (make-ball red (string-copy "Bob"))))
  91. (equal? first second)))
  92. (pass-if "not-equal?"
  93. (not (or (equal? (make-ball red "Bob") (make-ball green "Bob"))
  94. (equal? (make-ball red "Bob") (make-ball red "Bill"))))))
  95. (with-test-prefix "hash"
  96. (pass-if "simple structs"
  97. (let* ((v (make-vtable "pw"))
  98. (s1 (make-struct/no-tail v "hello"))
  99. (s2 (make-struct/no-tail v "hello")))
  100. (= (hash s1 7777) (hash s2 7777))))
  101. (pass-if "different structs"
  102. (let* ((v (make-vtable "pw"))
  103. (s1 (make-struct/no-tail v "hello"))
  104. (s2 (make-struct/no-tail v "world")))
  105. (or (not (= (hash s1 7777) (hash s2 7777)))
  106. (throw 'unresolved))))
  107. (pass-if "different struct types"
  108. (let* ((v1 (make-vtable "pw"))
  109. (v2 (make-vtable "pw"))
  110. (s1 (make-struct/no-tail v1 "hello"))
  111. (s2 (make-struct/no-tail v2 "hello")))
  112. (or (not (= (hash s1 7777) (hash s2 7777)))
  113. (throw 'unresolved))))
  114. (pass-if "more complex structs"
  115. (let ((s1 (make-ball red (string-copy "Bob")))
  116. (s2 (make-ball red (string-copy "Bob"))))
  117. (= (hash s1 7777) (hash s2 7777))))
  118. (pass-if "struct with weird fields"
  119. (let* ((v (make-vtable "pwuwph"))
  120. (s1 (make-struct/no-tail v "hello" 123 "invisible-secret1"))
  121. (s2 (make-struct/no-tail v "hello" 123 "invisible-secret2")))
  122. (= (hash s1 7777) (hash s2 7777))))
  123. (pass-if "cyclic structs"
  124. (let* ((v (make-vtable "pw"))
  125. (a (make-struct/no-tail v #f))
  126. (b (make-struct/no-tail v a)))
  127. (struct-set! a 0 b)
  128. (and (hash a 7777) (hash b 7777) #t))))
  129. ;;
  130. ;; make-struct
  131. ;;
  132. (with-test-prefix "make-struct"
  133. ;; in guile 1.8.1 and earlier, this caused an error throw out of an
  134. ;; SCM_CRITICAL_SECTION_START / SCM_CRITICAL_SECTION_END, which abort()ed
  135. ;; the program
  136. ;;
  137. (pass-if-exception "wrong type for `u' field" exception:wrong-type-arg
  138. (let* ((vv (make-vtable standard-vtable-fields))
  139. (v (make-struct/no-tail vv (make-struct-layout "uw"))))
  140. (make-struct/no-tail v 'x))))
  141. ;;
  142. ;; make-vtable
  143. ;;
  144. (with-test-prefix "make-vtable"
  145. (pass-if "without printer"
  146. (let* ((vtable (make-vtable "pwpw"))
  147. (struct (make-struct/no-tail vtable 'x 'y)))
  148. (and (eq? 'x (struct-ref struct 0))
  149. (eq? 'y (struct-ref struct 1)))))
  150. (pass-if "with printer"
  151. (let ()
  152. (define (print struct port)
  153. (display "hello" port))
  154. (let* ((vtable (make-vtable "pwpw" print))
  155. (struct (make-struct/no-tail vtable 'x 'y))
  156. (str (call-with-output-string
  157. (lambda (port)
  158. (display struct port)))))
  159. (equal? str "hello")))))