1 ;;; cl-macs-tests.el --- tests for emacs-lisp/cl-macs.el -*- lexical-binding:t -*-
3 ;; Copyright (C) 2017-2018 Free Software Foundation, Inc.
5 ;; This file is part of GNU Emacs.
7 ;; This program is free software: you can redistribute it and/or
8 ;; modify it under the terms of the GNU General Public License as
9 ;; published by the Free Software Foundation, either version 3 of the
10 ;; License, or (at your option) any later version.
12 ;; This program is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with this program. If not, see `https://www.gnu.org/licenses/'.
29 ;;;; cl-loop tests -- many adapted from Steele's CLtL2
31 ;;; ANSI 6.1.1.7 Destructuring
32 (ert-deftest cl-macs-loop-and-assignment
()
34 :expected-result
:failed
35 (should (equal (cl-loop for numlist in
'((1 2 4.0) (5 6 8.3) (8 9 10.4))
36 for a
= (cl-first numlist
)
37 and b
= (cl-second numlist
)
38 and c
= (cl-third numlist
)
40 '((4.0
2 1) (8.3
6 5) (10.4
9 8)))))
42 (ert-deftest cl-macs-loop-destructure
()
43 (should (equal (cl-loop for
(a b c
) in
'((1 2 4.0) (5 6 8.3) (8 9 10.4))
45 '((4.0
2 1) (8.3
6 5) (10.4
9 8)))))
47 (ert-deftest cl-macs-loop-destructure-nil
()
48 (should (equal (cl-loop for
(a nil b
) = '(1 2 3)
49 do
(cl-return (list a b
)))
52 (ert-deftest cl-macs-loop-destructure-cons
()
53 (should (equal (cl-loop for
((a . b
) (c . d
)) in
54 '(((1.2 .
2.4) (3 .
4)) ((3.4 .
4.6) (5 .
6)))
55 collect
(list a b c d
))
56 '((1.2
2.4 3 4) (3.4
4.6 5 6)))))
58 (ert-deftest cl-loop-destructuring-with
()
59 (should (equal (cl-loop with
(a b c
) = '(1 2 3) return
(+ a b c
)) 6)))
61 ;;; 6.1.2.1.1 The for-as-arithmetic subclause
62 (ert-deftest cl-macs-loop-for-as-arith
()
63 "Test various for-as-arithmetic subclauses."
64 :expected-result
:failed
65 (should (equal (cl-loop for i to
10 by
3 collect i
)
67 (should (equal (cl-loop for i upto
3 collect i
)
69 (should (equal (cl-loop for i below
3 collect i
)
71 (should (equal (cl-loop for i below
10 by
2 collect i
)
73 (should (equal (cl-loop for i downfrom
10 above
4 by
2 collect i
)
75 (should (equal (cl-loop for i from
10 downto
1 by
3 collect i
)
77 (should (equal (cl-loop for i above
0 by
2 downfrom
10 collect i
)
79 (should (equal (cl-loop for i downto
10 from
15 collect i
)
80 '(15 14 13 12 11 10))))
82 (ert-deftest cl-macs-loop-for-as-arith-order-side-effects
()
83 "Test side effects generated by different arithmetic phrase order."
84 :expected-result
:failed
86 (equal (let ((x 1)) (cl-loop for i from x to
10 by
(cl-incf x
) collect i
))
89 (equal (let ((x 1)) (cl-loop for i from x by
(cl-incf x
) to
10 collect i
))
92 (equal (let ((x 1)) (cl-loop for i to
10 from x by
(cl-incf x
) collect i
))
95 (equal (let ((x 1)) (cl-loop for i to
10 by
(cl-incf x
) from x collect i
))
98 (equal (let ((x 1)) (cl-loop for i by
(cl-incf x
) from x to
10 collect i
))
101 (equal (let ((x 1)) (cl-loop for i by
(cl-incf x
) to
10 from x collect i
))
104 (ert-deftest cl-macs-loop-for-as-arith-invalid
()
105 "Test for invalid phrase combinations."
106 :expected-result
:failed
107 ;; Mixing arithmetic-up and arithmetic-down* subclauses
108 (should-error (cl-loop for i downfrom
10 below
20 collect i
))
109 (should-error (cl-loop for i upfrom
20 above
10 collect i
))
110 (should-error (cl-loop for i upto
10 by
2 downfrom
5))
112 (should-error (cl-loop for i from
10 to
20 above
10))
113 (should-error (cl-loop for i from
10 to
20 upfrom
0))
114 (should-error (cl-loop for i by
2 to
10 by
5))
116 (should-error (cl-loop for i by -
1))
117 ;; no step given for a downward loop
118 (should-error (cl-loop for i downto -
5 collect i
)))
121 ;;; 6.1.2.1.2 The for-as-in-list subclause
122 (ert-deftest cl-macs-loop-for-as-in-list
()
123 (should (equal (cl-loop for x in
'(1 2 3 4 5 6) collect
(* x x
))
125 (should (equal (cl-loop for x in
'(1 2 3 4 5 6) by
#'cddr collect
(* x x
))
128 ;;; 6.1.2.1.3 The for-as-on-list subclause
129 (ert-deftest cl-macs-loop-for-as-on-list
()
130 (should (equal (cl-loop for x on
'(1 2 3 4) collect x
)
131 '((1 2 3 4) (2 3 4) (3 4) (4))))
132 (should (equal (cl-loop as
(item) on
'(1 2 3 4) by
#'cddr collect item
)
135 ;;; 6.1.2.1.4 The for-as-equals-then subclause
136 (ert-deftest cl-macs-loop-for-as-equals-then
()
137 (should (equal (cl-loop for item
= 1 then
(+ item
10)
141 (should (equal (cl-loop for x below
5 for y
= nil then x collect
(list x y
))
142 '((0 nil
) (1 1) (2 2) (3 3) (4 4))))
143 (should (equal (cl-loop for x below
5 and y
= nil then x collect
(list x y
))
144 '((0 nil
) (1 0) (2 1) (3 2) (4 3))))
145 (should (equal (cl-loop for x below
3 for y
= (+ 10 x
) nconc
(list x y
))
147 (should (equal (cl-loop with start
= 5
148 for x
= start then
(cl-incf start
)
153 ;;; 6.1.2.1.5 The for-as-across subclause
154 (ert-deftest cl-macs-loop-for-as-across
()
155 (should (string= (cl-loop for x across
"aeiou"
156 concat
(char-to-string x
))
158 (should (equal (cl-loop for v across
(vector 1 2 3) vconcat
(vector v
(+ 10 v
)))
161 ;;; 6.1.2.1.6 The for-as-hash subclause
162 (ert-deftest cl-macs-loop-for-as-hash
()
163 ;; example in Emacs manual 4.7.3
164 (should (equal (let ((hash (make-hash-table)))
165 (setf (gethash 1 hash
) 10)
166 (setf (gethash "test" hash
) "string")
167 (setf (gethash 'test hash
) 'value
)
168 (cl-loop for k being the hash-keys of hash
169 using
(hash-values v
)
171 '((1 10) ("test" "string") (test value
)))))
173 ;;; 6.1.2.2 Local Variable Initializations
174 (ert-deftest cl-macs-loop-with
()
175 (should (equal (cl-loop with a
= 1
180 (should (equal (let ((a 5)
185 return
(list a b c
)))
187 (should (and (equal (cl-loop for i below
3 with loop-with
188 do
(push (* i i
) loop-with
)
189 finally
(cl-return loop-with
))
191 (not (boundp 'loop-with
)))))
193 ;;; 6.1.3 Value Accumulation Clauses
194 (ert-deftest cl-macs-loop-accum
()
195 (should (equal (cl-loop for name in
'(fred sue alice joe june
)
196 for kids in
'((bob ken
) () () (kris sunshine
) ())
199 '(fred bob ken sue alice joe kris sunshine june
))))
201 (ert-deftest cl-macs-loop-collect
()
202 (should (equal (cl-loop for i in
'(bird 3 4 turtle
(1 .
4) horse cat
)
203 when
(symbolp i
) collect i
)
204 '(bird turtle horse cat
)))
205 (should (equal (cl-loop for i from
1 to
10
206 if
(cl-oddp i
) collect i
)
208 (should (equal (cl-loop for i in
'(a b c d e f g
) by
#'cddr
209 collect i into my-list
210 finally return
(nbutlast my-list
))
213 (ert-deftest cl-macs-loop-append
/nconc
()
214 (should (equal (cl-loop for x in
'((a) (b) ((c)))
217 (should (equal (cl-loop for i upfrom
0
219 nconc
(if (cl-evenp i
) (list x
) nil
))
222 (ert-deftest cl-macs-loop-count
()
223 (should (eql (cl-loop for i in
'(a b nil c nil d e
)
227 (ert-deftest cl-macs-loop-max
/min
()
228 (should (eql (cl-loop for i in
'(2 1 5 3 4)
231 (should (eql (cl-loop for i in
'(2 1 5 3 4)
234 (should (equal (cl-loop with series
= '(4.3
1.2 5.7)
236 minimize
(round v
) into min-result
237 maximize
(round v
) into max-result
238 collect
(list min-result max-result
))
239 '((4 4) (1 4) (1 6)))))
241 (ert-deftest cl-macs-loop-sum
()
242 (should (eql (cl-loop for i in
'(1 2 3 4 5)
245 (should (eql (cl-loop with series
= '(1.2
4.3 5.7)
250 ;;; 6.1.4 Termination Test Clauses
251 (ert-deftest cl-macs-loop-repeat
()
252 (should (equal (cl-loop with n
= 4
256 (should (equal (cl-loop for i upto
5
261 (ert-deftest cl-macs-loop-always
()
262 (should (cl-loop for i from
0 to
10
264 (should-not (cl-loop for i from
0 to
10
266 finally
(cl-return "you won't see this"))))
268 (ert-deftest cl-macs-loop-never
()
269 (should (cl-loop for i from
0 to
10
271 (should-not (cl-loop never t
272 finally
(cl-return "you won't see this"))))
274 (ert-deftest cl-macs-loop-thereis
()
275 (should (eql (cl-loop for i from
0
276 thereis
(when (> i
10) i
))
278 (should (string= (cl-loop thereis
"Here is my value"
279 finally
(cl-return "you won't see this"))
281 (should (cl-loop for i to
10
283 finally
(cl-return i
))))
285 (ert-deftest cl-macs-loop-anon-collection-conditional
()
286 "Always/never/thereis should error when used with an anonymous
288 :expected-result
:failed
289 (should-error (cl-loop always nil collect t
))
290 (should-error (cl-loop never t nconc t
))
291 (should-error (cl-loop thereis t append t
)))
293 (ert-deftest cl-macs-loop-while
()
294 (should (equal (let ((stack '(a b c d e f
)))
296 for item
= (length stack
) then
(pop stack
)
300 (ert-deftest cl-macs-loop-until
()
301 (should (equal (cl-loop for i to
100
305 '(10 0 10 1 10 2 10))))
307 ;;; 6.1.5 Unconditional Execution Clauses
308 (ert-deftest cl-macs-loop-do
()
309 (should (equal (cl-loop with list
314 finally
(cl-return list
))
316 (should (equal (cl-loop with res
= 0
318 doing
(cl-incf res i
)
319 finally
(cl-return res
))
321 (should (equal (cl-loop for i from
10
324 finally
(cl-return 0))
327 ;;; 6.1.6 Conditional Execution Clauses
328 (ert-deftest cl-macs-loop-when
()
329 (should (equal (cl-loop for i in
'(1 2 3 4 5 6)
333 (should (eql (cl-loop for i in
'(1 2 3 4 5 6)
338 (should (equal (cl-loop for elt in
'(1 a
2 "a" (3 4) 5 6)
340 when
(cl-evenp elt
) collect elt into even
341 else collect elt into odd
343 when
(symbolp elt
) collect elt into syms
344 else collect elt into other
345 finally return
(list even odd syms other
))
346 '((2 6) (1 5) (a) ("a" (3 4))))))
348 (ert-deftest cl-macs-loop-if
()
349 (should (equal (cl-loop for i to
5
352 and when
(and (= i
2) 'two
)
357 (should (equal (cl-loop for i to
5
360 and when
(and (= i
2) 'two
)
365 '(0 "low" 2 two
"low" 4)))
366 (should (equal (cl-loop with funny-numbers
= '(6 13 -
1)
372 and if
(memq x funny-numbers
) return
(cdr it
)
373 finally return
(vector odds evens
))
374 [(1 3 5 7 9) (0 2 4 6 8)])))
376 (ert-deftest cl-macs-loop-unless
()
377 (should (equal (cl-loop for i to
5
382 '(0 1 2 three
4 5))))
385 ;;; 6.1.7.1 Control Transfer Clauses
386 (ert-deftest cl-macs-loop-named
()
387 (should (eql (cl-loop named finished
390 do
(cl-return-from finished i
))
393 ;;; 6.1.7.2 Initial and Final Execution
394 (ert-deftest cl-macs-loop-initially
()
395 (should (equal (let ((var (list 1 2 3 4 5)))
396 (cl-loop for i in var
400 (setf (cadr var
) 20)))
403 (ert-deftest cl-macs-loop-finally
()
404 (should (eql (cl-loop for i from
10
411 ;;; Emacs extensions to loop
412 (ert-deftest cl-macs-loop-in-ref
()
413 (should (equal (cl-loop with my-list
= (list 1 2 3 4 5)
416 finally return my-list
)
419 (ert-deftest cl-macs-loop-across-ref
()
420 (should (equal (cl-loop with my-vec
= ["one" "two" "three"]
421 for x across-ref my-vec
422 do
(setf (aref x
0) (upcase (aref x
0)))
423 finally return my-vec
)
424 ["One" "Two" "Three"])))
426 (ert-deftest cl-macs-loop-being-elements
()
427 (should (equal (let ((var "StRiNG"))
428 (cl-loop for x being the elements of var
429 collect
(downcase x
)))
430 (string-to-list "string"))))
432 (ert-deftest cl-macs-loop-being-elements-of-ref
()
433 (should (equal (let ((var (list 1 2 3 4 5)))
434 (cl-loop for x being the elements of-ref var
439 (ert-deftest cl-macs-loop-being-symbols
()
440 (should (eq (cl-loop for sym being the symbols
441 when
(eq sym
'cl-loop
)
445 (ert-deftest cl-macs-loop-being-keymap
()
446 (should (equal (let ((map (make-sparse-keymap))
447 (parent (make-sparse-keymap))
449 (define-key map
"f" #'forward-char
)
450 (define-key map
"b" #'backward-char
)
451 (define-key parent
"n" #'next-line
)
452 (define-key parent
"p" #'previous-line
)
453 (set-keymap-parent map parent
)
454 (cl-loop for b being the key-bindings of map
456 do
(push (list c b
) res
))
457 (cl-loop for s being the key-seqs of map
458 using
(key-bindings b
)
459 do
(push (list (cl-copy-seq s
) b
) res
))
461 '(([?n
] next-line
) ([?p
] previous-line
)
462 ([?f
] forward-char
) ([?b
] backward-char
)
463 (?n next-line
) (?p previous-line
)
464 (?f forward-char
) (?b backward-char
)))))
466 (ert-deftest cl-macs-loop-being-overlays
()
467 (should (equal (let ((ov (make-overlay (point) (point))))
468 (overlay-put ov
'prop
"test")
469 (cl-loop for o being the overlays
471 return
(overlay-get o
'prop
)))
474 (ert-deftest cl-macs-loop-being-frames
()
475 (should (eq (cl-loop with selected
= (selected-frame)
476 for frame being the frames
477 when
(eq frame selected
)
481 (ert-deftest cl-macs-loop-being-windows
()
482 (should (eq (cl-loop with selected
= (selected-window)
483 for window being the windows
484 when
(eq window selected
)
488 (ert-deftest cl-macs-loop-being-buffers
()
489 (should (eq (cl-loop with current
= (current-buffer)
490 for buffer being the buffers
491 when
(eq buffer current
)
495 (ert-deftest cl-macs-loop-vconcat
()
496 (should (equal (cl-loop for x in
(list 1 2 3 4 5)
497 vconcat
(vector (1+ x
)))
500 (ert-deftest cl-macs-loop-for-as-equals-and
()
501 "Test for https://debbugs.gnu.org/29799 ."
502 (let ((arr (make-vector 3 0)))
503 (should (equal '((0 0) (1 1) (2 2))
504 (cl-loop for k below
3 for x
= k and z
= (elt arr k
)
505 collect
(list k x
))))))
508 (ert-deftest cl-defstruct
/builtin-type
()
510 (macroexpand '(cl-defstruct hash-table
))
511 :type
'wrong-type-argument
)
513 (macroexpand '(cl-defstruct (hash-table (:predicate hash-table-p
))))
514 :type
'wrong-type-argument
))
516 ;;; cl-macs-tests.el ends here