1 ;;;; srfi-9.test --- Test suite for Guile's SRFI-9 functions. -*- scheme -*-
2 ;;;; Martin Grabmueller, 2001-05-10
4 ;;;; Copyright (C) 2001, 2006, 2007, 2010, 2011, 2012 Free Software Foundation, Inc.
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.
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.
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
20 (define-module (test-suite test-numbers)
21 #:use-module (test-suite lib)
22 #:use-module ((system base compile) #:select (compile))
23 #:use-module (srfi srfi-26)
24 #:use-module (srfi srfi-9)
25 #:use-module (srfi srfi-9 gnu))
28 (define-record-type :qux (make-qux) qux?)
30 (define-record-type :foo (make-foo x) foo?
35 (define-record-type :bar (make-bar i j) bar?
39 (define f (make-foo 1))
42 (define b (make-bar 123 456))
44 (with-test-prefix "constructor"
46 ;; Constructors are defined using `define-integrable', meaning that direct
47 ;; calls as in `(make-foo)' lead to a compile-time psyntax error, hence the
50 (pass-if-exception "foo 0 args (inline)" exception:syntax-pattern-unmatched
51 (compile '(make-foo) #:env (current-module)))
52 (pass-if-exception "foo 2 args (inline)" exception:syntax-pattern-unmatched
53 (compile '(make-foo 1 2) #:env (current-module)))
55 (pass-if-exception "foo 0 args" exception:wrong-num-args
56 (let ((make-foo make-foo))
58 (pass-if-exception "foo 2 args" exception:wrong-num-args
59 (let ((make-foo make-foo))
62 (with-test-prefix "predicate"
66 (pass-if "fail wrong record type"
68 (pass-if "fail number"
71 (with-test-prefix "getter"
78 (pass-if-exception "foo-x on number" exception:wrong-type-arg
80 (pass-if-exception "foo-y on number" exception:wrong-type-arg
83 ;; prior to guile 1.6.9 and 1.8.1 this wan't enforced
84 (pass-if-exception "foo-x on bar" exception:wrong-type-arg
86 (pass-if-exception "foo-y on bar" exception:wrong-type-arg
89 (with-test-prefix "setter"
95 (pass-if-exception "set-foo-y! on number" exception:wrong-type-arg
98 ;; prior to guile 1.6.9 and 1.8.1 this wan't enforced
99 (pass-if-exception "set-foo-y! on bar" exception:wrong-type-arg
102 (with-test-prefix "functional setters"
105 (let ((s (make-foo (make-bar 1 2))))
106 (and (equal? (set-field (foo-x bar-j) s 3)
107 (make-foo (make-bar 1 3)))
108 (equal? (set-field (foo-z) s 'bar)
109 (let ((s2 (make-foo (make-bar 1 2))))
112 (equal? s (make-foo (make-bar 1 2))))))
114 (pass-if-exception "set-field on wrong struct type" exception:wrong-type-arg
115 (let ((s (make-bar (make-foo 5) 2)))
116 (set-field (foo-x bar-j) s 3)))
118 (pass-if-exception "set-field on number" exception:wrong-type-arg
119 (set-field (foo-x bar-j) 4 3))
121 (pass-if-equal "set-field with unknown first getter"
122 '(syntax-error set-fields "unknown getter"
123 (set-field (blah) s 3)
127 (compile '(let ((s (make-bar (make-foo 5) 2)))
128 (set-field (blah) s 3))
129 #:env (current-module))
131 (lambda (key whom what src form subform)
132 (list key whom what form subform))))
134 (pass-if-equal "set-field with unknown second getter"
135 '(syntax-error set-fields "unknown getter"
136 (set-field (bar-j blah) s 3)
140 (compile '(let ((s (make-bar (make-foo 5) 2)))
141 (set-field (bar-j blah) s 3))
142 #:env (current-module))
144 (lambda (key whom what src form subform)
145 (list key whom what form subform))))
147 (pass-if "set-fields"
148 (let ((s (make-foo (make-bar 1 2))))
149 (and (equal? (set-field (foo-x bar-j) s 3)
150 (make-foo (make-bar 1 3)))
151 (equal? (set-fields s
154 (let ((s2 (make-foo (make-bar 1 3))))
157 (equal? s (make-foo (make-bar 1 2))))))
159 (pass-if-exception "set-fields on wrong struct type" exception:wrong-type-arg
160 (let ((s (make-bar (make-foo 5) 2)))
165 (pass-if-exception "set-fields on number" exception:wrong-type-arg
170 (pass-if-equal "set-fields with unknown first getter"
171 '(syntax-error set-fields "unknown getter"
172 (set-fields s ((bar-i foo-x) 1) ((blah) 3))
176 (compile '(let ((s (make-bar (make-foo 5) 2)))
177 (set-fields s ((bar-i foo-x) 1) ((blah) 3)))
178 #:env (current-module))
180 (lambda (key whom what src form subform)
181 (list key whom what form subform))))
183 (pass-if-equal "set-fields with unknown second getter"
184 '(syntax-error set-fields "unknown getter"
185 (set-fields s ((bar-i foo-x) 1) ((blah) 3))
189 (compile '(let ((s (make-bar (make-foo 5) 2)))
190 (set-fields s ((bar-i foo-x) 1) ((blah) 3)))
191 #:env (current-module))
193 (lambda (key whom what src form subform)
194 (list key whom what form subform))))
196 (pass-if-equal "set-fields with duplicate field path"
197 '(syntax-error set-fields "duplicate field path"
205 (compile '(let ((s (make-bar (make-foo 5) 2)))
210 #:env (current-module))
212 (lambda (key whom what src form subform)
213 (list key whom what form subform))))
215 (pass-if-equal "set-fields with one path as a prefix of another"
216 '(syntax-error set-fields
217 "one field path is a prefix of another"
225 (compile '(let ((s (make-bar (make-foo 5) 2)))
230 #:env (current-module))
232 (lambda (key whom what src form subform)
233 (list key whom what form subform)))))
235 (with-test-prefix "side-effecting arguments"
239 (and (foo? (begin (set! x (+ x 1)) f))
242 (with-test-prefix "non-toplevel"
244 (define-record-type :frotz (make-frotz a b) frotz?
245 (a frotz-a) (b frotz-b set-frotz-b!))
247 (pass-if "construction"
248 (let ((frotz (make-frotz 1 2)))
249 (and (= (frotz-a frotz) 1)
250 (= (frotz-b frotz) 2))))
252 (with-test-prefix "functional setters"
254 (define-record-type foo (make-foo x) foo?
257 (z foo-z set-foo-z!))
259 (define-record-type :bar (make-bar i j) bar?
261 (j bar-j set-bar-j!))
264 (let ((s (make-foo (make-bar 1 2))))
265 (and (equal? (set-field (foo-x bar-j) s 3)
266 (make-foo (make-bar 1 3)))
267 (equal? (set-field (foo-z) s 'bar)
268 (let ((s2 (make-foo (make-bar 1 2))))
271 (equal? s (make-foo (make-bar 1 2)))))))
273 (pass-if "set-fields"
275 (let ((s (make-foo (make-bar 1 2))))
276 (and (equal? (set-field (foo-x bar-j) s 3)
277 (make-foo (make-bar 1 3)))
278 (equal? (set-fields s
281 (let ((s2 (make-foo (make-bar 1 3))))
284 (equal? s (make-foo (make-bar 1 2))))))))
287 (define-immutable-record-type :baz
294 (define-immutable-record-type :address
295 (make-address street city country)
297 (street address-street)
299 (country address-country))
301 (define-immutable-record-type :person
302 (make-person age email address)
306 (address person-address))
308 (with-test-prefix "define-immutable-record-type"
311 (let ((b (make-baz 1 2 3)))
316 (pass-if "get non-inlined"
317 (let ((b (make-baz 1 2 3)))
318 (equal? (map (cute apply <> (list b))
319 (list baz-x baz-y baz-z))
323 (let* ((b0 (make-baz 1 2 3))
324 (b1 (set-baz-x b0 11))
325 (b2 (set-baz-y b1 22))
326 (b3 (set-baz-z b2 33)))
327 (and (= (baz-x b0) 1)
328 (= (baz-x b1) 11) (= (baz-x b2) 11) (= (baz-x b3) 11)
329 (= (baz-y b0) 2) (= (baz-y b1) 2)
330 (= (baz-y b2) 22) (= (baz-y b3) 22)
331 (= (baz-z b0) 3) (= (baz-z b1) 3) (= (baz-z b2) 3)
334 (pass-if "set non-inlined"
335 (let ((set (compose (cut set-baz-x <> 1)
337 (cut set-baz-z <> 3))))
338 (equal? (set (make-baz 0 0 0)) (make-baz 1 2 3))))
341 (let ((p (make-person 30 "foo@example.com"
342 (make-address "Foo" "Paris" "France"))))
343 (and (equal? (set-field (person-address address-street) p "Bar")
344 (make-person 30 "foo@example.com"
345 (make-address "Bar" "Paris" "France")))
346 (equal? (set-field (person-email) p "bar@example.com")
347 (make-person 30 "bar@example.com"
348 (make-address "Foo" "Paris" "France")))
349 (equal? p (make-person 30 "foo@example.com"
350 (make-address "Foo" "Paris" "France"))))))
352 (pass-if "set-fields"
353 (let ((p (make-person 30 "foo@example.com"
354 (make-address "Foo" "Paris" "France"))))
355 (and (equal? (set-fields p
356 ((person-email) "bar@example.com")
357 ((person-address address-country) "Catalonia")
358 ((person-address address-city) "Barcelona"))
359 (make-person 30 "bar@example.com"
360 (make-address "Foo" "Barcelona" "Catalonia")))
361 (equal? (set-fields p
362 ((person-email) "bar@example.com")
364 (make-person 20 "bar@example.com"
365 (make-address "Foo" "Paris" "France")))
366 (equal? p (make-person 30 "foo@example.com"
367 (make-address "Foo" "Paris" "France"))))))
369 (with-test-prefix "non-toplevel"
373 (define-immutable-record-type bar
380 (let ((b (make-bar 1 2 3)))
385 (pass-if "get non-inlined"
387 (define-immutable-record-type bar
394 (let ((b (make-bar 1 2 3)))
395 (equal? (map (cute apply <> (list b))
396 (list bar-x bar-y bar-z))
401 (define-immutable-record-type bar
408 (let* ((b0 (make-bar 1 2 3))
409 (b1 (set-bar-x b0 11))
410 (b2 (set-bar-y b1 22))
411 (b3 (set-bar-z b2 33)))
412 (and (= (bar-x b0) 1)
413 (= (bar-x b1) 11) (= (bar-x b2) 11) (= (bar-x b3) 11)
414 (= (bar-y b0) 2) (= (bar-y b1) 2)
415 (= (bar-y b2) 22) (= (bar-y b3) 22)
416 (= (bar-z b0) 3) (= (bar-z b1) 3) (= (bar-z b2) 3)
417 (= (bar-z b3) 33)))))
419 (pass-if "set non-inlined"
421 (define-immutable-record-type bar
428 (let ((set (compose (cut set-bar-x <> 1)
430 (cut set-bar-z <> 3))))
431 (equal? (set (make-bar 0 0 0)) (make-bar 1 2 3)))))
435 (define-immutable-record-type address
436 (make-address street city country)
438 (street address-street)
440 (country address-country))
442 (define-immutable-record-type :person
443 (make-person age email address)
447 (address person-address))
449 (let ((p (make-person 30 "foo@example.com"
450 (make-address "Foo" "Paris" "France"))))
451 (and (equal? (set-field (person-address address-street) p "Bar")
452 (make-person 30 "foo@example.com"
453 (make-address "Bar" "Paris" "France")))
454 (equal? (set-field (person-email) p "bar@example.com")
455 (make-person 30 "bar@example.com"
456 (make-address "Foo" "Paris" "France")))
457 (equal? p (make-person 30 "foo@example.com"
458 (make-address "Foo" "Paris" "France")))))))
460 (pass-if "set-fields"
462 (define-immutable-record-type address
463 (make-address street city country)
465 (street address-street)
467 (country address-country))
469 (define-immutable-record-type :person
470 (make-person age email address)
474 (address person-address))
476 (let ((p (make-person 30 "foo@example.com"
477 (make-address "Foo" "Paris" "France"))))
478 (and (equal? (set-fields p
479 ((person-email) "bar@example.com")
480 ((person-address address-country) "Catalonia")
481 ((person-address address-city) "Barcelona"))
482 (make-person 30 "bar@example.com"
483 (make-address "Foo" "Barcelona" "Catalonia")))
484 (equal? (set-fields p
485 ((person-email) "bar@example.com")
487 (make-person 20 "bar@example.com"
488 (make-address "Foo" "Paris" "France")))
489 (equal? p (make-person 30 "foo@example.com"
490 (make-address "Foo" "Paris" "France")))))))
492 (pass-if-equal "set-fields with unknown first getter"
493 '(syntax-error set-fields "unknown getter"
494 (set-fields s ((bar-i foo-x) 1) ((blah) 3))
499 (define-immutable-record-type foo
506 (define-immutable-record-type :bar
512 (let ((s (make-bar (make-foo 5) 2)))
513 (set-fields s ((bar-i foo-x) 1) ((blah) 3))))
514 #:env (current-module))
516 (lambda (key whom what src form subform)
517 (list key whom what form subform))))
519 (pass-if-equal "set-fields with unknown second getter"
520 '(syntax-error set-fields "unknown getter"
521 (set-fields s ((bar-i foo-x) 1) ((blah) 3))
526 (define-immutable-record-type foo
533 (define-immutable-record-type :bar
539 (let ((s (make-bar (make-foo 5) 2)))
540 (set-fields s ((bar-i foo-x) 1) ((blah) 3))))
541 #:env (current-module))
543 (lambda (key whom what src form subform)
544 (list key whom what form subform))))
546 (pass-if-equal "set-fields with duplicate field path"
547 '(syntax-error set-fields "duplicate field path"
556 (define-immutable-record-type foo
563 (define-immutable-record-type :bar
569 (let ((s (make-bar (make-foo 5) 2)))
574 #:env (current-module))
576 (lambda (key whom what src form subform)
577 (list key whom what form subform))))
579 (pass-if-equal "set-fields with one path as a prefix of another"
580 '(syntax-error set-fields
581 "one field path is a prefix of another"
590 (define-immutable-record-type foo
597 (define-immutable-record-type :bar
603 (let ((s (make-bar (make-foo 5) 2)))
608 #:env (current-module))
610 (lambda (key whom what src form subform)
611 (list key whom what form subform))))))
614 (with-test-prefix "record type definition error reporting"
616 (pass-if-equal "invalid type name"
617 '(syntax-error define-immutable-record-type
619 (define-immutable-record-type
627 (compile '(define-immutable-record-type
632 #:env (current-module))
634 (lambda (key whom what src form subform)
635 (list key whom what form subform))))
637 (pass-if-equal "invalid constructor spec"
638 '(syntax-error define-immutable-record-type
639 "invalid constructor spec"
640 (define-immutable-record-type :foobar
648 (compile '(define-immutable-record-type :foobar
653 #:env (current-module))
655 (lambda (key whom what src form subform)
656 (list key whom what form subform))))
658 (pass-if-equal "invalid predicate name"
659 '(syntax-error define-immutable-record-type
660 "expected predicate name"
661 (define-immutable-record-type :foobar
668 (compile '(define-immutable-record-type :foobar
672 #:env (current-module))
674 (lambda (key whom what src form subform)
675 (list key whom what form subform))))
677 (pass-if-equal "invalid field spec"
678 '(syntax-error define-record-type
680 (define-record-type :foobar
688 (compile '(define-record-type :foobar
693 #:env (current-module))
695 (lambda (key whom what src form subform)
696 (list key whom what form subform))))
698 (pass-if-equal "unknown field in constructor spec"
699 '(syntax-error define-record-type
700 "unknown field in constructor spec"
701 (define-record-type :foobar
709 (compile '(define-record-type :foobar
714 #:env (current-module))
716 (lambda (key whom what src form subform)
717 (list key whom what form subform)))))
719 (with-test-prefix "record compatibility"
722 (record? (make-foo 1)))
724 (pass-if "record-constructor"
725 (equal? ((record-constructor :foo) 1)
730 ;;; eval: (put 'set-fields 'scheme-indent-function 1)