(SRFI-1 Length Append etc): In concatenate, note equivalence to "apply append".
[bpt/guile.git] / test-suite / tests / srfi-1.test
CommitLineData
91e7199f
KR
1;;;; srfi-1.test --- Test suite for Guile's SRFI-1 functions. -*- scheme -*-
2;;;;
3;;;; Copyright 2003 Free Software Foundation, Inc.
4;;;;
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.
9;;;;
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.
14;;;;
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
19
20(use-modules (srfi srfi-1)
21 (test-suite lib))
22
72f1b979
KR
23(define (ref-delete x lst . proc)
24 "Reference implemenation of srfi-1 `delete'."
25 (set! proc (if (null? proc) equal? (car proc)))
26 (do ((ret '())
27 (lst lst (cdr lst)))
28 ((null? lst)
29 (reverse! ret))
30 (if (not (proc x (car lst)))
31 (set! ret (cons (car lst) ret)))))
32
33(define (ref-delete-duplicates lst . proc)
34 "Reference implemenation of srfi-1 `delete-duplicates'."
35 (set! proc (if (null? proc) equal? (car proc)))
36 (if (null? lst)
37 '()
38 (do ((keep '()))
39 ((null? lst)
40 (reverse! keep))
41 (let ((elem (car lst)))
42 (set! keep (cons elem keep))
43 (set! lst (ref-delete elem lst proc))))))
44
91e7199f 45
c6e9db20
KR
46;;
47;; concatenate and concatenate!
48;;
49
50(let ()
51 (define (common-tests concatenate-proc unmodified?)
52 (define (try lstlst want)
53 (let ((lstlst-copy (copy-tree lstlst))
54 (got (concatenate-proc lstlst)))
55 (if unmodified?
56 (if (not (equal? lstlst lstlst-copy))
57 (error "input lists modified")))
58 (equal? got want)))
59
60 (pass-if-exception "too few args" exception:wrong-num-args
61 (concatenate-proc))
62
63 (pass-if-exception "too many args" exception:wrong-num-args
64 (concatenate-proc '() '()))
65
66 (pass-if "no lists"
67 (try '() '()))
68
69 (pass-if (try '((1)) '(1)))
70 (pass-if (try '((1 2)) '(1 2)))
71 (pass-if (try '(() (1)) '(1)))
72 (pass-if (try '(() () (1)) '(1)))
73
74 (pass-if (try '((1) (2)) '(1 2)))
75 (pass-if (try '(() (1 2)) '(1 2)))
76
77 (pass-if (try '((1) 2) '(1 . 2)))
78 (pass-if (try '((1) (2) 3) '(1 2 . 3)))
79 (pass-if (try '((1) (2) (3 . 4)) '(1 2 3 . 4)))
80 )
81
82 (with-test-prefix "concatenate"
83 (common-tests concatenate #t))
84
85 (with-test-prefix "concatenate!"
86 (common-tests concatenate! #f)))
87
f3903293
KR
88;;
89;; count
90;;
91
92(with-test-prefix "count"
93 (pass-if-exception "no args" exception:wrong-num-args
94 (count))
95
96 (pass-if-exception "one arg" exception:wrong-num-args
97 (count noop))
98
99 (with-test-prefix "one list"
100 (define (or1 x)
101 x)
102
103 (pass-if "empty list" (= 0 (count or1 '())))
104
105 (pass-if-exception "pred arg count 0" exception:wrong-type-arg
106 (count (lambda () x) '(1 2 3)))
107 (pass-if-exception "pred arg count 2" exception:wrong-type-arg
108 (count (lambda (x y) x) '(1 2 3)))
109
110 (pass-if-exception "improper 1" exception:wrong-type-arg
111 (count or1 1))
112 (pass-if-exception "improper 2" exception:wrong-type-arg
113 (count or1 '(1 . 2)))
114 (pass-if-exception "improper 3" exception:wrong-type-arg
115 (count or1 '(1 2 . 3)))
116
117 (pass-if (= 0 (count or1 '(#f))))
118 (pass-if (= 1 (count or1 '(#t))))
119
120 (pass-if (= 0 (count or1 '(#f #f))))
121 (pass-if (= 1 (count or1 '(#f #t))))
122 (pass-if (= 1 (count or1 '(#t #f))))
123 (pass-if (= 2 (count or1 '(#t #t))))
124
125 (pass-if (= 0 (count or1 '(#f #f #f))))
126 (pass-if (= 1 (count or1 '(#f #f #t))))
127 (pass-if (= 1 (count or1 '(#t #f #f))))
128 (pass-if (= 2 (count or1 '(#t #f #t))))
129 (pass-if (= 3 (count or1 '(#t #t #t)))))
130
131 (with-test-prefix "two lists"
132 (define (or2 x y)
133 (or x y))
134
135 (pass-if "arg order"
136 (= 1 (count (lambda (x y)
137 (and (= 1 x)
138 (= 2 y)))
139 '(1) '(2))))
140
141 (pass-if "empty lists" (= 0 (count or2 '() '())))
142
143 (pass-if-exception "pred arg count 0" exception:wrong-type-arg
144 (count (lambda () #t) '(1 2 3) '(1 2 3)))
145 (pass-if-exception "pred arg count 1" exception:wrong-type-arg
146 (count (lambda (x) x) '(1 2 3) '(1 2 3)))
147 (pass-if-exception "pred arg count 3" exception:wrong-type-arg
148 (count (lambda (x y z) x) '(1 2 3) '(1 2 3)))
149
150 (pass-if-exception "improper first 1" exception:wrong-type-arg
151 (count or2 1 '(1 2 3)))
152 (pass-if-exception "improper first 2" exception:wrong-type-arg
153 (count or2 '(1 . 2) '(1 2 3)))
154 (pass-if-exception "improper first 3" exception:wrong-type-arg
155 (count or2 '(1 2 . 3) '(1 2 3)))
156
157 (pass-if-exception "improper second 1" exception:wrong-type-arg
158 (count or2 '(1 2 3) 1))
159 (pass-if-exception "improper second 2" exception:wrong-type-arg
160 (count or2 '(1 2 3) '(1 . 2)))
161 (pass-if-exception "improper second 3" exception:wrong-type-arg
162 (count or2 '(1 2 3) '(1 2 . 3)))
163
164 (pass-if (= 0 (count or2 '(#f) '(#f))))
165 (pass-if (= 1 (count or2 '(#t) '(#f))))
166 (pass-if (= 1 (count or2 '(#f) '(#t))))
167
168 (pass-if (= 0 (count or2 '(#f #f) '(#f #f))))
169 (pass-if (= 1 (count or2 '(#t #f) '(#t #f))))
170 (pass-if (= 2 (count or2 '(#t #t) '(#f #f))))
171 (pass-if (= 2 (count or2 '(#t #f) '(#f #t))))
172
173 (with-test-prefix "stop shortest"
174 (pass-if (= 2 (count or2 '(#t #f #t) '(#f #t))))
175 (pass-if (= 2 (count or2 '(#t #f #t #t) '(#f #t))))
176 (pass-if (= 2 (count or2 '(#t #f) '(#f #t #t))))
177 (pass-if (= 2 (count or2 '(#t #f) '(#f #t #t #t))))))
178
179 (with-test-prefix "three lists"
180 (define (or3 x y z)
181 (or x y z))
182
183 (pass-if "arg order"
184 (= 1 (count (lambda (x y z)
185 (and (= 1 x)
186 (= 2 y)
187 (= 3 z)))
188 '(1) '(2) '(3))))
189
190 (pass-if "empty lists" (= 0 (count or3 '() '() '())))
191
192 ;; currently bad pred argument gives wrong-num-args when 3 or more
193 ;; lists, as opposed to wrong-type-arg for 1 or 2 lists
194 (pass-if-exception "pred arg count 0" exception:wrong-num-args
195 (count (lambda () #t) '(1 2 3) '(1 2 3) '(1 2 3)))
196 (pass-if-exception "pred arg count 2" exception:wrong-num-args
197 (count (lambda (x y) x) '(1 2 3) '(1 2 3)'(1 2 3) ))
198 (pass-if-exception "pred arg count 4" exception:wrong-num-args
199 (count (lambda (w x y z) x) '(1 2 3) '(1 2 3) '(1 2 3)))
200
201 (pass-if-exception "improper first 1" exception:wrong-type-arg
202 (count or3 1 '(1 2 3) '(1 2 3)))
203 (pass-if-exception "improper first 2" exception:wrong-type-arg
204 (count or3 '(1 . 2) '(1 2 3) '(1 2 3)))
205 (pass-if-exception "improper first 3" exception:wrong-type-arg
206 (count or3 '(1 2 . 3) '(1 2 3) '(1 2 3)))
207
208 (pass-if-exception "improper second 1" exception:wrong-type-arg
209 (count or3 '(1 2 3) 1 '(1 2 3)))
210 (pass-if-exception "improper second 2" exception:wrong-type-arg
211 (count or3 '(1 2 3) '(1 . 2) '(1 2 3)))
212 (pass-if-exception "improper second 3" exception:wrong-type-arg
213 (count or3 '(1 2 3) '(1 2 . 3) '(1 2 3)))
214
215 (pass-if-exception "improper third 1" exception:wrong-type-arg
216 (count or3 '(1 2 3) '(1 2 3) 1))
217 (pass-if-exception "improper third 2" exception:wrong-type-arg
218 (count or3 '(1 2 3) '(1 2 3) '(1 . 2)))
219 (pass-if-exception "improper third 3" exception:wrong-type-arg
220 (count or3 '(1 2 3) '(1 2 3) '(1 2 . 3)))
221
222 (pass-if (= 0 (count or3 '(#f) '(#f) '(#f))))
223 (pass-if (= 1 (count or3 '(#t) '(#f) '(#f))))
224 (pass-if (= 1 (count or3 '(#f) '(#t) '(#f))))
225 (pass-if (= 1 (count or3 '(#f) '(#f) '(#t))))
226
227 (pass-if (= 0 (count or3 '(#f #f) '(#f #f) '(#f #f))))
228
229 (pass-if (= 1 (count or3 '(#t #f) '(#f #f) '(#f #f))))
230 (pass-if (= 1 (count or3 '(#f #t) '(#f #f) '(#f #f))))
231 (pass-if (= 1 (count or3 '(#f #f) '(#t #f) '(#f #f))))
232 (pass-if (= 1 (count or3 '(#f #f) '(#f #t) '(#f #f))))
233 (pass-if (= 1 (count or3 '(#f #f) '(#f #f) '(#t #f))))
234 (pass-if (= 1 (count or3 '(#f #f) '(#f #f) '(#f #t))))
235
236 (pass-if (= 2 (count or3 '(#t #t) '(#f #f) '(#f #f))))
237 (pass-if (= 2 (count or3 '(#f #f) '(#t #t) '(#f #f))))
238 (pass-if (= 2 (count or3 '(#f #f) '(#f #f) '(#t #t))))
239 (pass-if (= 2 (count or3 '(#f #f) '(#t #f) '(#f #t))))
240
241 (with-test-prefix "stop shortest"
242 (pass-if (= 0 (count or3 '() '(#t #t #t) '(#t #t))))
243 (pass-if (= 0 (count or3 '(#t #t #t) '() '(#t #t))))
244 (pass-if (= 0 (count or3 '(#t #t #t) '(#t #t) '())))
245
246 (pass-if (= 1 (count or3 '(#t) '(#t #t #t) '(#t #t))))
247 (pass-if (= 1 (count or3 '(#t #t #t) '(#t) '(#t #t))))
248 (pass-if (= 1 (count or3 '(#t #t #t) '(#t #t) '(#t)))))))
c6e9db20 249
8ec84fe5
KR
250;;
251;; delete and delete!
252;;
253
254(let ()
72f1b979
KR
255 ;; Call (PROC lst) for all lists of length up to 6, with all combinations
256 ;; of elements to be retained or deleted. Elements to retain are numbers,
257 ;; 0 upwards. Elements to be deleted are #f.
258 (define (test-lists proc)
259 (do ((n 0 (1+ n)))
260 ((>= n 6))
261 (do ((limit (ash 1 n))
262 (i 0 (1+ i)))
263 ((>= i limit))
264 (let ((lst '()))
265 (do ((bit 0 (1+ bit)))
266 ((>= bit n))
267 (set! lst (cons (if (logbit? bit i) bit #f) lst)))
268 (proc lst)))))
269
8ec84fe5 270 (define (common-tests delete-proc)
72f1b979
KR
271 (pass-if-exception "too few args" exception:wrong-num-args
272 (delete-proc 0))
273
274 (pass-if-exception "too many args" exception:wrong-num-args
275 (delete-proc 0 '() equal? 99))
276
277 (pass-if "empty"
278 (eq? '() (delete-proc 0 '())))
279
280 (pass-if "equal? (the default)"
281 (equal? '((1) (3))
282 (delete-proc '(2) '((1) (2) (3)))))
283
284 (pass-if "eq?"
285 (equal? '((1) (2) (3))
286 (delete-proc '(2) '((1) (2) (3)) eq?)))
287
8ec84fe5
KR
288 (pass-if "called arg order"
289 (equal? '(1 2 3)
290 (delete-proc 3 '(1 2 3 4 5) <))))
291
292 (with-test-prefix "delete"
72f1b979 293 (common-tests delete)
8ec84fe5 294
72f1b979
KR
295 (test-lists
296 (lambda (lst)
297 (let ((lst-copy (list-copy lst)))
298 (with-test-prefix lst-copy
299 (pass-if "result"
300 (equal? (delete #f lst)
301 (ref-delete #f lst)))
302 (pass-if "non-destructive"
303 (equal? lst-copy lst)))))))
304
8ec84fe5 305 (with-test-prefix "delete!"
72f1b979
KR
306 (common-tests delete!)
307
308 (test-lists
309 (lambda (lst)
310 (pass-if lst
311 (equal? (delete! #f lst)
312 (ref-delete #f lst)))))))
313
314;;
315;; delete-duplicates and delete-duplicates!
316;;
317
318(let ()
319 ;; Call (PROC lst) for all lists of length 1 <= n <= 4, with all
320 ;; combinations of numbers 1 to n in the elements
321 (define (test-lists proc)
322 (do ((n 1 (1+ n)))
323 ((> n 4))
324 (do ((limit (integer-expt n n))
325 (i 0 (1+ i)))
326 ((>= i limit))
327 (let ((lst '()))
328 (do ((j 0 (1+ j))
329 (rem i (quotient rem n)))
330 ((>= j n))
331 (set! lst (cons (remainder rem n) lst)))
332 (proc lst)))))
333
334 (define (common-tests delete-duplicates-proc)
335 (pass-if-exception "too few args" exception:wrong-num-args
336 (delete-duplicates-proc))
337
338 (pass-if-exception "too many args" exception:wrong-num-args
339 (delete-duplicates-proc '() equal? 99))
340
341 (pass-if "empty"
342 (eq? '() (delete-duplicates-proc '())))
343
344 (pass-if "equal? (the default)"
345 (equal? '((2))
346 (delete-duplicates-proc '((2) (2) (2)))))
347
348 (pass-if "eq?"
349 (equal? '((2) (2) (2))
350 (delete-duplicates-proc '((2) (2) (2)) eq?)))
351
352 (pass-if "called arg order"
353 (let ((ok #t))
354 (delete-duplicates-proc '(1 2 3 4 5)
355 (lambda (x y)
356 (if (> x y)
357 (set! ok #f))
358 #f))
359 ok)))
360
361 (with-test-prefix "delete-duplicates"
362 (common-tests delete-duplicates)
363
364 (test-lists
365 (lambda (lst)
366 (let ((lst-copy (list-copy lst)))
367 (with-test-prefix lst-copy
368 (pass-if "result"
369 (equal? (delete-duplicates lst)
370 (ref-delete-duplicates lst)))
371 (pass-if "non-destructive"
372 (equal? lst-copy lst)))))))
373
374 (with-test-prefix "delete-duplicates!"
375 (common-tests delete-duplicates!)
376
377 (test-lists
378 (lambda (lst)
379 (pass-if lst
380 (equal? (delete-duplicates! lst)
381 (ref-delete-duplicates lst)))))))
8ec84fe5 382
91e7199f
KR
383;;
384;; drop
385;;
386
387(with-test-prefix "drop"
388
389 (pass-if "'() 0"
390 (null? (drop '() 0)))
391
392 (pass-if "'(a) 0"
393 (let ((lst '(a)))
394 (eq? lst
395 (drop lst 0))))
396
397 (pass-if "'(a b) 0"
398 (let ((lst '(a b)))
399 (eq? lst
400 (drop lst 0))))
401
402 (pass-if "'(a) 1"
403 (let ((lst '(a)))
404 (eq? (cdr lst)
405 (drop lst 1))))
406
407 (pass-if "'(a b) 1"
408 (let ((lst '(a b)))
409 (eq? (cdr lst)
410 (drop lst 1))))
411
412 (pass-if "'(a b) 2"
413 (let ((lst '(a b)))
414 (eq? (cddr lst)
415 (drop lst 2))))
416
417 (pass-if "'(a b c) 1"
418 (let ((lst '(a b c)))
419 (eq? (cddr lst)
420 (drop lst 2))))
421
422 (pass-if "circular '(a) 0"
423 (let ((lst (circular-list 'a)))
424 (eq? lst
425 (drop lst 0))))
426
427 (pass-if "circular '(a) 1"
428 (let ((lst (circular-list 'a)))
429 (eq? lst
430 (drop lst 1))))
431
432 (pass-if "circular '(a) 2"
433 (let ((lst (circular-list 'a)))
434 (eq? lst
435 (drop lst 1))))
436
437 (pass-if "circular '(a b) 1"
438 (let ((lst (circular-list 'a)))
439 (eq? (cdr lst)
440 (drop lst 0))))
441
442 (pass-if "circular '(a b) 2"
443 (let ((lst (circular-list 'a)))
444 (eq? lst
445 (drop lst 1))))
446
447 (pass-if "circular '(a b) 5"
448 (let ((lst (circular-list 'a)))
449 (eq? (cdr lst)
450 (drop lst 5))))
451
452 (pass-if "'(a . b) 1"
453 (eq? 'b
454 (drop '(a . b) 1)))
455
456 (pass-if "'(a b . c) 1"
457 (equal? 'c
458 (drop '(a b . c) 2))))
459
15d36a34
KR
460;;
461;; length+
462;;
463
464(with-test-prefix "length+"
465 (pass-if-exception "too few args" exception:wrong-num-args
466 (length+))
467 (pass-if-exception "too many args" exception:wrong-num-args
468 (length+ 123 456))
469 (pass-if (= 0 (length+ '())))
470 (pass-if (= 1 (length+ '(x))))
471 (pass-if (= 2 (length+ '(x y))))
472 (pass-if (= 3 (length+ '(x y z))))
473 (pass-if (not (length+ (circular-list 1))))
474 (pass-if (not (length+ (circular-list 1 2))))
475 (pass-if (not (length+ (circular-list 1 2 3)))))
476
b052db69
KR
477;;
478;; list-copy
479;;
480
481(with-test-prefix "list-copy"
b052db69
KR
482 (pass-if (equal? '() (list-copy '())))
483 (pass-if (equal? '(1 2) (list-copy '(1 2))))
484 (pass-if (equal? '(1 2 3) (list-copy '(1 2 3))))
485 (pass-if (equal? '(1 2 3 4) (list-copy '(1 2 3 4))))
486 (pass-if (equal? '(1 2 3 4 5) (list-copy '(1 2 3 4 5))))
487
488 ;; improper lists can be copied
489 (pass-if (equal? 1 (list-copy 1)))
490 (pass-if (equal? '(1 . 2) (list-copy '(1 . 2))))
491 (pass-if (equal? '(1 2 . 3) (list-copy '(1 2 . 3))))
492 (pass-if (equal? '(1 2 3 . 4) (list-copy '(1 2 3 . 4))))
493 (pass-if (equal? '(1 2 3 4 . 5) (list-copy '(1 2 3 4 . 5)))))
494
91e7199f
KR
495;;
496;; take
497;;
498
499(with-test-prefix "take"
500
501 (pass-if "'() 0"
502 (null? (take '() 0)))
503
504 (pass-if "'(a) 0"
505 (null? (take '(a) 0)))
506
507 (pass-if "'(a b) 0"
508 (null? (take '() 0)))
509
510 (pass-if "'(a b c) 0"
511 (null? (take '() 0)))
512
513 (pass-if "'(a) 1"
514 (let* ((lst '(a))
515 (got (take lst 1)))
516 (and (equal? '(a) got)
517 (not (eq? lst got)))))
518
519 (pass-if "'(a b) 1"
520 (equal? '(a)
521 (take '(a b) 1)))
522
523 (pass-if "'(a b c) 1"
524 (equal? '(a)
525 (take '(a b c) 1)))
526
527 (pass-if "'(a b) 2"
528 (let* ((lst '(a b))
529 (got (take lst 2)))
530 (and (equal? '(a b) got)
531 (not (eq? lst got)))))
532
533 (pass-if "'(a b c) 2"
534 (equal? '(a b)
535 (take '(a b c) 2)))
536
537 (pass-if "circular '(a) 0"
538 (equal? '()
539 (take (circular-list 'a) 0)))
540
541 (pass-if "circular '(a) 1"
542 (equal? '(a)
543 (take (circular-list 'a) 1)))
544
545 (pass-if "circular '(a) 2"
546 (equal? '(a a)
547 (take (circular-list 'a) 2)))
548
549 (pass-if "circular '(a b) 5"
550 (equal? '(a b a b a)
551 (take (circular-list 'a 'b) 5)))
552
553 (pass-if "'(a . b) 1"
554 (equal? '(a)
555 (take '(a . b) 1)))
556
557 (pass-if "'(a b . c) 1"
558 (equal? '(a)
559 (take '(a b . c) 1)))
560
561 (pass-if "'(a b . c) 2"
562 (equal? '(a b)
563 (take '(a b . c) 2))))
9a029e41
KR
564
565;;
566;; partition
567;;
568
569(define (test-partition pred list kept-good dropped-good)
570 (call-with-values (lambda ()
571 (partition pred list))
572 (lambda (kept dropped)
573 (and (equal? kept kept-good)
574 (equal? dropped dropped-good)))))
575
576(with-test-prefix "partition"
577
578 (pass-if "with dropped tail"
579 (test-partition even? '(1 2 3 4 5 6 7)
580 '(2 4 6) '(1 3 5 7)))
581
582 (pass-if "with kept tail"
583 (test-partition even? '(1 2 3 4 5 6)
584 '(2 4 6) '(1 3 5)))
585
586 (pass-if "with everything dropped"
587 (test-partition even? '(1 3 5 7)
588 '() '(1 3 5 7)))
589
590 (pass-if "with everything kept"
591 (test-partition even? '(2 4 6)
592 '(2 4 6) '()))
593
594 (pass-if "with empty list"
595 (test-partition even? '()
596 '() '()))
597
598 (pass-if "with reasonably long list"
599 ;; the old implementation from SRFI-1 reference implementation
600 ;; would signal a stack-overflow for a list of only 500 elements!
601 (call-with-values (lambda ()
602 (partition even?
603 (make-list 10000 1)))
604 (lambda (even odd)
605 (and (= (length odd) 10000)
606 (= (length even) 0))))))
607