1 ;;;; srfi-1.test --- Test suite for Guile's SRFI-1 functions. -*- scheme -*-
3 ;;;; Copyright 2003, 2004 Free Software Foundation, Inc.
5 ;;;; This program is free software; you can redistribute it and/or modify
6 ;;;; it under the terms of the GNU General Public License as published by
7 ;;;; the Free Software Foundation; either version 2, or (at your option)
8 ;;;; any later version.
10 ;;;; This program 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
13 ;;;; GNU General Public License for more details.
15 ;;;; You should have received a copy of the GNU General Public License
16 ;;;; along with this software; see the file COPYING. If not, write to
17 ;;;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 ;;;; Boston, MA 02111-1307 USA
20 (use-modules (srfi srfi-1)
23 (define (ref-delete x lst . proc)
24 "Reference implemenation of srfi-1 `delete'."
25 (set! proc (if (null? proc) equal? (car proc)))
30 (if (not (proc x (car lst)))
31 (set! ret (cons (car lst) ret)))))
33 (define (ref-delete-duplicates lst . proc)
34 "Reference implemenation of srfi-1 `delete-duplicates'."
35 (set! proc (if (null? proc) equal? (car proc)))
41 (let ((elem (car lst)))
42 (set! keep (cons elem keep))
43 (set! lst (ref-delete elem lst proc))))))
50 (with-test-prefix "alist-copy"
52 ;; return a list which is the pairs making up alist A, the spine and cells
53 (define (alist-pairs a)
57 (more (cdr a) (cons a result))
60 ;; return a list of the elements common to lists X and Y, compared with eq?
61 (define (common-elements x y)
65 (cons (car x) (common-elements (cdr x) y))
66 (common-elements (cdr x) y))))
68 ;; validate an alist-copy of OLD to NEW
69 ;; lists must be equal, and must comprise new pairs
70 (define (valid-alist-copy? old new)
72 (null? (common-elements old new))))
74 (pass-if-exception "too few args" exception:wrong-num-args
77 (pass-if-exception "too many args" exception:wrong-num-args
81 (pass-if old (valid-alist-copy? old (alist-copy old))))
83 (let ((old '((1 . 2))))
84 (pass-if old (valid-alist-copy? old (alist-copy old))))
86 (let ((old '((1 . 2) (3 . 4))))
87 (pass-if old (valid-alist-copy? old (alist-copy old))))
89 (let ((old '((1 . 2) (3 . 4) (5 . 6))))
90 (pass-if old (valid-alist-copy? old (alist-copy old)))))
96 (with-test-prefix "alist-delete"
98 (pass-if "equality call arg order"
100 (alist-delete 'k '((ak . 123))
102 (if (and (eq? k 'k) (eq? ak 'ak))
106 (pass-if "delete keys greater than 5"
107 (equal? '((4 . x) (5 . y))
108 (alist-delete 5 '((4 . x) (5 . y) (6 . z)) <)))
111 (equal? '() (alist-delete 'x '())))
114 (equal? '() (alist-delete 'y '((y . 1)))))
117 (equal? '((n . 1)) (alist-delete 'y '((n . 1)))))
120 (equal? '() (alist-delete 'y '((y . 1) (y . 2)))))
123 (equal? '((n . 1)) (alist-delete 'y '((n . 1) (y . 2)))))
126 (equal? '((n . 2)) (alist-delete 'y '((y . 1) (n . 2)))))
129 (equal? '((n . 1) (n . 2)) (alist-delete 'y '((n . 1) (n . 2)))))
132 (equal? '() (alist-delete 'y '((y . 1) (y . 2) (y . 3)))))
135 (equal? '((n . 1)) (alist-delete 'y '((n . 1) (y . 2) (y . 3)))))
138 (equal? '((n . 2)) (alist-delete 'y '((y . 1) (n . 2) (y . 3)))))
141 (equal? '((n . 1) (n . 2)) (alist-delete 'y '((n . 1) (n . 2) (y . 3)))))
144 (equal? '( (n . 3)) (alist-delete 'y '((y . 1) (y . 2) (n . 3)))))
147 (equal? '((n . 1) (n . 3)) (alist-delete 'y '((n . 1) (y . 2) (n . 3)))))
150 (equal? '((n . 2) (n . 3)) (alist-delete 'y '((y . 1) (n . 2) (n . 3)))))
153 (equal? '((n . 1) (n . 2) (n . 3)) (alist-delete 'y '((n . 1) (n . 2) (n . 3))))))
159 (with-test-prefix "append-map"
161 (with-test-prefix "one list"
164 (equal? '() (append-map noop '(()))))
167 (equal? '(1) (append-map noop '((1)))))
170 (equal? '(1 2) (append-map noop '((1 2)))))
173 (equal? '() (append-map noop '(() ()))))
176 (equal? '(1) (append-map noop '(() (1)))))
179 (equal? '(1 2) (append-map noop '(() (1 2)))))
182 (equal? '(1 2) (append-map noop '((1) (2)))))
185 (equal? '(1 2) (append-map noop '(() (1 2))))))
187 (with-test-prefix "two lists"
190 (equal? '() (append-map noop '(()) '(9))))
193 (equal? '(1) (append-map noop '((1)) '(9))))
195 (pass-if "() () / 9 9"
196 (equal? '() (append-map noop '(() ()) '(9 9))))
198 (pass-if "(1) (2) / 9"
199 (equal? '(1) (append-map noop '((1) (2)) '(9))))
201 (pass-if "(1) (2) / 9 9"
202 (equal? '(1 2) (append-map noop '((1) (2)) '(9 9))))))
205 ;; concatenate and concatenate!
209 (define (common-tests concatenate-proc unmodified?)
210 (define (try lstlst want)
211 (let ((lstlst-copy (copy-tree lstlst))
212 (got (concatenate-proc lstlst)))
214 (if (not (equal? lstlst lstlst-copy))
215 (error "input lists modified")))
218 (pass-if-exception "too few args" exception:wrong-num-args
221 (pass-if-exception "too many args" exception:wrong-num-args
222 (concatenate-proc '() '()))
227 (pass-if (try '((1)) '(1)))
228 (pass-if (try '((1 2)) '(1 2)))
229 (pass-if (try '(() (1)) '(1)))
230 (pass-if (try '(() () (1)) '(1)))
232 (pass-if (try '((1) (2)) '(1 2)))
233 (pass-if (try '(() (1 2)) '(1 2)))
235 (pass-if (try '((1) 2) '(1 . 2)))
236 (pass-if (try '((1) (2) 3) '(1 2 . 3)))
237 (pass-if (try '((1) (2) (3 . 4)) '(1 2 3 . 4)))
240 (with-test-prefix "concatenate"
241 (common-tests concatenate #t))
243 (with-test-prefix "concatenate!"
244 (common-tests concatenate! #f)))
250 (with-test-prefix "count"
251 (pass-if-exception "no args" exception:wrong-num-args
254 (pass-if-exception "one arg" exception:wrong-num-args
257 (with-test-prefix "one list"
261 (pass-if "empty list" (= 0 (count or1 '())))
263 (pass-if-exception "pred arg count 0" exception:wrong-type-arg
264 (count (lambda () x) '(1 2 3)))
265 (pass-if-exception "pred arg count 2" exception:wrong-type-arg
266 (count (lambda (x y) x) '(1 2 3)))
268 (pass-if-exception "improper 1" exception:wrong-type-arg
270 (pass-if-exception "improper 2" exception:wrong-type-arg
271 (count or1 '(1 . 2)))
272 (pass-if-exception "improper 3" exception:wrong-type-arg
273 (count or1 '(1 2 . 3)))
275 (pass-if (= 0 (count or1 '(#f))))
276 (pass-if (= 1 (count or1 '(#t))))
278 (pass-if (= 0 (count or1 '(#f #f))))
279 (pass-if (= 1 (count or1 '(#f #t))))
280 (pass-if (= 1 (count or1 '(#t #f))))
281 (pass-if (= 2 (count or1 '(#t #t))))
283 (pass-if (= 0 (count or1 '(#f #f #f))))
284 (pass-if (= 1 (count or1 '(#f #f #t))))
285 (pass-if (= 1 (count or1 '(#t #f #f))))
286 (pass-if (= 2 (count or1 '(#t #f #t))))
287 (pass-if (= 3 (count or1 '(#t #t #t)))))
289 (with-test-prefix "two lists"
294 (= 1 (count (lambda (x y)
299 (pass-if "empty lists" (= 0 (count or2 '() '())))
301 (pass-if-exception "pred arg count 0" exception:wrong-type-arg
302 (count (lambda () #t) '(1 2 3) '(1 2 3)))
303 (pass-if-exception "pred arg count 1" exception:wrong-type-arg
304 (count (lambda (x) x) '(1 2 3) '(1 2 3)))
305 (pass-if-exception "pred arg count 3" exception:wrong-type-arg
306 (count (lambda (x y z) x) '(1 2 3) '(1 2 3)))
308 (pass-if-exception "improper first 1" exception:wrong-type-arg
309 (count or2 1 '(1 2 3)))
310 (pass-if-exception "improper first 2" exception:wrong-type-arg
311 (count or2 '(1 . 2) '(1 2 3)))
312 (pass-if-exception "improper first 3" exception:wrong-type-arg
313 (count or2 '(1 2 . 3) '(1 2 3)))
315 (pass-if-exception "improper second 1" exception:wrong-type-arg
316 (count or2 '(1 2 3) 1))
317 (pass-if-exception "improper second 2" exception:wrong-type-arg
318 (count or2 '(1 2 3) '(1 . 2)))
319 (pass-if-exception "improper second 3" exception:wrong-type-arg
320 (count or2 '(1 2 3) '(1 2 . 3)))
322 (pass-if (= 0 (count or2 '(#f) '(#f))))
323 (pass-if (= 1 (count or2 '(#t) '(#f))))
324 (pass-if (= 1 (count or2 '(#f) '(#t))))
326 (pass-if (= 0 (count or2 '(#f #f) '(#f #f))))
327 (pass-if (= 1 (count or2 '(#t #f) '(#t #f))))
328 (pass-if (= 2 (count or2 '(#t #t) '(#f #f))))
329 (pass-if (= 2 (count or2 '(#t #f) '(#f #t))))
331 (with-test-prefix "stop shortest"
332 (pass-if (= 2 (count or2 '(#t #f #t) '(#f #t))))
333 (pass-if (= 2 (count or2 '(#t #f #t #t) '(#f #t))))
334 (pass-if (= 2 (count or2 '(#t #f) '(#f #t #t))))
335 (pass-if (= 2 (count or2 '(#t #f) '(#f #t #t #t))))))
337 (with-test-prefix "three lists"
342 (= 1 (count (lambda (x y z)
348 (pass-if "empty lists" (= 0 (count or3 '() '() '())))
350 ;; currently bad pred argument gives wrong-num-args when 3 or more
351 ;; lists, as opposed to wrong-type-arg for 1 or 2 lists
352 (pass-if-exception "pred arg count 0" exception:wrong-num-args
353 (count (lambda () #t) '(1 2 3) '(1 2 3) '(1 2 3)))
354 (pass-if-exception "pred arg count 2" exception:wrong-num-args
355 (count (lambda (x y) x) '(1 2 3) '(1 2 3)'(1 2 3) ))
356 (pass-if-exception "pred arg count 4" exception:wrong-num-args
357 (count (lambda (w x y z) x) '(1 2 3) '(1 2 3) '(1 2 3)))
359 (pass-if-exception "improper first 1" exception:wrong-type-arg
360 (count or3 1 '(1 2 3) '(1 2 3)))
361 (pass-if-exception "improper first 2" exception:wrong-type-arg
362 (count or3 '(1 . 2) '(1 2 3) '(1 2 3)))
363 (pass-if-exception "improper first 3" exception:wrong-type-arg
364 (count or3 '(1 2 . 3) '(1 2 3) '(1 2 3)))
366 (pass-if-exception "improper second 1" exception:wrong-type-arg
367 (count or3 '(1 2 3) 1 '(1 2 3)))
368 (pass-if-exception "improper second 2" exception:wrong-type-arg
369 (count or3 '(1 2 3) '(1 . 2) '(1 2 3)))
370 (pass-if-exception "improper second 3" exception:wrong-type-arg
371 (count or3 '(1 2 3) '(1 2 . 3) '(1 2 3)))
373 (pass-if-exception "improper third 1" exception:wrong-type-arg
374 (count or3 '(1 2 3) '(1 2 3) 1))
375 (pass-if-exception "improper third 2" exception:wrong-type-arg
376 (count or3 '(1 2 3) '(1 2 3) '(1 . 2)))
377 (pass-if-exception "improper third 3" exception:wrong-type-arg
378 (count or3 '(1 2 3) '(1 2 3) '(1 2 . 3)))
380 (pass-if (= 0 (count or3 '(#f) '(#f) '(#f))))
381 (pass-if (= 1 (count or3 '(#t) '(#f) '(#f))))
382 (pass-if (= 1 (count or3 '(#f) '(#t) '(#f))))
383 (pass-if (= 1 (count or3 '(#f) '(#f) '(#t))))
385 (pass-if (= 0 (count or3 '(#f #f) '(#f #f) '(#f #f))))
387 (pass-if (= 1 (count or3 '(#t #f) '(#f #f) '(#f #f))))
388 (pass-if (= 1 (count or3 '(#f #t) '(#f #f) '(#f #f))))
389 (pass-if (= 1 (count or3 '(#f #f) '(#t #f) '(#f #f))))
390 (pass-if (= 1 (count or3 '(#f #f) '(#f #t) '(#f #f))))
391 (pass-if (= 1 (count or3 '(#f #f) '(#f #f) '(#t #f))))
392 (pass-if (= 1 (count or3 '(#f #f) '(#f #f) '(#f #t))))
394 (pass-if (= 2 (count or3 '(#t #t) '(#f #f) '(#f #f))))
395 (pass-if (= 2 (count or3 '(#f #f) '(#t #t) '(#f #f))))
396 (pass-if (= 2 (count or3 '(#f #f) '(#f #f) '(#t #t))))
397 (pass-if (= 2 (count or3 '(#f #f) '(#t #f) '(#f #t))))
399 (with-test-prefix "stop shortest"
400 (pass-if (= 0 (count or3 '() '(#t #t #t) '(#t #t))))
401 (pass-if (= 0 (count or3 '(#t #t #t) '() '(#t #t))))
402 (pass-if (= 0 (count or3 '(#t #t #t) '(#t #t) '())))
404 (pass-if (= 1 (count or3 '(#t) '(#t #t #t) '(#t #t))))
405 (pass-if (= 1 (count or3 '(#t #t #t) '(#t) '(#t #t))))
406 (pass-if (= 1 (count or3 '(#t #t #t) '(#t #t) '(#t)))))))
409 ;; delete and delete!
413 ;; Call (PROC lst) for all lists of length up to 6, with all combinations
414 ;; of elements to be retained or deleted. Elements to retain are numbers,
415 ;; 0 upwards. Elements to be deleted are #f.
416 (define (test-lists proc)
419 (do ((limit (ash 1 n))
423 (do ((bit 0 (1+ bit)))
425 (set! lst (cons (if (logbit? bit i) bit #f) lst)))
428 (define (common-tests delete-proc)
429 (pass-if-exception "too few args" exception:wrong-num-args
432 (pass-if-exception "too many args" exception:wrong-num-args
433 (delete-proc 0 '() equal? 99))
436 (eq? '() (delete-proc 0 '())))
438 (pass-if "equal? (the default)"
440 (delete-proc '(2) '((1) (2) (3)))))
443 (equal? '((1) (2) (3))
444 (delete-proc '(2) '((1) (2) (3)) eq?)))
446 (pass-if "called arg order"
448 (delete-proc 3 '(1 2 3 4 5) <))))
450 (with-test-prefix "delete"
451 (common-tests delete)
455 (let ((lst-copy (list-copy lst)))
456 (with-test-prefix lst-copy
458 (equal? (delete #f lst)
459 (ref-delete #f lst)))
460 (pass-if "non-destructive"
461 (equal? lst-copy lst)))))))
463 (with-test-prefix "delete!"
464 (common-tests delete!)
469 (equal? (delete! #f lst)
470 (ref-delete #f lst)))))))
473 ;; delete-duplicates and delete-duplicates!
477 ;; Call (PROC lst) for all lists of length 1 <= n <= 4, with all
478 ;; combinations of numbers 1 to n in the elements
479 (define (test-lists proc)
482 (do ((limit (integer-expt n n))
487 (rem i (quotient rem n)))
489 (set! lst (cons (remainder rem n) lst)))
492 (define (common-tests delete-duplicates-proc)
493 (pass-if-exception "too few args" exception:wrong-num-args
494 (delete-duplicates-proc))
496 (pass-if-exception "too many args" exception:wrong-num-args
497 (delete-duplicates-proc '() equal? 99))
500 (eq? '() (delete-duplicates-proc '())))
502 (pass-if "equal? (the default)"
504 (delete-duplicates-proc '((2) (2) (2)))))
507 (equal? '((2) (2) (2))
508 (delete-duplicates-proc '((2) (2) (2)) eq?)))
510 (pass-if "called arg order"
512 (delete-duplicates-proc '(1 2 3 4 5)
519 (with-test-prefix "delete-duplicates"
520 (common-tests delete-duplicates)
524 (let ((lst-copy (list-copy lst)))
525 (with-test-prefix lst-copy
527 (equal? (delete-duplicates lst)
528 (ref-delete-duplicates lst)))
529 (pass-if "non-destructive"
530 (equal? lst-copy lst)))))))
532 (with-test-prefix "delete-duplicates!"
533 (common-tests delete-duplicates!)
538 (equal? (delete-duplicates! lst)
539 (ref-delete-duplicates lst)))))))
545 (with-test-prefix "drop"
548 (null? (drop '() 0)))
575 (pass-if "'(a b c) 1"
576 (let ((lst '(a b c)))
580 (pass-if "circular '(a) 0"
581 (let ((lst (circular-list 'a)))
585 (pass-if "circular '(a) 1"
586 (let ((lst (circular-list 'a)))
590 (pass-if "circular '(a) 2"
591 (let ((lst (circular-list 'a)))
595 (pass-if "circular '(a b) 1"
596 (let ((lst (circular-list 'a)))
600 (pass-if "circular '(a b) 2"
601 (let ((lst (circular-list 'a)))
605 (pass-if "circular '(a b) 5"
606 (let ((lst (circular-list 'a)))
610 (pass-if "'(a . b) 1"
614 (pass-if "'(a b . c) 1"
616 (drop '(a b . c) 2))))
622 (with-test-prefix "filter-map"
624 (with-test-prefix "one list"
626 (equal? '(1) (filter-map noop '(1))))
629 (equal? '() (filter-map noop '(#f))))
632 (equal? '(1 2) (filter-map noop '(1 2))))
635 (equal? '(2) (filter-map noop '(#f 2))))
638 (equal? '() (filter-map noop '(#f #f))))
641 (equal? '(1 2 3) (filter-map noop '(1 2 3))))
644 (equal? '(2 3) (filter-map noop '(#f 2 3))))
647 (equal? '(1 3) (filter-map noop '(1 #f 3))))
650 (equal? '(1 2) (filter-map noop '(1 2 #f)))))
652 (with-test-prefix "two lists"
653 (pass-if "(1 2 3) (4 5 6)"
654 (equal? '(1 2 3) (filter-map noop '(1 2 3) '(4 5 6))))
656 (pass-if "(#f 2 3) (4 5)"
657 (equal? '(2) (filter-map noop '(#f 2 3) '(4 5))))
659 (pass-if "(4 #f) (1 2 3)"
660 (equal? '(4) (filter-map noop '(4 #f) '(1 2 3))))))
666 (with-test-prefix "length+"
667 (pass-if-exception "too few args" exception:wrong-num-args
669 (pass-if-exception "too many args" exception:wrong-num-args
671 (pass-if (= 0 (length+ '())))
672 (pass-if (= 1 (length+ '(x))))
673 (pass-if (= 2 (length+ '(x y))))
674 (pass-if (= 3 (length+ '(x y z))))
675 (pass-if (not (length+ (circular-list 1))))
676 (pass-if (not (length+ (circular-list 1 2))))
677 (pass-if (not (length+ (circular-list 1 2 3)))))
683 (with-test-prefix "list-copy"
684 (pass-if (equal? '() (list-copy '())))
685 (pass-if (equal? '(1 2) (list-copy '(1 2))))
686 (pass-if (equal? '(1 2 3) (list-copy '(1 2 3))))
687 (pass-if (equal? '(1 2 3 4) (list-copy '(1 2 3 4))))
688 (pass-if (equal? '(1 2 3 4 5) (list-copy '(1 2 3 4 5))))
690 ;; improper lists can be copied
691 (pass-if (equal? 1 (list-copy 1)))
692 (pass-if (equal? '(1 . 2) (list-copy '(1 . 2))))
693 (pass-if (equal? '(1 2 . 3) (list-copy '(1 2 . 3))))
694 (pass-if (equal? '(1 2 3 . 4) (list-copy '(1 2 3 . 4))))
695 (pass-if (equal? '(1 2 3 4 . 5) (list-copy '(1 2 3 4 . 5)))))
701 (with-test-prefix "take"
704 (null? (take '() 0)))
707 (null? (take '(a) 0)))
710 (null? (take '() 0)))
712 (pass-if "'(a b c) 0"
713 (null? (take '() 0)))
718 (and (equal? '(a) got)
719 (not (eq? lst got)))))
725 (pass-if "'(a b c) 1"
732 (and (equal? '(a b) got)
733 (not (eq? lst got)))))
735 (pass-if "'(a b c) 2"
739 (pass-if "circular '(a) 0"
741 (take (circular-list 'a) 0)))
743 (pass-if "circular '(a) 1"
745 (take (circular-list 'a) 1)))
747 (pass-if "circular '(a) 2"
749 (take (circular-list 'a) 2)))
751 (pass-if "circular '(a b) 5"
753 (take (circular-list 'a 'b) 5)))
755 (pass-if "'(a . b) 1"
759 (pass-if "'(a b . c) 1"
761 (take '(a b . c) 1)))
763 (pass-if "'(a b . c) 2"
765 (take '(a b . c) 2))))
771 (define (test-partition pred list kept-good dropped-good)
772 (call-with-values (lambda ()
773 (partition pred list))
774 (lambda (kept dropped)
775 (and (equal? kept kept-good)
776 (equal? dropped dropped-good)))))
778 (with-test-prefix "partition"
780 (pass-if "with dropped tail"
781 (test-partition even? '(1 2 3 4 5 6 7)
782 '(2 4 6) '(1 3 5 7)))
784 (pass-if "with kept tail"
785 (test-partition even? '(1 2 3 4 5 6)
788 (pass-if "with everything dropped"
789 (test-partition even? '(1 3 5 7)
792 (pass-if "with everything kept"
793 (test-partition even? '(2 4 6)
796 (pass-if "with empty list"
797 (test-partition even? '()
800 (pass-if "with reasonably long list"
801 ;; the old implementation from SRFI-1 reference implementation
802 ;; would signal a stack-overflow for a list of only 500 elements!
803 (call-with-values (lambda ()
805 (make-list 10000 1)))
807 (and (= (length odd) 10000)
808 (= (length even) 0))))))