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 "append-map"
98 (with-test-prefix "one list"
101 (equal? '() (append-map noop '(()))))
104 (equal? '(1) (append-map noop '((1)))))
107 (equal? '(1 2) (append-map noop '((1 2)))))
110 (equal? '() (append-map noop '(() ()))))
113 (equal? '(1) (append-map noop '(() (1)))))
116 (equal? '(1 2) (append-map noop '(() (1 2)))))
119 (equal? '(1 2) (append-map noop '((1) (2)))))
122 (equal? '(1 2) (append-map noop '(() (1 2))))))
124 (with-test-prefix "two lists"
127 (equal? '() (append-map noop '(()) '(9))))
130 (equal? '(1) (append-map noop '((1)) '(9))))
132 (pass-if "() () / 9 9"
133 (equal? '() (append-map noop '(() ()) '(9 9))))
135 (pass-if "(1) (2) / 9"
136 (equal? '(1) (append-map noop '((1) (2)) '(9))))
138 (pass-if "(1) (2) / 9 9"
139 (equal? '(1 2) (append-map noop '((1) (2)) '(9 9))))))
142 ;; concatenate and concatenate!
146 (define (common-tests concatenate-proc unmodified?)
147 (define (try lstlst want)
148 (let ((lstlst-copy (copy-tree lstlst))
149 (got (concatenate-proc lstlst)))
151 (if (not (equal? lstlst lstlst-copy))
152 (error "input lists modified")))
155 (pass-if-exception "too few args" exception:wrong-num-args
158 (pass-if-exception "too many args" exception:wrong-num-args
159 (concatenate-proc '() '()))
164 (pass-if (try '((1)) '(1)))
165 (pass-if (try '((1 2)) '(1 2)))
166 (pass-if (try '(() (1)) '(1)))
167 (pass-if (try '(() () (1)) '(1)))
169 (pass-if (try '((1) (2)) '(1 2)))
170 (pass-if (try '(() (1 2)) '(1 2)))
172 (pass-if (try '((1) 2) '(1 . 2)))
173 (pass-if (try '((1) (2) 3) '(1 2 . 3)))
174 (pass-if (try '((1) (2) (3 . 4)) '(1 2 3 . 4)))
177 (with-test-prefix "concatenate"
178 (common-tests concatenate #t))
180 (with-test-prefix "concatenate!"
181 (common-tests concatenate! #f)))
187 (with-test-prefix "count"
188 (pass-if-exception "no args" exception:wrong-num-args
191 (pass-if-exception "one arg" exception:wrong-num-args
194 (with-test-prefix "one list"
198 (pass-if "empty list" (= 0 (count or1 '())))
200 (pass-if-exception "pred arg count 0" exception:wrong-type-arg
201 (count (lambda () x) '(1 2 3)))
202 (pass-if-exception "pred arg count 2" exception:wrong-type-arg
203 (count (lambda (x y) x) '(1 2 3)))
205 (pass-if-exception "improper 1" exception:wrong-type-arg
207 (pass-if-exception "improper 2" exception:wrong-type-arg
208 (count or1 '(1 . 2)))
209 (pass-if-exception "improper 3" exception:wrong-type-arg
210 (count or1 '(1 2 . 3)))
212 (pass-if (= 0 (count or1 '(#f))))
213 (pass-if (= 1 (count or1 '(#t))))
215 (pass-if (= 0 (count or1 '(#f #f))))
216 (pass-if (= 1 (count or1 '(#f #t))))
217 (pass-if (= 1 (count or1 '(#t #f))))
218 (pass-if (= 2 (count or1 '(#t #t))))
220 (pass-if (= 0 (count or1 '(#f #f #f))))
221 (pass-if (= 1 (count or1 '(#f #f #t))))
222 (pass-if (= 1 (count or1 '(#t #f #f))))
223 (pass-if (= 2 (count or1 '(#t #f #t))))
224 (pass-if (= 3 (count or1 '(#t #t #t)))))
226 (with-test-prefix "two lists"
231 (= 1 (count (lambda (x y)
236 (pass-if "empty lists" (= 0 (count or2 '() '())))
238 (pass-if-exception "pred arg count 0" exception:wrong-type-arg
239 (count (lambda () #t) '(1 2 3) '(1 2 3)))
240 (pass-if-exception "pred arg count 1" exception:wrong-type-arg
241 (count (lambda (x) x) '(1 2 3) '(1 2 3)))
242 (pass-if-exception "pred arg count 3" exception:wrong-type-arg
243 (count (lambda (x y z) x) '(1 2 3) '(1 2 3)))
245 (pass-if-exception "improper first 1" exception:wrong-type-arg
246 (count or2 1 '(1 2 3)))
247 (pass-if-exception "improper first 2" exception:wrong-type-arg
248 (count or2 '(1 . 2) '(1 2 3)))
249 (pass-if-exception "improper first 3" exception:wrong-type-arg
250 (count or2 '(1 2 . 3) '(1 2 3)))
252 (pass-if-exception "improper second 1" exception:wrong-type-arg
253 (count or2 '(1 2 3) 1))
254 (pass-if-exception "improper second 2" exception:wrong-type-arg
255 (count or2 '(1 2 3) '(1 . 2)))
256 (pass-if-exception "improper second 3" exception:wrong-type-arg
257 (count or2 '(1 2 3) '(1 2 . 3)))
259 (pass-if (= 0 (count or2 '(#f) '(#f))))
260 (pass-if (= 1 (count or2 '(#t) '(#f))))
261 (pass-if (= 1 (count or2 '(#f) '(#t))))
263 (pass-if (= 0 (count or2 '(#f #f) '(#f #f))))
264 (pass-if (= 1 (count or2 '(#t #f) '(#t #f))))
265 (pass-if (= 2 (count or2 '(#t #t) '(#f #f))))
266 (pass-if (= 2 (count or2 '(#t #f) '(#f #t))))
268 (with-test-prefix "stop shortest"
269 (pass-if (= 2 (count or2 '(#t #f #t) '(#f #t))))
270 (pass-if (= 2 (count or2 '(#t #f #t #t) '(#f #t))))
271 (pass-if (= 2 (count or2 '(#t #f) '(#f #t #t))))
272 (pass-if (= 2 (count or2 '(#t #f) '(#f #t #t #t))))))
274 (with-test-prefix "three lists"
279 (= 1 (count (lambda (x y z)
285 (pass-if "empty lists" (= 0 (count or3 '() '() '())))
287 ;; currently bad pred argument gives wrong-num-args when 3 or more
288 ;; lists, as opposed to wrong-type-arg for 1 or 2 lists
289 (pass-if-exception "pred arg count 0" exception:wrong-num-args
290 (count (lambda () #t) '(1 2 3) '(1 2 3) '(1 2 3)))
291 (pass-if-exception "pred arg count 2" exception:wrong-num-args
292 (count (lambda (x y) x) '(1 2 3) '(1 2 3)'(1 2 3) ))
293 (pass-if-exception "pred arg count 4" exception:wrong-num-args
294 (count (lambda (w x y z) x) '(1 2 3) '(1 2 3) '(1 2 3)))
296 (pass-if-exception "improper first 1" exception:wrong-type-arg
297 (count or3 1 '(1 2 3) '(1 2 3)))
298 (pass-if-exception "improper first 2" exception:wrong-type-arg
299 (count or3 '(1 . 2) '(1 2 3) '(1 2 3)))
300 (pass-if-exception "improper first 3" exception:wrong-type-arg
301 (count or3 '(1 2 . 3) '(1 2 3) '(1 2 3)))
303 (pass-if-exception "improper second 1" exception:wrong-type-arg
304 (count or3 '(1 2 3) 1 '(1 2 3)))
305 (pass-if-exception "improper second 2" exception:wrong-type-arg
306 (count or3 '(1 2 3) '(1 . 2) '(1 2 3)))
307 (pass-if-exception "improper second 3" exception:wrong-type-arg
308 (count or3 '(1 2 3) '(1 2 . 3) '(1 2 3)))
310 (pass-if-exception "improper third 1" exception:wrong-type-arg
311 (count or3 '(1 2 3) '(1 2 3) 1))
312 (pass-if-exception "improper third 2" exception:wrong-type-arg
313 (count or3 '(1 2 3) '(1 2 3) '(1 . 2)))
314 (pass-if-exception "improper third 3" exception:wrong-type-arg
315 (count or3 '(1 2 3) '(1 2 3) '(1 2 . 3)))
317 (pass-if (= 0 (count or3 '(#f) '(#f) '(#f))))
318 (pass-if (= 1 (count or3 '(#t) '(#f) '(#f))))
319 (pass-if (= 1 (count or3 '(#f) '(#t) '(#f))))
320 (pass-if (= 1 (count or3 '(#f) '(#f) '(#t))))
322 (pass-if (= 0 (count or3 '(#f #f) '(#f #f) '(#f #f))))
324 (pass-if (= 1 (count or3 '(#t #f) '(#f #f) '(#f #f))))
325 (pass-if (= 1 (count or3 '(#f #t) '(#f #f) '(#f #f))))
326 (pass-if (= 1 (count or3 '(#f #f) '(#t #f) '(#f #f))))
327 (pass-if (= 1 (count or3 '(#f #f) '(#f #t) '(#f #f))))
328 (pass-if (= 1 (count or3 '(#f #f) '(#f #f) '(#t #f))))
329 (pass-if (= 1 (count or3 '(#f #f) '(#f #f) '(#f #t))))
331 (pass-if (= 2 (count or3 '(#t #t) '(#f #f) '(#f #f))))
332 (pass-if (= 2 (count or3 '(#f #f) '(#t #t) '(#f #f))))
333 (pass-if (= 2 (count or3 '(#f #f) '(#f #f) '(#t #t))))
334 (pass-if (= 2 (count or3 '(#f #f) '(#t #f) '(#f #t))))
336 (with-test-prefix "stop shortest"
337 (pass-if (= 0 (count or3 '() '(#t #t #t) '(#t #t))))
338 (pass-if (= 0 (count or3 '(#t #t #t) '() '(#t #t))))
339 (pass-if (= 0 (count or3 '(#t #t #t) '(#t #t) '())))
341 (pass-if (= 1 (count or3 '(#t) '(#t #t #t) '(#t #t))))
342 (pass-if (= 1 (count or3 '(#t #t #t) '(#t) '(#t #t))))
343 (pass-if (= 1 (count or3 '(#t #t #t) '(#t #t) '(#t)))))))
346 ;; delete and delete!
350 ;; Call (PROC lst) for all lists of length up to 6, with all combinations
351 ;; of elements to be retained or deleted. Elements to retain are numbers,
352 ;; 0 upwards. Elements to be deleted are #f.
353 (define (test-lists proc)
356 (do ((limit (ash 1 n))
360 (do ((bit 0 (1+ bit)))
362 (set! lst (cons (if (logbit? bit i) bit #f) lst)))
365 (define (common-tests delete-proc)
366 (pass-if-exception "too few args" exception:wrong-num-args
369 (pass-if-exception "too many args" exception:wrong-num-args
370 (delete-proc 0 '() equal? 99))
373 (eq? '() (delete-proc 0 '())))
375 (pass-if "equal? (the default)"
377 (delete-proc '(2) '((1) (2) (3)))))
380 (equal? '((1) (2) (3))
381 (delete-proc '(2) '((1) (2) (3)) eq?)))
383 (pass-if "called arg order"
385 (delete-proc 3 '(1 2 3 4 5) <))))
387 (with-test-prefix "delete"
388 (common-tests delete)
392 (let ((lst-copy (list-copy lst)))
393 (with-test-prefix lst-copy
395 (equal? (delete #f lst)
396 (ref-delete #f lst)))
397 (pass-if "non-destructive"
398 (equal? lst-copy lst)))))))
400 (with-test-prefix "delete!"
401 (common-tests delete!)
406 (equal? (delete! #f lst)
407 (ref-delete #f lst)))))))
410 ;; delete-duplicates and delete-duplicates!
414 ;; Call (PROC lst) for all lists of length 1 <= n <= 4, with all
415 ;; combinations of numbers 1 to n in the elements
416 (define (test-lists proc)
419 (do ((limit (integer-expt n n))
424 (rem i (quotient rem n)))
426 (set! lst (cons (remainder rem n) lst)))
429 (define (common-tests delete-duplicates-proc)
430 (pass-if-exception "too few args" exception:wrong-num-args
431 (delete-duplicates-proc))
433 (pass-if-exception "too many args" exception:wrong-num-args
434 (delete-duplicates-proc '() equal? 99))
437 (eq? '() (delete-duplicates-proc '())))
439 (pass-if "equal? (the default)"
441 (delete-duplicates-proc '((2) (2) (2)))))
444 (equal? '((2) (2) (2))
445 (delete-duplicates-proc '((2) (2) (2)) eq?)))
447 (pass-if "called arg order"
449 (delete-duplicates-proc '(1 2 3 4 5)
456 (with-test-prefix "delete-duplicates"
457 (common-tests delete-duplicates)
461 (let ((lst-copy (list-copy lst)))
462 (with-test-prefix lst-copy
464 (equal? (delete-duplicates lst)
465 (ref-delete-duplicates lst)))
466 (pass-if "non-destructive"
467 (equal? lst-copy lst)))))))
469 (with-test-prefix "delete-duplicates!"
470 (common-tests delete-duplicates!)
475 (equal? (delete-duplicates! lst)
476 (ref-delete-duplicates lst)))))))
482 (with-test-prefix "drop"
485 (null? (drop '() 0)))
512 (pass-if "'(a b c) 1"
513 (let ((lst '(a b c)))
517 (pass-if "circular '(a) 0"
518 (let ((lst (circular-list 'a)))
522 (pass-if "circular '(a) 1"
523 (let ((lst (circular-list 'a)))
527 (pass-if "circular '(a) 2"
528 (let ((lst (circular-list 'a)))
532 (pass-if "circular '(a b) 1"
533 (let ((lst (circular-list 'a)))
537 (pass-if "circular '(a b) 2"
538 (let ((lst (circular-list 'a)))
542 (pass-if "circular '(a b) 5"
543 (let ((lst (circular-list 'a)))
547 (pass-if "'(a . b) 1"
551 (pass-if "'(a b . c) 1"
553 (drop '(a b . c) 2))))
559 (with-test-prefix "filter-map"
561 (with-test-prefix "one list"
563 (equal? '(1) (filter-map noop '(1))))
566 (equal? '() (filter-map noop '(#f))))
569 (equal? '(1 2) (filter-map noop '(1 2))))
572 (equal? '(2) (filter-map noop '(#f 2))))
575 (equal? '() (filter-map noop '(#f #f))))
578 (equal? '(1 2 3) (filter-map noop '(1 2 3))))
581 (equal? '(2 3) (filter-map noop '(#f 2 3))))
584 (equal? '(1 3) (filter-map noop '(1 #f 3))))
587 (equal? '(1 2) (filter-map noop '(1 2 #f)))))
589 (with-test-prefix "two lists"
590 (pass-if "(1 2 3) (4 5 6)"
591 (equal? '(1 2 3) (filter-map noop '(1 2 3) '(4 5 6))))
593 (pass-if "(#f 2 3) (4 5)"
594 (equal? '(2) (filter-map noop '(#f 2 3) '(4 5))))
596 (pass-if "(4 #f) (1 2 3)"
597 (equal? '(4) (filter-map noop '(4 #f) '(1 2 3))))))
603 (with-test-prefix "length+"
604 (pass-if-exception "too few args" exception:wrong-num-args
606 (pass-if-exception "too many args" exception:wrong-num-args
608 (pass-if (= 0 (length+ '())))
609 (pass-if (= 1 (length+ '(x))))
610 (pass-if (= 2 (length+ '(x y))))
611 (pass-if (= 3 (length+ '(x y z))))
612 (pass-if (not (length+ (circular-list 1))))
613 (pass-if (not (length+ (circular-list 1 2))))
614 (pass-if (not (length+ (circular-list 1 2 3)))))
620 (with-test-prefix "list-copy"
621 (pass-if (equal? '() (list-copy '())))
622 (pass-if (equal? '(1 2) (list-copy '(1 2))))
623 (pass-if (equal? '(1 2 3) (list-copy '(1 2 3))))
624 (pass-if (equal? '(1 2 3 4) (list-copy '(1 2 3 4))))
625 (pass-if (equal? '(1 2 3 4 5) (list-copy '(1 2 3 4 5))))
627 ;; improper lists can be copied
628 (pass-if (equal? 1 (list-copy 1)))
629 (pass-if (equal? '(1 . 2) (list-copy '(1 . 2))))
630 (pass-if (equal? '(1 2 . 3) (list-copy '(1 2 . 3))))
631 (pass-if (equal? '(1 2 3 . 4) (list-copy '(1 2 3 . 4))))
632 (pass-if (equal? '(1 2 3 4 . 5) (list-copy '(1 2 3 4 . 5)))))
638 (with-test-prefix "take"
641 (null? (take '() 0)))
644 (null? (take '(a) 0)))
647 (null? (take '() 0)))
649 (pass-if "'(a b c) 0"
650 (null? (take '() 0)))
655 (and (equal? '(a) got)
656 (not (eq? lst got)))))
662 (pass-if "'(a b c) 1"
669 (and (equal? '(a b) got)
670 (not (eq? lst got)))))
672 (pass-if "'(a b c) 2"
676 (pass-if "circular '(a) 0"
678 (take (circular-list 'a) 0)))
680 (pass-if "circular '(a) 1"
682 (take (circular-list 'a) 1)))
684 (pass-if "circular '(a) 2"
686 (take (circular-list 'a) 2)))
688 (pass-if "circular '(a b) 5"
690 (take (circular-list 'a 'b) 5)))
692 (pass-if "'(a . b) 1"
696 (pass-if "'(a b . c) 1"
698 (take '(a b . c) 1)))
700 (pass-if "'(a b . c) 2"
702 (take '(a b . c) 2))))
708 (define (test-partition pred list kept-good dropped-good)
709 (call-with-values (lambda ()
710 (partition pred list))
711 (lambda (kept dropped)
712 (and (equal? kept kept-good)
713 (equal? dropped dropped-good)))))
715 (with-test-prefix "partition"
717 (pass-if "with dropped tail"
718 (test-partition even? '(1 2 3 4 5 6 7)
719 '(2 4 6) '(1 3 5 7)))
721 (pass-if "with kept tail"
722 (test-partition even? '(1 2 3 4 5 6)
725 (pass-if "with everything dropped"
726 (test-partition even? '(1 3 5 7)
729 (pass-if "with everything kept"
730 (test-partition even? '(2 4 6)
733 (pass-if "with empty list"
734 (test-partition even? '()
737 (pass-if "with reasonably long list"
738 ;; the old implementation from SRFI-1 reference implementation
739 ;; would signal a stack-overflow for a list of only 500 elements!
740 (call-with-values (lambda ()
742 (make-list 10000 1)))
744 (and (= (length odd) 10000)
745 (= (length even) 0))))))