* bug#27559: 26.0.50; [PATCH] Add tests for cl-macs.el
@ 2017-07-03 5:54 Alex
2017-07-03 9:42 ` Tino Calancha
0 siblings, 1 reply; 9+ messages in thread
From: Alex @ 2017-07-03 5:54 UTC (permalink / raw)
To: 27559
[-- Attachment #1: Type: text/plain, Size: 442 bytes --]
This initial version just includes tests for cl-loop, many of which were
adapted from Common Lisp the Language 2nd Edition. They are mostly
ordered by their appearance in the Hyperspec.
When I was just about finished I realized that I could have just used an
ert wrapper macro to avoid all of the (eval (quote ...))) business,
which would have the added bonus of easily evaluating most of the tests
lexically. Should I redo it in this way?
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: cl-loop tests --]
[-- Type: text/x-diff, Size: 24622 bytes --]
From 3c1abd54e52a01808de1ebd67a4fc49465700c11 Mon Sep 17 00:00:00 2001
From: Alexander Gramiak <agrambot@gmail.com>
Date: Sun, 2 Jul 2017 23:46:50 -0600
Subject: [PATCH] Add tests for cl-macs.el
* test/lisp/emacs-lisp/cl-lib-tests.el (cl-lib-test-loop): Remove this
duplicate.
(cl-loop-destructuring-with): Move to cl-macs-tests.el.
* test/lisp/emacs-lisp/cl-macs-tests.el: New file.
---
test/lisp/emacs-lisp/cl-lib-tests.el | 10 +-
test/lisp/emacs-lisp/cl-macs-tests.el | 507 ++++++++++++++++++++++++++++++++++
2 files changed, 509 insertions(+), 8 deletions(-)
create mode 100644 test/lisp/emacs-lisp/cl-macs-tests.el
diff --git a/test/lisp/emacs-lisp/cl-lib-tests.el b/test/lisp/emacs-lisp/cl-lib-tests.el
index 65bd97f3b2..e1f0955839 100644
--- a/test/lisp/emacs-lisp/cl-lib-tests.el
+++ b/test/lisp/emacs-lisp/cl-lib-tests.el
@@ -1,4 +1,4 @@
-;;; cl-lib.el --- tests for emacs-lisp/cl-lib.el -*- lexical-binding:t -*-
+;;; cl-lib-tests.el --- tests for emacs-lisp/cl-lib.el -*- lexical-binding:t -*-
;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
@@ -195,9 +195,6 @@
(should (eql (cl-mismatch "Aa" "aA") 0))
(should (eql (cl-mismatch '(a b c) '(a b d)) 2)))
-(ert-deftest cl-lib-test-loop ()
- (should (eql (cl-loop with (a b c) = '(1 2 3) return (+ a b c)) 6)))
-
(ert-deftest cl-lib-keyword-names-versus-values ()
(should (equal
(funcall (cl-function (lambda (&key a b) (list a b)))
@@ -480,9 +477,6 @@
(should (= 239 (cl-parse-integer "zzef" :radix 16 :start 2)))
(should (= -123 (cl-parse-integer " -123 "))))
-(ert-deftest cl-loop-destructuring-with ()
- (should (equal (cl-loop with (a b c) = '(1 2 3) return (+ a b c)) 6)))
-
(ert-deftest cl-flet-test ()
(should (equal (cl-flet ((f1 (x) x)) (let ((x #'f1)) (funcall x 5))) 5)))
@@ -548,4 +542,4 @@ cl-lib-symbol-macrolet-4+5
(should cl-old-struct-compat-mode)
(cl-old-struct-compat-mode (if saved 1 -1))))
-;;; cl-lib.el ends here
+;;; cl-lib-tests.el ends here
diff --git a/test/lisp/emacs-lisp/cl-macs-tests.el b/test/lisp/emacs-lisp/cl-macs-tests.el
new file mode 100644
index 0000000000..03ce655fb8
--- /dev/null
+++ b/test/lisp/emacs-lisp/cl-macs-tests.el
@@ -0,0 +1,507 @@
+;;; cl-macs-tests.el --- tests for emacs-lisp/cl-macs.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see `http://www.gnu.org/licenses/'.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'cl-macs)
+(require 'ert)
+
+\f
+;;;; cl-loop tests -- many adapted from Steele's CLtL2
+
+;;; ANSI 6.1.1.7 Destructuring
+(ert-deftest cl-macs-loop-and-assignment ()
+ ;; Bug#6583
+ :expected-result :failed
+ (should (equal (eval '(cl-loop for numlist in '((1 2 4.0) (5 6 8.3) (8 9 10.4))
+ for a = (cl-first numlist)
+ and b = (cl-second numlist)
+ and c = (cl-third numlist)
+ collect (list c b a)))
+ '((4.0 2 1) (8.3 6 5) (10.4 9 8)))))
+
+(ert-deftest cl-macs-loop-destructure ()
+ (should (equal (eval '(cl-loop for (a b c) in '((1 2 4.0) (5 6 8.3) (8 9 10.4))
+ collect (list c b a)))
+ '((4.0 2 1) (8.3 6 5) (10.4 9 8)))))
+
+(ert-deftest cl-macs-loop-destructure-nil ()
+ (should (equal (eval '(cl-loop for (a nil b) = '(1 2 3)
+ do (cl-return (list a b))))
+ '(1 3))))
+
+(ert-deftest cl-macs-loop-destructure-cons ()
+ (should (equal (eval '(cl-loop for ((a . b) (c . d)) in
+ '(((1.2 . 2.4) (3 . 4)) ((3.4 . 4.6) (5 . 6)))
+ collect (list a b c d)))
+ '((1.2 2.4 3 4) (3.4 4.6 5 6)))))
+
+(ert-deftest cl-loop-destructuring-with ()
+ (should (equal (eval '(cl-loop with (a b c) = '(1 2 3) return (+ a b c))) 6)))
+
+;;; 6.1.2.1.1 The for-as-arithmetic subclause
+(ert-deftest cl-macs-loop-for-as-arith ()
+ "Test various for-as-arithmetic subclauses."
+ :expected-result :failed
+ (should (equal (eval '(cl-loop for i to 10 by 3 collect i))
+ '(0 3 6 9)))
+ (should (equal (eval '(cl-loop for i upto 3 collect i))
+ '(0 1 2 3)))
+ (should (equal (eval '(cl-loop for i below 3 collect i))
+ '(0 1 2)))
+ (should (equal (eval '(cl-loop for i below 10 by 2 collect i))
+ '(0 2 4 6 8)))
+ (should (equal (eval '(cl-loop for i downfrom 10 above 4 by 2 collect i))
+ '(10 8 6)))
+ (should (equal (eval '(cl-loop for i from 10 downto 1 by 3 collect i))
+ '(10 7 4 1)))
+ (should (equal (eval '(cl-loop for i above 0 by 2 downfrom 10 collect i))
+ '(10 8 6 4 2)))
+ (should (equal (eval '(cl-loop for i downto 10 from 15 collect i))
+ '(15 14 13 12 11 10))))
+
+(ert-deftest cl-macs-loop-for-as-arith-order-side-effects ()
+ "Test side effects generated by different arithmetic phrase order."
+ :expected-result :failed
+ (should
+ (equal (eval '(let ((x 1))
+ (cl-loop for i from x to 10 by (cl-incf x) collect i)))
+ '(1 3 5 7 9)))
+ (should
+ (equal (eval '(let ((x 1))
+ (cl-loop for i from x by (cl-incf x) to 10 collect i)))
+ '(1 3 5 7 9)))
+ (should
+ (equal (eval '(let ((x 1))
+ (cl-loop for i to 10 from x by (cl-incf x) collect i)))
+ '(1 3 5 7 9)))
+ (should
+ (equal (eval '(let ((x 1))
+ (cl-loop for i to 10 by (cl-incf x) from x collect i)))
+ '(2 4 6 8 10)))
+ (should
+ (equal (eval '(let ((x 1))
+ (cl-loop for i by (cl-incf x) from x to 10 collect i)))
+ '(2 4 6 8 10)))
+ (should
+ (equal (eval '(let ((x 1))
+ (cl-loop for i by (cl-incf x) to 10 from x collect i)))
+ '(2 4 6 8 10))))
+
+(ert-deftest cl-macs-loop-for-as-arith-invalid ()
+ "Test for invalid phrase combinations."
+ :expected-result :failed
+ ;; Mixing arithmetic-up and arithmetic-down* subclauses
+ (should-error (eval '(cl-loop for i downfrom 10 below 20 collect i)))
+ (should-error (eval '(cl-loop for i upfrom 20 above 10 collect i)))
+ (should-error (eval '(cl-loop for i upto 10 by 2 downfrom 5)))
+ ;; Repeated phrases
+ (should-error (eval '(cl-loop for i from 10 to 20 above 10)))
+ (should-error (eval '(cl-loop for i from 10 to 20 upfrom 0)))
+ (should-error (eval '(cl-loop for i by 2 to 10 by 5)))
+ ;; negative step
+ (should-error (eval '(cl-loop for i by -1)))
+ ;; no step given for a downward loop
+ (should-error (eval '(cl-loop for i downto -5 collect i))))
+
+
+;;; 6.1.2.1.2 The for-as-in-list subclause
+(ert-deftest cl-macs-loop-for-as-in-list ()
+ (should (equal (eval '(cl-loop for x in '(1 2 3 4 5 6) collect (* x x)))
+ '(1 4 9 16 25 36)))
+ (should (equal (eval '(cl-loop for x in '(1 2 3 4 5 6) by #'cddr collect (* x x)))
+ '(1 9 25))))
+
+;;; 6.1.2.1.3 The for-as-on-list subclause
+(ert-deftest cl-macs-loop-for-as-on-list ()
+ (should (equal (eval '(cl-loop for x on '(1 2 3 4) collect x))
+ '((1 2 3 4) (2 3 4) (3 4) (4))))
+ (should (equal (eval '(cl-loop as (item) on '(1 2 3 4) by #'cddr collect item))
+ '(1 3))))
+
+;;; 6.1.2.1.4 The for-as-equals-then subclause
+(ert-deftest cl-macs-loop-for-as-equals-then ()
+ (should (equal (eval '(cl-loop for item = 1 then (+ item 10)
+ repeat 5
+ collect item))
+ '(1 11 21 31 41)))
+ (should (equal (eval '(cl-loop for x below 5 for y = nil then x collect (list x y)))
+ '((0 nil) (1 1) (2 2) (3 3) (4 4))))
+ (should (equal (eval '(cl-loop for x below 5 and y = nil then x collect (list x y)))
+ '((0 nil) (1 0) (2 1) (3 2) (4 3))))
+ (should (equal (eval '(cl-loop for x below 3 for y = (+ 10 x) nconc (list x y)))
+ '(0 10 1 11 2 12)))
+ (should (equal (eval '(cl-loop with start = 5
+ for x = start
+ then (cl-incf start)
+ repeat 5
+ collect x))
+ '(5 6 7 8 9))))
+
+;;; 6.1.2.1.5 The for-as-across subclause
+(ert-deftest cl-macs-loop-for-as-across ()
+ (should (string= (eval '(cl-loop for x across "aeiou"
+ concat (char-to-string x)))
+ "aeiou"))
+ (should (equal (eval '(cl-loop for v across (vector 1 2 3) vconcat (vector v (+ 10 v))))
+ [1 11 2 12 3 13])))
+
+;;; 6.1.2.1.6 The for-as-hash subclause
+(ert-deftest cl-macs-loop-for-as-hash ()
+ ;; example in Emacs manual 4.7.3
+ (should (equal (eval '(let ((hash (make-hash-table)))
+ (setf (gethash 1 hash) 10)
+ (setf (gethash "test" hash) "string")
+ (setf (gethash 'test hash) 'value)
+ (cl-loop for k being the hash-keys of hash
+ using (hash-values v)
+ collect (list k v))))
+ '((1 10) ("test" "string") (test value)))))
+
+;;; 6.1.2.2 Local Variable Initializations
+(ert-deftest cl-macs-loop-with ()
+ (should (equal (eval '(cl-loop with a = 1
+ with b = (+ a 2)
+ with c = (+ b 3)
+ return (list a b c)))
+ '(1 3 6)))
+ (should (equal (eval '(let ((a 5)
+ (b 10))
+ (cl-loop with a = 1
+ and b = (+ a 2)
+ and c = (+ b 3)
+ return (list a b c))))
+ '(1 7 13)))
+ (should (and (equal (eval '(cl-loop for i below 3 with loop-with
+ do (push (* i i) loop-with)
+ finally (cl-return loop-with)))
+ '(4 1 0))
+ (not (boundp 'loop-with)))))
+
+;;; 6.1.3 Value Accumulation Clauses
+(ert-deftest cl-macs-loop-accum ()
+ (should (equal (eval '(cl-loop for name in '(fred sue alice joe june)
+ for kids in '((bob ken) () () (kris sunshine) ())
+ collect name
+ append kids))
+ '(fred bob ken sue alice joe kris sunshine june))))
+
+(ert-deftest cl-macs-loop-collect ()
+ (should (equal (eval '(cl-loop for i in '(bird 3 4 turtle (1 . 4) horse cat)
+ when (symbolp i) collect i))
+ '(bird turtle horse cat)))
+ (should (equal (eval '(cl-loop for i from 1 to 10
+ if (cl-oddp i) collect i))
+ '(1 3 5 7 9)))
+ (should (equal (eval '(cl-loop for i in '(a b c d e f g) by #'cddr
+ collect i into my-list
+ finally return (nbutlast my-list)))
+ '(a c e))))
+
+(ert-deftest cl-macs-loop-append/nconc ()
+ (should (equal (eval '(cl-loop for x in '((a) (b) ((c)))
+ append x))
+ '(a b (c))))
+ (should (equal (eval '(cl-loop for i upfrom 0
+ as x in '(a b (c))
+ nconc (if (cl-evenp i) (list x) nil)))
+ '(a (c)))))
+
+(ert-deftest cl-macs-loop-count ()
+ (should (eql (eval '(cl-loop for i in '(a b nil c nil d e)
+ count i))
+ 5)))
+
+(ert-deftest cl-macs-loop-max/min ()
+ (should (eql (eval '(cl-loop for i in '(2 1 5 3 4)
+ maximize i))
+ 5))
+ (should (eql (eval '(cl-loop for i in '(2 1 5 3 4)
+ minimize i))
+ 1))
+ (should (equal (eval '(cl-loop with series = '(4.3 1.2 5.7)
+ for v in series
+ minimize (round v) into min-result
+ maximize (round v) into max-result
+ collect (list min-result max-result)))
+ '((4 4) (1 4) (1 6)))))
+
+(ert-deftest cl-macs-loop-sum ()
+ (should (eql (eval '(cl-loop for i in '(1 2 3 4 5)
+ sum i))
+ 15))
+ (should (eql (eval '(cl-loop with series = '(1.2 4.3 5.7)
+ for v in series
+ sum (* 2.0 v)))
+ 22.4)))
+
+;;; 6.1.4 Termination Test Clauses
+(ert-deftest cl-macs-loop-repeat ()
+ (should (equal (eval '(cl-loop with n = 4
+ repeat (1+ n)
+ collect n))
+ '(4 4 4 4 4)))
+ (should (equal (eval '(cl-loop for i upto 5
+ repeat 3
+ collect i))
+ '(0 1 2))))
+
+(ert-deftest cl-macs-loop-always ()
+ (should (eval '(cl-loop for i from 0 to 10
+ always (< i 11))))
+ (should-not (eval '(cl-loop for i from 0 to 10
+ always (< i 9)
+ finally (cl-return "you won't see this")))))
+
+(ert-deftest cl-macs-loop-never ()
+ (should (eval '(cl-loop for i from 0 to 10
+ never (> i 11))))
+ (should-not (eval '(cl-loop never t
+ finally (cl-return "you won't see this")))))
+
+(ert-deftest cl-macs-loop-thereis ()
+ (should (eql (eval '(cl-loop for i from 0
+ thereis (when (> i 10) i)))
+ 11))
+ (should (string= (eval '(cl-loop thereis "Here is my value"
+ finally (cl-return "you won't see this")))
+ "Here is my value"))
+ (should (eval '(cl-loop for i to 10
+ thereis (> i 11)
+ finally (cl-return i)))))
+
+(ert-deftest cl-macs-loop-anon-collection-conditional ()
+ "Always/never/thereis should error when used with an anonymous
+collection clause."
+ :expected-result :failed
+ (should-error (eval '(cl-loop always nil collect t)))
+ (should-error (eval '(cl-loop never t nconc t)))
+ (should-error (eval '(cl-loop thereis t append t))))
+
+(ert-deftest cl-macs-loop-while ()
+ (should (equal (eval '(let ((stack '(a b c d e f)))
+ (cl-loop while stack
+ for item = (length stack) then (pop stack)
+ collect item)))
+ '(6 a b c d e f))))
+
+(ert-deftest cl-macs-loop-until ()
+ (should (equal (eval '(cl-loop for i to 100
+ collect 10
+ until (= i 3)
+ collect i))
+ '(10 0 10 1 10 2 10))))
+
+;;; 6.1.5 Unconditional Execution Clauses
+(ert-deftest cl-macs-loop-do ()
+ (should (equal (eval '(cl-loop with list
+ for i from 1 to 3
+ do
+ (push 10 list)
+ (push i list)
+ finally (cl-return list)))
+ '(3 10 2 10 1 10)))
+ (should (equal (eval '(cl-loop with res = 0
+ for i from 1 to 10
+ doing (cl-incf res i)
+ finally (cl-return res)))
+ 55))
+ (should (equal (eval '(cl-loop for i from 10
+ do (when (= i 15)
+ (cl-return i))
+ finally (cl-return 0)))
+ 15)))
+
+;;; 6.1.6 Conditional Execution Clauses
+(ert-deftest cl-macs-loop-when ()
+ (should (equal (eval '(cl-loop for i in '(1 2 3 4 5 6)
+ when (and (> i 3) i)
+ collect it))
+ '(4 5 6)))
+ (should (eql (eval '(cl-loop for i in '(1 2 3 4 5 6)
+ when (and (> i 3) i)
+ return it))
+ 4))
+
+ (should (equal (eval '(cl-loop for elt in '(1 a 2 "a" (3 4) 5 6)
+ when (numberp elt)
+ when (cl-evenp elt) collect elt into even
+ else collect elt into odd
+ else
+ when (symbolp elt) collect elt into syms
+ else collect elt into other
+ finally return (list even odd syms other)))
+ '((2 6) (1 5) (a) ("a" (3 4))))))
+
+(ert-deftest cl-macs-loop-if ()
+ (should (equal (eval '(cl-loop for i to 5
+ if (cl-evenp i)
+ collect i
+ and when (and (= i 2) 'two)
+ collect it
+ and if (< i 3)
+ collect "low"))
+ '(0 2 two "low" 4)))
+ (should (equal (eval '(cl-loop for i to 5
+ if (cl-evenp i)
+ collect i
+ and when (and (= i 2) 'two)
+ collect it
+ end
+ and if (< i 3)
+ collect "low"))
+ '(0 "low" 2 two "low" 4)))
+ (should (equal (eval '(cl-loop with funny-numbers = '(6 13 -1)
+ for x below 10
+ if (cl-evenp x)
+ collect x into evens
+ else
+ collect x into odds
+ and if (memq x funny-numbers) return (cdr it)
+ finally return (vector odds evens)))
+ [(1 3 5 7 9) (0 2 4 6 8)])))
+
+(ert-deftest cl-macs-loop-unless ()
+ (should (equal (eval '(cl-loop for i to 5
+ unless (= i 3)
+ collect i
+ else
+ collect 'three))
+ '(0 1 2 three 4 5))))
+
+
+;;; 6.1.7.1 Control Transfer Clauses
+(ert-deftest cl-macs-loop-named ()
+ (should (eql (eval '(cl-loop named finished
+ for i to 10
+ when (> (* i i) 30)
+ do (cl-return-from finished i)))
+ 6)))
+
+;;; 6.1.7.2 Initial and Final Execution
+(ert-deftest cl-macs-loop-initially ()
+ (should (equal (eval '(let ((var (list 1 2 3 4 5)))
+ (cl-loop for i in var
+ collect i
+ initially
+ (setf (car var) 10)
+ (setf (cadr var) 20))))
+ '(10 20 3 4 5))))
+
+(ert-deftest cl-macs-loop-finally ()
+ (should (eql (eval '(cl-loop for i from 10
+ finally
+ (cl-incf i 10)
+ (cl-return i)
+ while (< i 20)))
+ 30)))
+
+;;; Emacs extensions to loop
+(ert-deftest cl-macs-loop-in-ref ()
+ (should (equal (eval '(cl-loop with my-list = (list 1 2 3 4 5)
+ for x in-ref my-list
+ do (cl-incf x)
+ finally return my-list))
+ '(2 3 4 5 6))))
+
+(ert-deftest cl-macs-loop-across-ref ()
+ (should (equal (eval '(cl-loop with my-vec = ["one" "two" "three"]
+ for x across-ref my-vec
+ do (setf (aref x 0) (upcase (aref x 0)))
+ finally return my-vec))
+ ["One" "Two" "Three"])))
+
+(ert-deftest cl-macs-loop-being-elements ()
+ (should (equal (eval '(let ((var "StRiNG"))
+ (cl-loop for x being the elements of var
+ collect (downcase x))))
+ (string-to-list "string"))))
+
+(ert-deftest cl-macs-loop-being-elements-of-ref ()
+ (should (equal (eval '(let ((var (list 1 2 3 4 5)))
+ (cl-loop for x being the elements of-ref var
+ do (cl-incf x)
+ finally return var)))
+ '(2 3 4 5 6))))
+
+(ert-deftest cl-macs-loop-being-symbols ()
+ (should (eq (eval '(cl-loop for sym being the symbols
+ when (eq sym 'cl-loop)
+ return 'cl-loop))
+ 'cl-loop)))
+
+(ert-deftest cl-macs-loop-being-keymap ()
+ (should (equal (eval '(let ((map (make-sparse-keymap))
+ (parent (make-sparse-keymap))
+ res)
+ (define-key map "f" #'forward-char)
+ (define-key map "b" #'backward-char)
+ (define-key parent "n" #'next-line)
+ (define-key parent "p" #'previous-line)
+ (set-keymap-parent map parent)
+ (cl-loop for b being the key-bindings of map
+ using (key-codes c)
+ do (push (list c b) res))
+ (cl-loop for s being the key-seqs of map
+ using (key-bindings b)
+ do (push (list (cl-copy-seq s) b) res))
+ res))
+ '(([?n] next-line) ([?p] previous-line)
+ ([?f] forward-char) ([?b] backward-char)
+ (?n next-line) (?p previous-line)
+ (?f forward-char) (?b backward-char)))))
+
+(ert-deftest cl-macs-loop-being-overlays ()
+ (should (equal (eval '(let ((ov (make-overlay (point) (point))))
+ (overlay-put ov 'prop "test")
+ (cl-loop for o being the overlays
+ when (eq o ov)
+ return (overlay-get o 'prop))))
+ "test")))
+
+(ert-deftest cl-macs-loop-being-frames ()
+ (should (eq (eval '(cl-loop with selected = (selected-frame)
+ for frame being the frames
+ when (eq frame selected)
+ return frame))
+ (selected-frame))))
+
+(ert-deftest cl-macs-loop-being-windows ()
+ (should (eq (eval '(cl-loop with selected = (selected-window)
+ for window being the windows
+ when (eq window selected)
+ return window))
+ (selected-window))))
+
+(ert-deftest cl-macs-loop-being-buffers ()
+ (should (eq (eval '(cl-loop with current = (current-buffer)
+ for buffer being the buffers
+ when (eq buffer current)
+ return buffer))
+ (current-buffer))))
+
+(ert-deftest cl-macs-loop-vconcat ()
+ (should (equal (eval '(cl-loop for x in (list 1 2 3 4 5)
+ vconcat (vector (1+ x))))
+ [2 3 4 5 6])))
+
+;;; cl-macs-tests.el ends here
--
2.11.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* bug#27559: 26.0.50; [PATCH] Add tests for cl-macs.el
2017-07-03 5:54 bug#27559: 26.0.50; [PATCH] Add tests for cl-macs.el Alex
@ 2017-07-03 9:42 ` Tino Calancha
2017-07-03 20:23 ` Alex
0 siblings, 1 reply; 9+ messages in thread
From: Tino Calancha @ 2017-07-03 9:42 UTC (permalink / raw)
To: Alex; +Cc: 27559, tino.calancha
Alex <agrambot@gmail.com> writes:
> This initial version just includes tests for cl-loop, many of which were
> adapted from Common Lisp the Language 2nd Edition. They are mostly
> ordered by their appearance in the Hyperspec.
>
> When I was just about finished I realized that I could have just used an
> ert wrapper macro to avoid all of the (eval (quote ...))) business,
> which would have the added bonus of easily evaluating most of the tests
> lexically. Should I redo it in this way?
Thanks! It's very good having all those tests.
I think we can avoid many of the (eval (quote ...)).
In the following patch, i keep just those (eval (quote ...)
where the expansion of `cl-loop' throws an error:
--8<-----------------------------cut here---------------start------------->8---
commit 2cdd8ca7459ff61551ffcb656cbb711f541f5447
Author: Alexander Gramiak <agrambot@gmail.com>
Date: Mon Jul 3 18:29:27 2017 +0900
Add tests for cl-macs.el
* test/lisp/emacs-lisp/cl-lib-tests.el (cl-lib-test-loop): Remove this
duplicate.
(cl-loop-destructuring-with): Move to cl-macs-tests.el.
* test/lisp/emacs-lisp/cl-macs-tests.el: New file.
diff --git a/test/lisp/emacs-lisp/cl-lib-tests.el b/test/lisp/emacs-lisp/cl-lib-tests.el
index 65bd97f3b2..e1f0955839 100644
--- a/test/lisp/emacs-lisp/cl-lib-tests.el
+++ b/test/lisp/emacs-lisp/cl-lib-tests.el
@@ -1,4 +1,4 @@
-;;; cl-lib.el --- tests for emacs-lisp/cl-lib.el -*- lexical-binding:t -*-
+;;; cl-lib-tests.el --- tests for emacs-lisp/cl-lib.el -*- lexical-binding:t -*-
;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
@@ -195,9 +195,6 @@
(should (eql (cl-mismatch "Aa" "aA") 0))
(should (eql (cl-mismatch '(a b c) '(a b d)) 2)))
-(ert-deftest cl-lib-test-loop ()
- (should (eql (cl-loop with (a b c) = '(1 2 3) return (+ a b c)) 6)))
-
(ert-deftest cl-lib-keyword-names-versus-values ()
(should (equal
(funcall (cl-function (lambda (&key a b) (list a b)))
@@ -480,9 +477,6 @@
(should (= 239 (cl-parse-integer "zzef" :radix 16 :start 2)))
(should (= -123 (cl-parse-integer " -123 "))))
-(ert-deftest cl-loop-destructuring-with ()
- (should (equal (cl-loop with (a b c) = '(1 2 3) return (+ a b c)) 6)))
-
(ert-deftest cl-flet-test ()
(should (equal (cl-flet ((f1 (x) x)) (let ((x #'f1)) (funcall x 5))) 5)))
@@ -548,4 +542,4 @@ cl-lib-symbol-macrolet-4+5
(should cl-old-struct-compat-mode)
(cl-old-struct-compat-mode (if saved 1 -1))))
-;;; cl-lib.el ends here
+;;; cl-lib-tests.el ends here
diff --git a/test/lisp/emacs-lisp/cl-macs-tests.el b/test/lisp/emacs-lisp/cl-macs-tests.el
new file mode 100644
index 0000000000..77c62f2d37
--- /dev/null
+++ b/test/lisp/emacs-lisp/cl-macs-tests.el
@@ -0,0 +1,498 @@
+;;; cl-macs-tests.el --- tests for emacs-lisp/cl-macs.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see `http://www.gnu.org/licenses/'.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'cl-macs)
+(require 'ert)
+
+\f
+;;;; cl-loop tests -- many adapted from Steele's CLtL2
+
+;;; ANSI 6.1.1.7 Destructuring
+(ert-deftest cl-macs-loop-and-assignment ()
+ ;; Bug#6583
+ (should-not (equal (cl-loop for numlist in '((1 2 4.0) (5 6 8.3) (8 9 10.4))
+ for a = (cl-first numlist)
+ and b = (cl-second numlist)
+ and c = (cl-third numlist)
+ collect (list c b a))
+ '((4.0 2 1) (8.3 6 5) (10.4 9 8)))))
+
+(ert-deftest cl-macs-loop-destructure ()
+ (should (equal (cl-loop for (a b c) in '((1 2 4.0) (5 6 8.3) (8 9 10.4))
+ collect (list c b a))
+ '((4.0 2 1) (8.3 6 5) (10.4 9 8)))))
+
+(ert-deftest cl-macs-loop-destructure-nil ()
+ (should (equal (cl-loop for (a nil b) = '(1 2 3)
+ do (cl-return (list a b)))
+ '(1 3))))
+
+(ert-deftest cl-macs-loop-destructure-cons ()
+ (should (equal (cl-loop for ((a . b) (c . d)) in
+ '(((1.2 . 2.4) (3 . 4)) ((3.4 . 4.6) (5 . 6)))
+ collect (list a b c d))
+ '((1.2 2.4 3 4) (3.4 4.6 5 6)))))
+
+(ert-deftest cl-loop-destructuring-with ()
+ (should (equal (cl-loop with (a b c) = '(1 2 3) return (+ a b c)) 6)))
+
+;;; 6.1.2.1.1 The for-as-arithmetic subclause
+(ert-deftest cl-macs-loop-for-as-arith ()
+ "Test various for-as-arithmetic subclauses."
+ (should (equal (cl-loop for i to 10 by 3 collect i)
+ '(0 3 6 9)))
+ (should (equal (cl-loop for i upto 3 collect i)
+ '(0 1 2 3)))
+ (should (equal (cl-loop for i below 3 collect i)
+ '(0 1 2)))
+ (should (equal (cl-loop for i below 10 by 2 collect i)
+ '(0 2 4 6 8)))
+ (should (equal (cl-loop for i downfrom 10 above 4 by 2 collect i)
+ '(10 8 6)))
+ (should (equal (cl-loop for i from 10 downto 1 by 3 collect i)
+ '(10 7 4 1)))
+ (should-error (eval '(cl-loop for i above 0 by 2 downfrom 10 collect i)))
+
+ (should (equal (cl-loop for i from 15 downto 10 collect i)
+ '(15 14 13 12 11 10))))
+
+(ert-deftest cl-macs-loop-for-as-arith-order-side-effects ()
+ "Test side effects generated by different arithmetic phrase order."
+ (should
+ (equal (let ((x 1))
+ (cl-loop for i from x to 10 by (cl-incf x) collect i))
+ '(1 3 5 7 9)))
+ (should-error
+ (eval '(let ((x 1))
+ (cl-loop for i from x by (cl-incf x) to 10 collect i))))
+ (should
+ (equal (let ((x 1))
+ (cl-loop for i from x to 10 by (cl-incf x) collect i))
+ '(1 3 5 7 9)))
+ (should-error
+ (eval '(let ((x 1))
+ (cl-loop for i to 10 by (cl-incf x) from x collect i))))
+ (should-error
+ (eval '(let ((x 1))
+ (cl-loop for i by (cl-incf x) from x to 10 collect i))))
+ (should-error
+ (eval '(let ((x 1))
+ (cl-loop for i by (cl-incf x) to 10 from x collect i)))))
+
+(ert-deftest cl-macs-loop-for-as-arith-invalid ()
+ "Test for invalid phrase combinations."
+ ;; Mixing arithmetic-up and arithmetic-down* subclauses
+ (should-not (cl-loop for i downfrom 10 below 20 collect i))
+ (should (cl-loop for i upfrom 20 above 10 collect i))
+ (should-error (eval '(cl-loop for i upto 10 by 2 downfrom 5)))
+ ;; Repeated phrases
+ (should-error (eval '(cl-loop for i from 10 to 20 above 10)))
+ (should-error (eval '(cl-loop for i from 10 to 20 upfrom 0)))
+ (should-error (eval '(cl-loop for i by 2 to 10 by 5)))
+ ;; negative step
+ (should-error (eval '(cl-loop for i by -1)))
+ ;; no step given for a downward loop
+ (should-error (eval '(cl-loop for i downto -5 collect i))))
+
+
+;;; 6.1.2.1.2 The for-as-in-list subclause
+(ert-deftest cl-macs-loop-for-as-in-list ()
+ (should (equal (cl-loop for x in '(1 2 3 4 5 6) collect (* x x))
+ '(1 4 9 16 25 36)))
+ (should (equal (cl-loop for x in '(1 2 3 4 5 6) by #'cddr collect (* x x))
+ '(1 9 25))))
+
+;;; 6.1.2.1.3 The for-as-on-list subclause
+(ert-deftest cl-macs-loop-for-as-on-list ()
+ (should (equal (cl-loop for x on '(1 2 3 4) collect x)
+ '((1 2 3 4) (2 3 4) (3 4) (4))))
+ (should (equal (cl-loop as (item) on '(1 2 3 4) by #'cddr collect item)
+ '(1 3))))
+
+;;; 6.1.2.1.4 The for-as-equals-then subclause
+(ert-deftest cl-macs-loop-for-as-equals-then ()
+ (should (equal (cl-loop for item = 1 then (+ item 10)
+ repeat 5
+ collect item)
+ '(1 11 21 31 41)))
+ (should (equal (cl-loop for x below 5 for y = nil then x collect (list x y))
+ '((0 nil) (1 1) (2 2) (3 3) (4 4))))
+ (should (equal (cl-loop for x below 5 and y = nil then x collect (list x y))
+ '((0 nil) (1 0) (2 1) (3 2) (4 3))))
+ (should (equal (cl-loop for x below 3 for y = (+ 10 x) nconc (list x y))
+ '(0 10 1 11 2 12)))
+ (should (equal (cl-loop with start = 5
+ for x = start
+ then (cl-incf start)
+ repeat 5
+ collect x)
+ '(5 6 7 8 9))))
+
+;;; 6.1.2.1.5 The for-as-across subclause
+(ert-deftest cl-macs-loop-for-as-across ()
+ (should (string= (cl-loop for x across "aeiou"
+ concat (char-to-string x))
+ "aeiou"))
+ (should (equal (cl-loop for v across (vector 1 2 3) vconcat (vector v (+ 10 v)))
+ [1 11 2 12 3 13])))
+
+;;; 6.1.2.1.6 The for-as-hash subclause
+(ert-deftest cl-macs-loop-for-as-hash ()
+ ;; example in Emacs manual 4.7.3
+ (should (equal (let ((hash (make-hash-table)))
+ (setf (gethash 1 hash) 10)
+ (setf (gethash "test" hash) "string")
+ (setf (gethash 'test hash) 'value)
+ (cl-loop for k being the hash-keys of hash
+ using (hash-values v)
+ collect (list k v)))
+ '((1 10) ("test" "string") (test value)))))
+
+;;; 6.1.2.2 Local Variable Initializations
+(ert-deftest cl-macs-loop-with ()
+ (should (equal (cl-loop with a = 1
+ with b = (+ a 2)
+ with c = (+ b 3)
+ return (list a b c))
+ '(1 3 6)))
+ (should (equal (let ((a 5)
+ (b 10))
+ (cl-loop with a = 1
+ and b = (+ a 2)
+ and c = (+ b 3)
+ return (list a b c)))
+ '(1 7 13)))
+ (should (and (equal (cl-loop for i below 3 with loop-with
+ do (push (* i i) loop-with)
+ finally (cl-return loop-with))
+ '(4 1 0))
+ (not (boundp 'loop-with)))))
+
+;;; 6.1.3 Value Accumulation Clauses
+(ert-deftest cl-macs-loop-accum ()
+ (should (equal (cl-loop for name in '(fred sue alice joe june)
+ for kids in '((bob ken) () () (kris sunshine) ())
+ collect name
+ append kids)
+ '(fred bob ken sue alice joe kris sunshine june))))
+
+(ert-deftest cl-macs-loop-collect ()
+ (should (equal (cl-loop for i in '(bird 3 4 turtle (1 . 4) horse cat)
+ when (symbolp i) collect i)
+ '(bird turtle horse cat)))
+ (should (equal (cl-loop for i from 1 to 10
+ if (cl-oddp i) collect i)
+ '(1 3 5 7 9)))
+ (should (equal (cl-loop for i in '(a b c d e f g) by #'cddr
+ collect i into my-list
+ finally return (nbutlast my-list))
+ '(a c e))))
+
+(ert-deftest cl-macs-loop-append/nconc ()
+ (should (equal (cl-loop for x in '((a) (b) ((c)))
+ append x)
+ '(a b (c))))
+ (should (equal (cl-loop for i upfrom 0
+ as x in '(a b (c))
+ nconc (if (cl-evenp i) (list x) nil))
+ '(a (c)))))
+
+(ert-deftest cl-macs-loop-count ()
+ (should (eql (cl-loop for i in '(a b nil c nil d e)
+ count i)
+ 5)))
+
+(ert-deftest cl-macs-loop-max/min ()
+ (should (eql (cl-loop for i in '(2 1 5 3 4)
+ maximize i)
+ 5))
+ (should (eql (cl-loop for i in '(2 1 5 3 4)
+ minimize i)
+ 1))
+ (should (equal (cl-loop with series = '(4.3 1.2 5.7)
+ for v in series
+ minimize (round v) into min-result
+ maximize (round v) into max-result
+ collect (list min-result max-result))
+ '((4 4) (1 4) (1 6)))))
+
+(ert-deftest cl-macs-loop-sum ()
+ (should (eql (cl-loop for i in '(1 2 3 4 5)
+ sum i)
+ 15))
+ (should (eql (cl-loop with series = '(1.2 4.3 5.7)
+ for v in series
+ sum (* 2.0 v))
+ 22.4)))
+
+;;; 6.1.4 Termination Test Clauses
+(ert-deftest cl-macs-loop-repeat ()
+ (should (equal (cl-loop with n = 4
+ repeat (1+ n)
+ collect n)
+ '(4 4 4 4 4)))
+ (should (equal (cl-loop for i upto 5
+ repeat 3
+ collect i)
+ '(0 1 2))))
+
+(ert-deftest cl-macs-loop-always ()
+ (should (cl-loop for i from 0 to 10
+ always (< i 11)))
+ (should-not (cl-loop for i from 0 to 10
+ always (< i 9)
+ finally (cl-return "you won't see this"))))
+
+(ert-deftest cl-macs-loop-never ()
+ (should (cl-loop for i from 0 to 10
+ never (> i 11)))
+ (should-not (cl-loop never t
+ finally (cl-return "you won't see this"))))
+
+(ert-deftest cl-macs-loop-thereis ()
+ (should (eql (cl-loop for i from 0
+ thereis (when (> i 10) i))
+ 11))
+ (should (string= (cl-loop thereis "Here is my value"
+ finally (cl-return "you won't see this"))
+ "Here is my value"))
+ (should (cl-loop for i to 10
+ thereis (> i 11)
+ finally (cl-return i))))
+
+(ert-deftest cl-macs-loop-anon-collection-conditional ()
+ "Always/never/thereis should error when used with an anonymous
+collection clause."
+ (should-not (cl-loop always nil collect t))
+ (should-not (cl-loop never t nconc t))
+ (should (cl-loop thereis t append t)))
+
+(ert-deftest cl-macs-loop-while ()
+ (should (equal (let ((stack '(a b c d e f)))
+ (cl-loop while stack
+ for item = (length stack) then (pop stack)
+ collect item))
+ '(6 a b c d e f))))
+
+(ert-deftest cl-macs-loop-until ()
+ (should (equal (cl-loop for i to 100
+ collect 10
+ until (= i 3)
+ collect i)
+ '(10 0 10 1 10 2 10))))
+
+;;; 6.1.5 Unconditional Execution Clauses
+(ert-deftest cl-macs-loop-do ()
+ (should (equal (cl-loop with list
+ for i from 1 to 3
+ do
+ (push 10 list)
+ (push i list)
+ finally (cl-return list))
+ '(3 10 2 10 1 10)))
+ (should (equal (cl-loop with res = 0
+ for i from 1 to 10
+ doing (cl-incf res i)
+ finally (cl-return res))
+ 55))
+ (should (equal (cl-loop for i from 10
+ do (when (= i 15)
+ (cl-return i))
+ finally (cl-return 0))
+ 15)))
+
+;;; 6.1.6 Conditional Execution Clauses
+(ert-deftest cl-macs-loop-when ()
+ (should (equal (cl-loop for i in '(1 2 3 4 5 6)
+ when (and (> i 3) i)
+ collect it)
+ '(4 5 6)))
+ (should (eql (cl-loop for i in '(1 2 3 4 5 6)
+ when (and (> i 3) i)
+ return it)
+ 4))
+
+ (should (equal (cl-loop for elt in '(1 a 2 "a" (3 4) 5 6)
+ when (numberp elt)
+ when (cl-evenp elt) collect elt into even
+ else collect elt into odd
+ else
+ when (symbolp elt) collect elt into syms
+ else collect elt into other
+ finally return (list even odd syms other))
+ '((2 6) (1 5) (a) ("a" (3 4))))))
+
+(ert-deftest cl-macs-loop-if ()
+ (should (equal (cl-loop for i to 5
+ if (cl-evenp i)
+ collect i
+ and when (and (= i 2) 'two)
+ collect it
+ and if (< i 3)
+ collect "low")
+ '(0 2 two "low" 4)))
+ (should (equal (cl-loop for i to 5
+ if (cl-evenp i)
+ collect i
+ and when (and (= i 2) 'two)
+ collect it
+ end
+ and if (< i 3)
+ collect "low")
+ '(0 "low" 2 two "low" 4)))
+ (should (equal (cl-loop with funny-numbers = '(6 13 -1)
+ for x below 10
+ if (cl-evenp x)
+ collect x into evens
+ else
+ collect x into odds
+ and if (memq x funny-numbers) return (cdr it)
+ finally return (vector odds evens))
+ [(1 3 5 7 9) (0 2 4 6 8)])))
+
+(ert-deftest cl-macs-loop-unless ()
+ (should (equal (cl-loop for i to 5
+ unless (= i 3)
+ collect i
+ else
+ collect 'three)
+ '(0 1 2 three 4 5))))
+
+
+;;; 6.1.7.1 Control Transfer Clauses
+(ert-deftest cl-macs-loop-named ()
+ (should (eql (cl-loop named finished
+ for i to 10
+ when (> (* i i) 30)
+ do (cl-return-from finished i))
+ 6)))
+
+;;; 6.1.7.2 Initial and Final Execution
+(ert-deftest cl-macs-loop-initially ()
+ (should (equal (let ((var (list 1 2 3 4 5)))
+ (cl-loop for i in var
+ collect i
+ initially
+ (setf (car var) 10)
+ (setf (cadr var) 20)))
+ '(10 20 3 4 5))))
+
+(ert-deftest cl-macs-loop-finally ()
+ (should (eql (cl-loop for i from 10
+ finally
+ (cl-incf i 10)
+ (cl-return i)
+ while (< i 20))
+ 30)))
+
+;;; Emacs extensions to loop
+(ert-deftest cl-macs-loop-in-ref ()
+ (should (equal (cl-loop with my-list = (list 1 2 3 4 5)
+ for x in-ref my-list
+ do (cl-incf x)
+ finally return my-list)
+ '(2 3 4 5 6))))
+
+(ert-deftest cl-macs-loop-across-ref ()
+ (should (equal (cl-loop with my-vec = ["one" "two" "three"]
+ for x across-ref my-vec
+ do (setf (aref x 0) (upcase (aref x 0)))
+ finally return my-vec)
+ ["One" "Two" "Three"])))
+
+(ert-deftest cl-macs-loop-being-elements ()
+ (should (equal (let ((var "StRiNG"))
+ (cl-loop for x being the elements of var
+ collect (downcase x)))
+ (string-to-list "string"))))
+
+(ert-deftest cl-macs-loop-being-elements-of-ref ()
+ (should (equal (let ((var (list 1 2 3 4 5)))
+ (cl-loop for x being the elements of-ref var
+ do (cl-incf x)
+ finally return var))
+ '(2 3 4 5 6))))
+
+(ert-deftest cl-macs-loop-being-symbols ()
+ (should (eq (cl-loop for sym being the symbols
+ when (eq sym 'cl-loop)
+ return 'cl-loop)
+ 'cl-loop)))
+
+(ert-deftest cl-macs-loop-being-keymap ()
+ (should (equal (let ((map (make-sparse-keymap))
+ (parent (make-sparse-keymap))
+ res)
+ (define-key map "f" #'forward-char)
+ (define-key map "b" #'backward-char)
+ (define-key parent "n" #'next-line)
+ (define-key parent "p" #'previous-line)
+ (set-keymap-parent map parent)
+ (cl-loop for b being the key-bindings of map
+ using (key-codes c)
+ do (push (list c b) res))
+ (cl-loop for s being the key-seqs of map
+ using (key-bindings b)
+ do (push (list (cl-copy-seq s) b) res))
+ res)
+ '(([?n] next-line) ([?p] previous-line)
+ ([?f] forward-char) ([?b] backward-char)
+ (?n next-line) (?p previous-line)
+ (?f forward-char) (?b backward-char)))))
+
+(ert-deftest cl-macs-loop-being-overlays ()
+ (should (equal (let ((ov (make-overlay (point) (point))))
+ (overlay-put ov 'prop "test")
+ (cl-loop for o being the overlays
+ when (eq o ov)
+ return (overlay-get o 'prop)))
+ "test")))
+
+(ert-deftest cl-macs-loop-being-frames ()
+ (should (eq (cl-loop with selected = (selected-frame)
+ for frame being the frames
+ when (eq frame selected)
+ return frame)
+ (selected-frame))))
+
+(ert-deftest cl-macs-loop-being-windows ()
+ (should (eq (cl-loop with selected = (selected-window)
+ for window being the windows
+ when (eq window selected)
+ return window)
+ (selected-window))))
+
+(ert-deftest cl-macs-loop-being-buffers ()
+ (should (eq (cl-loop with current = (current-buffer)
+ for buffer being the buffers
+ when (eq buffer current)
+ return buffer)
+ (current-buffer))))
+
+(ert-deftest cl-macs-loop-vconcat ()
+ (should (equal (cl-loop for x in (list 1 2 3 4 5)
+ vconcat (vector (1+ x)))
+ [2 3 4 5 6])))
+
+;;; cl-macs-tests.el ends here
--8<-----------------------------cut here---------------end--------------->8---
In GNU Emacs 26.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.11)
of 2017-07-03
Repository revision: 71169d5185a2465714cc3fb669c9e10338602340
^ permalink raw reply related [flat|nested] 9+ messages in thread
* bug#27559: 26.0.50; [PATCH] Add tests for cl-macs.el
2017-07-03 9:42 ` Tino Calancha
@ 2017-07-03 20:23 ` Alex
2017-07-04 5:04 ` Tino Calancha
0 siblings, 1 reply; 9+ messages in thread
From: Alex @ 2017-07-03 20:23 UTC (permalink / raw)
To: Tino Calancha; +Cc: 27559
Tino Calancha <tino.calancha@gmail.com> writes:
> Alex <agrambot@gmail.com> writes:
>
>> This initial version just includes tests for cl-loop, many of which were
>> adapted from Common Lisp the Language 2nd Edition. They are mostly
>> ordered by their appearance in the Hyperspec.
>>
>> When I was just about finished I realized that I could have just used an
>> ert wrapper macro to avoid all of the (eval (quote ...))) business,
>> which would have the added bonus of easily evaluating most of the tests
>> lexically. Should I redo it in this way?
>
> Thanks! It's very good having all those tests.
> I think we can avoid many of the (eval (quote ...)).
> In the following patch, i keep just those (eval (quote ...)
> where the expansion of `cl-loop' throws an error:
That's more or less what I did at first, but I figured since cl-loop is
a large macro, that it's best to quote the macro so that an accidental
error doesn't halt testing. I actually asked about this in
emacs-devel[1] a couple weeks ago, but no one responded.
For instance, some for-as-arith tests that aren't marked as should-error
currently error in master. As an example, (cl-loop for i above 0 by 2
downfrom 10 collect i) should work, but it errors. I have a working
patch for these, but I wanted to make the tests first.
It would be nice if the ert tests in general could just continue on with
testing even if there are macro-expansion errors.
Footnotes:
[1] https://lists.gnu.org/archive/html/emacs-devel/2017-06/msg00461.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#27559: 26.0.50; [PATCH] Add tests for cl-macs.el
2017-07-03 20:23 ` Alex
@ 2017-07-04 5:04 ` Tino Calancha
2017-07-04 19:49 ` Alex
0 siblings, 1 reply; 9+ messages in thread
From: Tino Calancha @ 2017-07-04 5:04 UTC (permalink / raw)
To: Alex; +Cc: 27559, tino.calancha
Alex <agrambot@gmail.com> writes:
> That's more or less what I did at first, but I figured since cl-loop is
> a large macro, that it's best to quote the macro so that an accidental
> error doesn't halt testing.
I prefer just use (eval '...) in those cases where the expansion fails.
That way the file is more readable, and a reader focus her eye in those
failing expansions.
Maybe we could add a comment in the file saying that those
`should-error' are failing expansions to be fixed.
> For instance, some for-as-arith tests that aren't marked as should-error
> currently error in master. As an example, (cl-loop for i above 0 by 2
> downfrom 10 collect i) should work, but it errors. I have a working
> patch for these, but I wanted to make the tests first.
That's great! Looking forward to see the patch fixing these problems.
> It would be nice if the ert tests in general could just continue on with
> testing even if there are macro-expansion errors.
Sure, as long as the errors are expected.
^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#27559: 26.0.50; [PATCH] Add tests for cl-macs.el
2017-07-04 5:04 ` Tino Calancha
@ 2017-07-04 19:49 ` Alex
2017-07-05 13:29 ` Tino Calancha
2017-08-11 1:17 ` npostavs
0 siblings, 2 replies; 9+ messages in thread
From: Alex @ 2017-07-04 19:49 UTC (permalink / raw)
To: Tino Calancha; +Cc: 27559
Tino Calancha <tino.calancha@gmail.com> writes:
> Alex <agrambot@gmail.com> writes:
>
>> That's more or less what I did at first, but I figured since cl-loop is
>> a large macro, that it's best to quote the macro so that an accidental
>> error doesn't halt testing.
> I prefer just use (eval '...) in those cases where the expansion fails.
> That way the file is more readable, and a reader focus her eye in those
> failing expansions.
I agree that it's more readable, and if I was doing this for my own
project I'd just leave the (eval '...) out where possible.
> Maybe we could add a comment in the file saying that those
> `should-error' are failing expansions to be fixed.
Part of the problem is that the "failing expansions that should be fixed" aren't
wrapped in a should-error, but are wrapped in a should. The test itself
is marked as ":expected-result :failed".
>> It would be nice if the ert tests in general could just continue on with
>> testing even if there are macro-expansion errors.
> Sure, as long as the errors are expected.
I think any macro-expansion errors inside of a
should-error/should/should-not should be similarly to run-time errors.
I also have a patch that appears to do this, but it breaks a few tests
due to Bug#24402[1]. Perhaps a fix to that bug will also make it so that
macro-expansion errors will be caught be should*.
I hope that Bug#24402 can be fixed before committing these tests, so we
can just remove the (eval '...) noise altogether.
Footnotes:
[1] https://debbugs.gnu.org/cgi/bugreport.cgi?bug=24402
^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#27559: 26.0.50; [PATCH] Add tests for cl-macs.el
2017-07-04 19:49 ` Alex
@ 2017-07-05 13:29 ` Tino Calancha
2017-08-11 1:17 ` npostavs
1 sibling, 0 replies; 9+ messages in thread
From: Tino Calancha @ 2017-07-05 13:29 UTC (permalink / raw)
To: Alex; +Cc: 27559, Tino Calancha
On Tue, 4 Jul 2017, Alex wrote:
> Tino Calancha <tino.calancha@gmail.com> writes:
>
>> Alex <agrambot@gmail.com> writes:
>>
>>> That's more or less what I did at first, but I figured since cl-loop is
>>> a large macro, that it's best to quote the macro so that an accidental
>>> error doesn't halt testing.
>> I prefer just use (eval '...) in those cases where the expansion fails.
>> That way the file is more readable, and a reader focus her eye in those
>> failing expansions.
>
> I agree that it's more readable, and if I was doing this for my own
> project I'd just leave the (eval '...) out where possible.
>
>> Maybe we could add a comment in the file saying that those
>> `should-error' are failing expansions to be fixed.
>
> Part of the problem is that the "failing expansions that should be fixed" aren't
> wrapped in a should-error, but are wrapped in a should. The test itself
> is marked as ":expected-result :failed".
Feel free to adapt the patch to your taste: in the way you find it more
convenient.
> I also have a patch that appears to do this, but it breaks a few tests
> due to Bug#24402[1]. Perhaps a fix to that bug will also make it so that
> macro-expansion errors will be caught be should*.
>
> I hope that Bug#24402 can be fixed before committing these tests, so we
> can just remove the (eval '...) noise altogether.
I agree with you. Thanks for point me out to such bug report (i wasn't
aware of it).
I will teletransport to that bug report. See you there!
^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#27559: 26.0.50; [PATCH] Add tests for cl-macs.el
2017-07-04 19:49 ` Alex
2017-07-05 13:29 ` Tino Calancha
@ 2017-08-11 1:17 ` npostavs
2017-08-12 0:02 ` Alex
1 sibling, 1 reply; 9+ messages in thread
From: npostavs @ 2017-08-11 1:17 UTC (permalink / raw)
To: Alex; +Cc: 27559, Tino Calancha
Alex <agrambot@gmail.com> writes:
> I think any macro-expansion errors inside of a
> should-error/should/should-not should be similarly to run-time errors.
>
> I also have a patch that appears to do this, but it breaks a few tests
> due to Bug#24402[1]. Perhaps a fix to that bug will also make it so that
> macro-expansion errors will be caught be should*.
>
> I hope that Bug#24402 can be fixed before committing these tests, so we
> can just remove the (eval '...) noise altogether.
So now that #24402 is done, where are we on this?
^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#27559: 26.0.50; [PATCH] Add tests for cl-macs.el
2017-08-11 1:17 ` npostavs
@ 2017-08-12 0:02 ` Alex
2017-08-22 0:55 ` npostavs
0 siblings, 1 reply; 9+ messages in thread
From: Alex @ 2017-08-12 0:02 UTC (permalink / raw)
To: npostavs; +Cc: 27559, Tino Calancha
[-- Attachment #1: Type: text/plain, Size: 196 bytes --]
npostavs@users.sourceforge.net writes:
> So now that #24402 is done, where are we on this?
Here's a patch without any use of eval. All results are as expected with
and without TEST_LOAD_EL=no.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: cl-macs tests sans eval --]
[-- Type: text/x-diff, Size: 22576 bytes --]
From 7e7fdea81ac6803942889f0f46345591638dacfa Mon Sep 17 00:00:00 2001
From: Alexander Gramiak <agrambot@gmail.com>
Date: Fri, 11 Aug 2017 17:53:27 -0600
Subject: [PATCH] Add tests for cl-macs.el
* test/lisp/emacs-lisp/cl-lib-tests.el (cl-lib-test-loop): Remove
duplicate.
(cl-loop-destructuring-with): Move to cl-macs-tests.el.
* test/lisp/emacs-lisp/cl-macs-tests.el: New file.
---
test/lisp/emacs-lisp/cl-lib-tests.el | 10 +-
test/lisp/emacs-lisp/cl-macs-tests.el | 500 ++++++++++++++++++++++++++++++++++
2 files changed, 502 insertions(+), 8 deletions(-)
create mode 100644 test/lisp/emacs-lisp/cl-macs-tests.el
diff --git a/test/lisp/emacs-lisp/cl-lib-tests.el b/test/lisp/emacs-lisp/cl-lib-tests.el
index 9e68dceb8f..7763d062a0 100644
--- a/test/lisp/emacs-lisp/cl-lib-tests.el
+++ b/test/lisp/emacs-lisp/cl-lib-tests.el
@@ -1,4 +1,4 @@
-;;; cl-lib.el --- tests for emacs-lisp/cl-lib.el -*- lexical-binding:t -*-
+;;; cl-lib-tests.el --- tests for emacs-lisp/cl-lib.el -*- lexical-binding:t -*-
;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
@@ -195,9 +195,6 @@
(should (eql (cl-mismatch "Aa" "aA") 0))
(should (eql (cl-mismatch '(a b c) '(a b d)) 2)))
-(ert-deftest cl-lib-test-loop ()
- (should (eql (cl-loop with (a b c) = '(1 2 3) return (+ a b c)) 6)))
-
(ert-deftest cl-lib-keyword-names-versus-values ()
(should (equal
(funcall (cl-function (lambda (&key a b) (list a b)))
@@ -480,9 +477,6 @@
(should (= 239 (cl-parse-integer "zzef" :radix 16 :start 2)))
(should (= -123 (cl-parse-integer " -123 "))))
-(ert-deftest cl-loop-destructuring-with ()
- (should (equal (cl-loop with (a b c) = '(1 2 3) return (+ a b c)) 6)))
-
(ert-deftest cl-flet-test ()
(should (equal (cl-flet ((f1 (x) x)) (let ((x #'f1)) (funcall x 5))) 5)))
@@ -556,4 +550,4 @@ cl-lib-tests--dummy-function
(should cl-old-struct-compat-mode)
(cl-old-struct-compat-mode (if saved 1 -1))))
-;;; cl-lib.el ends here
+;;; cl-lib-tests.el ends here
diff --git a/test/lisp/emacs-lisp/cl-macs-tests.el b/test/lisp/emacs-lisp/cl-macs-tests.el
new file mode 100644
index 0000000000..16cb4fb40c
--- /dev/null
+++ b/test/lisp/emacs-lisp/cl-macs-tests.el
@@ -0,0 +1,500 @@
+;;; cl-macs-tests.el --- tests for emacs-lisp/cl-macs.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see `http://www.gnu.org/licenses/'.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'cl-macs)
+(require 'ert)
+
+\f
+;;;; cl-loop tests -- many adapted from Steele's CLtL2
+
+;;; ANSI 6.1.1.7 Destructuring
+(ert-deftest cl-macs-loop-and-assignment ()
+ ;; Bug#6583
+ :expected-result :failed
+ (should (equal (cl-loop for numlist in '((1 2 4.0) (5 6 8.3) (8 9 10.4))
+ for a = (cl-first numlist)
+ and b = (cl-second numlist)
+ and c = (cl-third numlist)
+ collect (list c b a))
+ '((4.0 2 1) (8.3 6 5) (10.4 9 8)))))
+
+(ert-deftest cl-macs-loop-destructure ()
+ (should (equal (cl-loop for (a b c) in '((1 2 4.0) (5 6 8.3) (8 9 10.4))
+ collect (list c b a))
+ '((4.0 2 1) (8.3 6 5) (10.4 9 8)))))
+
+(ert-deftest cl-macs-loop-destructure-nil ()
+ (should (equal (cl-loop for (a nil b) = '(1 2 3)
+ do (cl-return (list a b)))
+ '(1 3))))
+
+(ert-deftest cl-macs-loop-destructure-cons ()
+ (should (equal (cl-loop for ((a . b) (c . d)) in
+ '(((1.2 . 2.4) (3 . 4)) ((3.4 . 4.6) (5 . 6)))
+ collect (list a b c d))
+ '((1.2 2.4 3 4) (3.4 4.6 5 6)))))
+
+(ert-deftest cl-loop-destructuring-with ()
+ (should (equal (cl-loop with (a b c) = '(1 2 3) return (+ a b c)) 6)))
+
+;;; 6.1.2.1.1 The for-as-arithmetic subclause
+(ert-deftest cl-macs-loop-for-as-arith ()
+ "Test various for-as-arithmetic subclauses."
+ :expected-result :failed
+ (should (equal (cl-loop for i to 10 by 3 collect i)
+ '(0 3 6 9)))
+ (should (equal (cl-loop for i upto 3 collect i)
+ '(0 1 2 3)))
+ (should (equal (cl-loop for i below 3 collect i)
+ '(0 1 2)))
+ (should (equal (cl-loop for i below 10 by 2 collect i)
+ '(0 2 4 6 8)))
+ (should (equal (cl-loop for i downfrom 10 above 4 by 2 collect i)
+ '(10 8 6)))
+ (should (equal (cl-loop for i from 10 downto 1 by 3 collect i)
+ '(10 7 4 1)))
+ (should (equal (cl-loop for i above 0 by 2 downfrom 10 collect i)
+ '(10 8 6 4 2)))
+ (should (equal (cl-loop for i downto 10 from 15 collect i)
+ '(15 14 13 12 11 10))))
+
+(ert-deftest cl-macs-loop-for-as-arith-order-side-effects ()
+ "Test side effects generated by different arithmetic phrase order."
+ :expected-result :failed
+ (should
+ (equal (let ((x 1)) (cl-loop for i from x to 10 by (cl-incf x) collect i))
+ '(1 3 5 7 9)))
+ (should
+ (equal (let ((x 1)) (cl-loop for i from x by (cl-incf x) to 10 collect i))
+ '(1 3 5 7 9)))
+ (should
+ (equal (let ((x 1)) (cl-loop for i to 10 from x by (cl-incf x) collect i))
+ '(1 3 5 7 9)))
+ (should
+ (equal (let ((x 1)) (cl-loop for i to 10 by (cl-incf x) from x collect i))
+ '(2 4 6 8 10)))
+ (should
+ (equal (let ((x 1)) (cl-loop for i by (cl-incf x) from x to 10 collect i))
+ '(2 4 6 8 10)))
+ (should
+ (equal (let ((x 1)) (cl-loop for i by (cl-incf x) to 10 from x collect i))
+ '(2 4 6 8 10))))
+
+(ert-deftest cl-macs-loop-for-as-arith-invalid ()
+ "Test for invalid phrase combinations."
+ :expected-result :failed
+ ;; Mixing arithmetic-up and arithmetic-down* subclauses
+ (should-error (cl-loop for i downfrom 10 below 20 collect i))
+ (should-error (cl-loop for i upfrom 20 above 10 collect i))
+ (should-error (cl-loop for i upto 10 by 2 downfrom 5))
+ ;; Repeated phrases
+ (should-error (cl-loop for i from 10 to 20 above 10))
+ (should-error (cl-loop for i from 10 to 20 upfrom 0))
+ (should-error (cl-loop for i by 2 to 10 by 5))
+ ;; negative step
+ (should-error (cl-loop for i by -1))
+ ;; no step given for a downward loop
+ (should-error (cl-loop for i downto -5 collect i)))
+
+
+;;; 6.1.2.1.2 The for-as-in-list subclause
+(ert-deftest cl-macs-loop-for-as-in-list ()
+ (should (equal (cl-loop for x in '(1 2 3 4 5 6) collect (* x x))
+ '(1 4 9 16 25 36)))
+ (should (equal (cl-loop for x in '(1 2 3 4 5 6) by #'cddr collect (* x x))
+ '(1 9 25))))
+
+;;; 6.1.2.1.3 The for-as-on-list subclause
+(ert-deftest cl-macs-loop-for-as-on-list ()
+ (should (equal (cl-loop for x on '(1 2 3 4) collect x)
+ '((1 2 3 4) (2 3 4) (3 4) (4))))
+ (should (equal (cl-loop as (item) on '(1 2 3 4) by #'cddr collect item)
+ '(1 3))))
+
+;;; 6.1.2.1.4 The for-as-equals-then subclause
+(ert-deftest cl-macs-loop-for-as-equals-then ()
+ (should (equal (cl-loop for item = 1 then (+ item 10)
+ repeat 5
+ collect item)
+ '(1 11 21 31 41)))
+ (should (equal (cl-loop for x below 5 for y = nil then x collect (list x y))
+ '((0 nil) (1 1) (2 2) (3 3) (4 4))))
+ (should (equal (cl-loop for x below 5 and y = nil then x collect (list x y))
+ '((0 nil) (1 0) (2 1) (3 2) (4 3))))
+ (should (equal (cl-loop for x below 3 for y = (+ 10 x) nconc (list x y))
+ '(0 10 1 11 2 12)))
+ (should (equal (cl-loop with start = 5
+ for x = start then (cl-incf start)
+ repeat 5
+ collect x)
+ '(5 6 7 8 9))))
+
+;;; 6.1.2.1.5 The for-as-across subclause
+(ert-deftest cl-macs-loop-for-as-across ()
+ (should (string= (cl-loop for x across "aeiou"
+ concat (char-to-string x))
+ "aeiou"))
+ (should (equal (cl-loop for v across (vector 1 2 3) vconcat (vector v (+ 10 v)))
+ [1 11 2 12 3 13])))
+
+;;; 6.1.2.1.6 The for-as-hash subclause
+(ert-deftest cl-macs-loop-for-as-hash ()
+ ;; example in Emacs manual 4.7.3
+ (should (equal (let ((hash (make-hash-table)))
+ (setf (gethash 1 hash) 10)
+ (setf (gethash "test" hash) "string")
+ (setf (gethash 'test hash) 'value)
+ (cl-loop for k being the hash-keys of hash
+ using (hash-values v)
+ collect (list k v)))
+ '((1 10) ("test" "string") (test value)))))
+
+;;; 6.1.2.2 Local Variable Initializations
+(ert-deftest cl-macs-loop-with ()
+ (should (equal (cl-loop with a = 1
+ with b = (+ a 2)
+ with c = (+ b 3)
+ return (list a b c))
+ '(1 3 6)))
+ (should (equal (let ((a 5)
+ (b 10))
+ (cl-loop with a = 1
+ and b = (+ a 2)
+ and c = (+ b 3)
+ return (list a b c)))
+ '(1 7 13)))
+ (should (and (equal (cl-loop for i below 3 with loop-with
+ do (push (* i i) loop-with)
+ finally (cl-return loop-with))
+ '(4 1 0))
+ (not (boundp 'loop-with)))))
+
+;;; 6.1.3 Value Accumulation Clauses
+(ert-deftest cl-macs-loop-accum ()
+ (should (equal (cl-loop for name in '(fred sue alice joe june)
+ for kids in '((bob ken) () () (kris sunshine) ())
+ collect name
+ append kids)
+ '(fred bob ken sue alice joe kris sunshine june))))
+
+(ert-deftest cl-macs-loop-collect ()
+ (should (equal (cl-loop for i in '(bird 3 4 turtle (1 . 4) horse cat)
+ when (symbolp i) collect i)
+ '(bird turtle horse cat)))
+ (should (equal (cl-loop for i from 1 to 10
+ if (cl-oddp i) collect i)
+ '(1 3 5 7 9)))
+ (should (equal (cl-loop for i in '(a b c d e f g) by #'cddr
+ collect i into my-list
+ finally return (nbutlast my-list))
+ '(a c e))))
+
+(ert-deftest cl-macs-loop-append/nconc ()
+ (should (equal (cl-loop for x in '((a) (b) ((c)))
+ append x)
+ '(a b (c))))
+ (should (equal (cl-loop for i upfrom 0
+ as x in '(a b (c))
+ nconc (if (cl-evenp i) (list x) nil))
+ '(a (c)))))
+
+(ert-deftest cl-macs-loop-count ()
+ (should (eql (cl-loop for i in '(a b nil c nil d e)
+ count i)
+ 5)))
+
+(ert-deftest cl-macs-loop-max/min ()
+ (should (eql (cl-loop for i in '(2 1 5 3 4)
+ maximize i)
+ 5))
+ (should (eql (cl-loop for i in '(2 1 5 3 4)
+ minimize i)
+ 1))
+ (should (equal (cl-loop with series = '(4.3 1.2 5.7)
+ for v in series
+ minimize (round v) into min-result
+ maximize (round v) into max-result
+ collect (list min-result max-result))
+ '((4 4) (1 4) (1 6)))))
+
+(ert-deftest cl-macs-loop-sum ()
+ (should (eql (cl-loop for i in '(1 2 3 4 5)
+ sum i)
+ 15))
+ (should (eql (cl-loop with series = '(1.2 4.3 5.7)
+ for v in series
+ sum (* 2.0 v))
+ 22.4)))
+
+;;; 6.1.4 Termination Test Clauses
+(ert-deftest cl-macs-loop-repeat ()
+ (should (equal (cl-loop with n = 4
+ repeat (1+ n)
+ collect n)
+ '(4 4 4 4 4)))
+ (should (equal (cl-loop for i upto 5
+ repeat 3
+ collect i)
+ '(0 1 2))))
+
+(ert-deftest cl-macs-loop-always ()
+ (should (cl-loop for i from 0 to 10
+ always (< i 11)))
+ (should-not (cl-loop for i from 0 to 10
+ always (< i 9)
+ finally (cl-return "you won't see this"))))
+
+(ert-deftest cl-macs-loop-never ()
+ (should (cl-loop for i from 0 to 10
+ never (> i 11)))
+ (should-not (cl-loop never t
+ finally (cl-return "you won't see this"))))
+
+(ert-deftest cl-macs-loop-thereis ()
+ (should (eql (cl-loop for i from 0
+ thereis (when (> i 10) i))
+ 11))
+ (should (string= (cl-loop thereis "Here is my value"
+ finally (cl-return "you won't see this"))
+ "Here is my value"))
+ (should (cl-loop for i to 10
+ thereis (> i 11)
+ finally (cl-return i))))
+
+(ert-deftest cl-macs-loop-anon-collection-conditional ()
+ "Always/never/thereis should error when used with an anonymous
+collection clause."
+ :expected-result :failed
+ (should-error (cl-loop always nil collect t))
+ (should-error (cl-loop never t nconc t))
+ (should-error (cl-loop thereis t append t)))
+
+(ert-deftest cl-macs-loop-while ()
+ (should (equal (let ((stack '(a b c d e f)))
+ (cl-loop while stack
+ for item = (length stack) then (pop stack)
+ collect item))
+ '(6 a b c d e f))))
+
+(ert-deftest cl-macs-loop-until ()
+ (should (equal (cl-loop for i to 100
+ collect 10
+ until (= i 3)
+ collect i)
+ '(10 0 10 1 10 2 10))))
+
+;;; 6.1.5 Unconditional Execution Clauses
+(ert-deftest cl-macs-loop-do ()
+ (should (equal (cl-loop with list
+ for i from 1 to 3
+ do
+ (push 10 list)
+ (push i list)
+ finally (cl-return list))
+ '(3 10 2 10 1 10)))
+ (should (equal (cl-loop with res = 0
+ for i from 1 to 10
+ doing (cl-incf res i)
+ finally (cl-return res))
+ 55))
+ (should (equal (cl-loop for i from 10
+ do (when (= i 15)
+ (cl-return i))
+ finally (cl-return 0))
+ 15)))
+
+;;; 6.1.6 Conditional Execution Clauses
+(ert-deftest cl-macs-loop-when ()
+ (should (equal (cl-loop for i in '(1 2 3 4 5 6)
+ when (and (> i 3) i)
+ collect it)
+ '(4 5 6)))
+ (should (eql (cl-loop for i in '(1 2 3 4 5 6)
+ when (and (> i 3) i)
+ return it)
+ 4))
+
+ (should (equal (cl-loop for elt in '(1 a 2 "a" (3 4) 5 6)
+ when (numberp elt)
+ when (cl-evenp elt) collect elt into even
+ else collect elt into odd
+ else
+ when (symbolp elt) collect elt into syms
+ else collect elt into other
+ finally return (list even odd syms other))
+ '((2 6) (1 5) (a) ("a" (3 4))))))
+
+(ert-deftest cl-macs-loop-if ()
+ (should (equal (cl-loop for i to 5
+ if (cl-evenp i)
+ collect i
+ and when (and (= i 2) 'two)
+ collect it
+ and if (< i 3)
+ collect "low")
+ '(0 2 two "low" 4)))
+ (should (equal (cl-loop for i to 5
+ if (cl-evenp i)
+ collect i
+ and when (and (= i 2) 'two)
+ collect it
+ end
+ and if (< i 3)
+ collect "low")
+ '(0 "low" 2 two "low" 4)))
+ (should (equal (cl-loop with funny-numbers = '(6 13 -1)
+ for x below 10
+ if (cl-evenp x)
+ collect x into evens
+ else
+ collect x into odds
+ and if (memq x funny-numbers) return (cdr it)
+ finally return (vector odds evens))
+ [(1 3 5 7 9) (0 2 4 6 8)])))
+
+(ert-deftest cl-macs-loop-unless ()
+ (should (equal (cl-loop for i to 5
+ unless (= i 3)
+ collect i
+ else
+ collect 'three)
+ '(0 1 2 three 4 5))))
+
+
+;;; 6.1.7.1 Control Transfer Clauses
+(ert-deftest cl-macs-loop-named ()
+ (should (eql (cl-loop named finished
+ for i to 10
+ when (> (* i i) 30)
+ do (cl-return-from finished i))
+ 6)))
+
+;;; 6.1.7.2 Initial and Final Execution
+(ert-deftest cl-macs-loop-initially ()
+ (should (equal (let ((var (list 1 2 3 4 5)))
+ (cl-loop for i in var
+ collect i
+ initially
+ (setf (car var) 10)
+ (setf (cadr var) 20)))
+ '(10 20 3 4 5))))
+
+(ert-deftest cl-macs-loop-finally ()
+ (should (eql (cl-loop for i from 10
+ finally
+ (cl-incf i 10)
+ (cl-return i)
+ while (< i 20))
+ 30)))
+
+;;; Emacs extensions to loop
+(ert-deftest cl-macs-loop-in-ref ()
+ (should (equal (cl-loop with my-list = (list 1 2 3 4 5)
+ for x in-ref my-list
+ do (cl-incf x)
+ finally return my-list)
+ '(2 3 4 5 6))))
+
+(ert-deftest cl-macs-loop-across-ref ()
+ (should (equal (cl-loop with my-vec = ["one" "two" "three"]
+ for x across-ref my-vec
+ do (setf (aref x 0) (upcase (aref x 0)))
+ finally return my-vec)
+ ["One" "Two" "Three"])))
+
+(ert-deftest cl-macs-loop-being-elements ()
+ (should (equal (let ((var "StRiNG"))
+ (cl-loop for x being the elements of var
+ collect (downcase x)))
+ (string-to-list "string"))))
+
+(ert-deftest cl-macs-loop-being-elements-of-ref ()
+ (should (equal (let ((var (list 1 2 3 4 5)))
+ (cl-loop for x being the elements of-ref var
+ do (cl-incf x)
+ finally return var))
+ '(2 3 4 5 6))))
+
+(ert-deftest cl-macs-loop-being-symbols ()
+ (should (eq (cl-loop for sym being the symbols
+ when (eq sym 'cl-loop)
+ return 'cl-loop)
+ 'cl-loop)))
+
+(ert-deftest cl-macs-loop-being-keymap ()
+ (should (equal (let ((map (make-sparse-keymap))
+ (parent (make-sparse-keymap))
+ res)
+ (define-key map "f" #'forward-char)
+ (define-key map "b" #'backward-char)
+ (define-key parent "n" #'next-line)
+ (define-key parent "p" #'previous-line)
+ (set-keymap-parent map parent)
+ (cl-loop for b being the key-bindings of map
+ using (key-codes c)
+ do (push (list c b) res))
+ (cl-loop for s being the key-seqs of map
+ using (key-bindings b)
+ do (push (list (cl-copy-seq s) b) res))
+ res)
+ '(([?n] next-line) ([?p] previous-line)
+ ([?f] forward-char) ([?b] backward-char)
+ (?n next-line) (?p previous-line)
+ (?f forward-char) (?b backward-char)))))
+
+(ert-deftest cl-macs-loop-being-overlays ()
+ (should (equal (let ((ov (make-overlay (point) (point))))
+ (overlay-put ov 'prop "test")
+ (cl-loop for o being the overlays
+ when (eq o ov)
+ return (overlay-get o 'prop)))
+ "test")))
+
+(ert-deftest cl-macs-loop-being-frames ()
+ (should (eq (cl-loop with selected = (selected-frame)
+ for frame being the frames
+ when (eq frame selected)
+ return frame)
+ (selected-frame))))
+
+(ert-deftest cl-macs-loop-being-windows ()
+ (should (eq (cl-loop with selected = (selected-window)
+ for window being the windows
+ when (eq window selected)
+ return window)
+ (selected-window))))
+
+(ert-deftest cl-macs-loop-being-buffers ()
+ (should (eq (cl-loop with current = (current-buffer)
+ for buffer being the buffers
+ when (eq buffer current)
+ return buffer)
+ (current-buffer))))
+
+(ert-deftest cl-macs-loop-vconcat ()
+ (should (equal (cl-loop for x in (list 1 2 3 4 5)
+ vconcat (vector (1+ x)))
+ [2 3 4 5 6])))
+
+;;; cl-macs-tests.el ends here
--
2.13.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2017-08-22 0:55 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-03 5:54 bug#27559: 26.0.50; [PATCH] Add tests for cl-macs.el Alex
2017-07-03 9:42 ` Tino Calancha
2017-07-03 20:23 ` Alex
2017-07-04 5:04 ` Tino Calancha
2017-07-04 19:49 ` Alex
2017-07-05 13:29 ` Tino Calancha
2017-08-11 1:17 ` npostavs
2017-08-12 0:02 ` Alex
2017-08-22 0:55 ` npostavs
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).