1 ;;;; testcases.el -- Test cases for testcover-tests.el
3 ;; Copyright (C) 2017 Free Software Foundation, Inc.
5 ;; Author: Gemini Lasswell
7 ;; This file is part of GNU Emacs.
9 ;; This program is free software: you can redistribute it and/or
10 ;; modify it under the terms of the GNU General Public License as
11 ;; published by the Free Software Foundation, either version 3 of the
12 ;; License, or (at your option) any later version.
14 ;; This program is distributed in the hope that it will be useful, but
15 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 ;; General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with this program. If not, see `http://www.gnu.org/licenses/'.
24 ;; * This file should not be loaded directly. It is meant to be read
25 ;; by `testcover-tests-build-test-cases'.
27 ;; * Test cases begin with ;; ==== name ====. The symbol name between
28 ;; the ===='s is used to create the name of the test.
30 ;; * Following the beginning comment place the test docstring and
31 ;; any tags or keywords for ERT. These will be spliced into the
32 ;; ert-deftest for the test.
34 ;; * To separate the above from the test case code, use another
37 ;; * These special comments should start at the beginning of a line.
39 ;; * `testcover-tests-skeleton' will prompt you for a test name and
40 ;; insert the special comments.
42 ;; * The test case code should be annotated with %%% at the end of
43 ;; each form where a tan splotch is expected, and !!! at the end
44 ;; of each form where a red mark is expected.
46 ;; * If Testcover is working correctly on your code sample, using
47 ;; `testcover-tests-markup-region' and
48 ;; `testcover-tests-unmarkup-region' can make creating test cases
54 ;; ==== constants-bug-25316 ====
55 "Testcover doesn't splotch constants."
56 :expected-result
:failed
58 (defconst testcover-testcase-const
"apples")
59 (defun testcover-testcase-zero () 0)
60 (defun testcover-testcase-list-consts ()
64 `(a b c
,testcover-testcase-const
)
66 testcover-testcase-const
67 (testcover-testcase-zero)
70 (defun testcover-testcase-add-to-const-list (arg)
71 (cons arg%%%
(testcover-testcase-list-consts))%%%
)
73 (should (equal (testcover-testcase-add-to-const-list 'a
)
74 `(a ,emacs-version
10 "hello" (a b c
"apples") (1 2 3)
77 ;; ==== customize-defcustom-bug-25326 ====
78 "Testcover doesn't prevent testing of defcustom values."
79 :expected-result
:failed
81 (defgroup testcover-testcase nil
82 "Test case for testcover"
84 :prefix
"testcover-testcase-"
86 (defcustom testcover-testcase-flag t
87 "Test value used by testcover-tests.el"
89 :group
'testcover-testcase
)
90 (defun testcover-testcase-get-flag ()
91 testcover-testcase-flag
)
93 (testcover-testcase-get-flag)
94 (setq testcover-testcase-flag
(not testcover-testcase-flag
))
95 (testcover-testcase-get-flag)
97 ;; ==== no-returns ====
98 "Testcover doesn't splotch functions which don't return."
100 (defun testcover-testcase-play-ball (retval)
102 (throw 'ball retval%%%
))%%%
) ; catch gets marked but not throw
104 (defun testcover-testcase-not-my-favorite-error-message ()
105 (signal 'wrong-type-argument
(list 'consp nil
)))
107 (should (testcover-testcase-play-ball t
))
109 (testcover-testcase-not-my-favorite-error-message)
112 ;; ==== noreturn-symbol ====
113 "Wrapping a form with noreturn prevents splotching."
115 (defun testcover-testcase-cancel (spacecraft)
116 (error "no destination for %s" spacecraft
))
117 (defun testcover-testcase-launch (spacecraft planet
)
119 (noreturn (testcover-testcase-cancel spacecraft%%%
))
120 (list spacecraft%%% planet%%%
)%%%
)%%%
)
121 (defun testcover-testcase-launch-2 (spacecraft planet
)
122 (if (null planet%%%
)%%%
123 (testcover-testcase-cancel spacecraft%%%
)!!!
124 (list spacecraft
!!! planet
!!!)!!!)!!!)
125 (should (equal (testcover-testcase-launch "Curiosity" "Mars") '("Curiosity" "Mars")))
127 (testcover-testcase-launch "Voyager" nil
)
130 (testcover-testcase-launch-2 "Voyager II" nil
)
133 (should-error (testcover-testcase-launch "Voyager" nil
))
134 (should-error (testcover-testcase-launch-2 "Voyager II" nil
))
136 ;; ==== 1-value-symbol-bug-25316 ====
137 "Wrapping a form with 1value prevents splotching."
138 :expected-result
:failed
140 (defun testcover-testcase-always-zero (num)
141 (- num%%% num%%%
)%%%
)
142 (defun testcover-testcase-still-always-zero (num)
143 (1value (- num%%% num%%%
(- num%%% num%%%
)%%%
)))
144 (defun testcover-testcase-never-called (num)
145 (1value (/ num
!!! num
!!!)!!!)!!!)
146 (should (eql 0 (testcover-testcase-always-zero 3)))
147 (should (eql 0 (testcover-testcase-still-always-zero 5)))
149 ;; ==== dotimes-dolist ====
150 "Dolist and dotimes with a 1valued return value are 1valued."
152 (defun testcover-testcase-do-over (things)
153 (dolist (thing things%%%
)
155 (dolist (thing things%%%
42)
157 (dolist (thing things%%% things%%%
)
159 (defun testcover-testcase-do-more (count)
160 (dotimes (num count%%%
)
162 (dotimes (num count%%% count%%%
)
164 (dotimes (num count%%%
0)
166 (should (equal '(a b c
) (testcover-testcase-do-over '(a b c
))))
167 (should (eql 0 (testcover-testcase-do-more 2)))
169 ;; ==== let-last-form ====
170 "A let form is 1valued if its last form is 1valued."
172 (defun testcover-testcase-double (num)
173 (let ((double (* num%%%
2)%%%
))
175 (defun testcover-testcase-nullbody-let (num)
176 (let* ((square (* num%%% num%%%
)%%%
)
177 (double (* 2 num%%%
)%%%
))))
178 (defun testcover-testcase-answer ()
181 (should-not (testcover-testcase-nullbody-let 3))
182 (should (eql (testcover-testcase-answer) 42))
183 (should (eql (testcover-testcase-double 10) 20))
185 ;; ==== if-with-1value-clauses ====
186 "An if is 1valued if both then and else are 1valued."
188 (defun testcover-testcase-describe (val)
189 (if (zerop val%%%
)%%%
191 "a different number"))
192 (defun testcover-testcase-describe-2 (val)
196 (defun testcover-testcase-describe-3 (val)
197 (if (zerop val%%%
)%%%
199 (format "%d" val%%%
)%%%
)%%%
)
200 (should (equal (testcover-testcase-describe 0) "a number"))
201 (should (equal (testcover-testcase-describe-2 0) "zero"))
202 (should (equal (testcover-testcase-describe-2 1) "not zero"))
203 (should (equal (testcover-testcase-describe-3 1) "1"))
205 ;; ==== cond-with-1value-clauses ====
206 "A cond form is marked 1valued if all clauses are 1valued."
208 (defun testcover-testcase-cond (num)
210 ((eql num%%%
0)%%%
'a
)
211 ((eql num%%%
1)%%%
'b
)
212 ((eql num
!!! 2)!!! 'c
)))
213 (defun testcover-testcase-cond-2 (num)
215 ((eql num%%%
0)%%%
(cons 'a
0)!!!)
216 ((eql num%%%
1)%%%
'b
))%%%
)
217 (should (eql (testcover-testcase-cond 1) 'b
))
218 (should (eql (testcover-testcase-cond-2 1) 'b
))
220 ;; ==== condition-case-with-1value-components ====
221 "A condition-case is marked 1valued if its body and handlers are."
223 (defun testcover-testcase-cc (arg)
229 (should-not (testcover-testcase-cc nil
))
231 ;; ==== quotes-within-backquotes-bug-25316 ====
232 "Forms to instrument are found within quotes within backquotes."
233 :expected-result
:failed
235 (defun testcover-testcase-make-list ()
236 (list 'defun
'defvar
))
237 (defmacro testcover-testcase-bq-macro
(arg)
239 `(memq ,arg%%%
'(defconst ,@(testcover-testcase-make-list)))%%%
)
240 (defun testcover-testcase-use-bq-macro (arg)
241 (testcover-testcase-bq-macro arg%%%
)%%%
)
242 (should (equal '(defun defvar) (testcover-testcase-use-bq-macro 'defun
)))
244 ;; ==== progn-functions ====
245 "Some forms are 1value if their last argument is 1value."
247 (defun testcover-testcase-one (arg)
249 (setq arg
(1- arg%%%
)%%%
)%%%
)%%%
251 (setq arg
(1+ arg%%%
)%%%
)%%%
254 (should (eql 1 (testcover-testcase-one 0)))
255 ;; ==== prog1-functions ====
256 "Some forms are 1value if their first argument is 1value."
258 (defun testcover-testcase-unwinder (arg)
263 (format "unwinding %s!" arg%%%
)%%%
))
264 (defun testcover-testcase-divider (arg)
267 (format "unwinding! %s" arg%%%
)%%%
)%%%
)
269 (should (eq 0 (testcover-testcase-unwinder 0)))
270 (should (eq 1 (testcover-testcase-divider 100)))
272 ;; ==== compose-functions ====
273 "Some functions are 1value if all their arguments are 1value."
275 (defconst testcover-testcase-count
3)
276 (defun testcover-testcase-number ()
277 (+ 1 testcover-testcase-count
))
278 (defun testcover-testcase-more ()
279 (+ 1 (testcover-testcase-number) testcover-testcase-count
))
281 (should (equal (testcover-testcase-more) 8))
283 ;; ==== apply-quoted-symbol ====
284 "Apply with a quoted function symbol treated as 1value if function is."
286 (defun testcover-testcase-numlist (flag)
290 (defun testcover-testcase-sum (flag)
291 (apply '+ (testcover-testcase-numlist flag%%%
)))
292 (defun testcover-testcase-label ()
293 (apply 'message
"edebug uses: %s %s" (list 1 2)!!!)!!!)
295 (should (equal 6 (testcover-testcase-sum t
)))
297 ;; ==== backquote-1value-bug-24509 ====
298 "Commas within backquotes are recognized as non-1value."
299 :expected-result
:failed
301 (defmacro testcover-testcase-lambda
(&rest body
)
304 (defun testcover-testcase-example ()
305 (let ((lambda-1 (testcover-testcase-lambda (format "lambda-%d" 1))%%%
)
306 (lambda-2 (testcover-testcase-lambda (format "lambda-%d" 2))%%%
))
307 (concat (funcall lambda-1%%%
)%%%
" "
308 (funcall lambda-2%%%
)%%%
)%%%
)%%%
)
310 (defmacro testcover-testcase-message-symbol
(name)
311 `(message "%s" ',name
))
313 (defun testcover-testcase-example-2 ()
315 (testcover-testcase-message-symbol foo
)%%%
316 (testcover-testcase-message-symbol bar
)%%%
)%%%
)
318 (should (equal "lambda-1 lambda-2" (testcover-testcase-example)))
319 (should (equal "foobar" (testcover-testcase-example-2)))
321 ;; ==== pcase-bug-24688 ====
322 "Testcover copes with condition-case within backquoted list."
323 :expected-result
:failed
325 (defun testcover-testcase-pcase (form)
327 (`(condition-case ,var
,protected-form .
,handlers
)
328 (list var%%% protected-form%%% handlers%%%
)%%%
)
331 (should (equal (testcover-testcase-pcase '(condition-case a
334 '(a (/ 5 a
) ((error 0)))))
336 ;; ==== defun-in-backquote-bug-11307-and-24743 ====
337 "Testcover handles defun forms within backquoted list."
338 :expected-result
:failed
340 (defmacro testcover-testcase-defun
(name &rest body
)
341 (declare (debug (symbolp def-body
)))
342 `(defun ,name
() ,@body
))
344 (testcover-testcase-defun foo (+ 1 2))
345 (testcover-testcase-defun bar (+ 3 4))
346 (should (eql (foo) 3))
347 (should (eql (bar) 7))
349 ;; ==== closure-1value-bug ====
350 "Testcover does not mark closures as 1value."
351 :expected-result
:failed
353 ;; -*- lexical-binding:t -*-
354 (setq testcover-testcase-foo nil
)
355 (setq testcover-testcase-bar
0)
357 (defun testcover-testcase-baz (arg)
358 (setq testcover-testcase-foo
359 (lambda () (+ arg testcover-testcase-bar%%%
))))
361 (testcover-testcase-baz 2)
362 (should (equal 2 (funcall testcover-testcase-foo
)))
363 (testcover-testcase-baz 3)
364 (should (equal 3 (funcall testcover-testcase-foo
)))
366 ;; ==== by-value-vs-by-reference-bug-25351 ====
367 "An object created by a 1value expression may be modified by other code."
368 :expected-result
:failed
370 (defun testcover-testcase-ab ()
372 (defun testcover-testcase-change-it (arg)
373 (setf (cadr arg%%%
)%%%
'c
)%%%
376 (should (equal (testcover-testcase-change-it (testcover-testcase-ab)) '(a c
)))
377 (should (equal (testcover-testcase-ab) '(a b
)))
379 ;; ==== 1value-error-test ====
380 "Forms wrapped by `1value' should always return the same value."
382 (defun testcover-testcase-thing (arg)
383 (1value (list 1 arg
3)))
385 (should (equal '(1 2 3) (testcover-testcase-thing 2)))
386 (should-error (testcover-testcase-thing 3))
388 ;; ==== dotted-backquote ====
389 "Testcover correctly instruments dotted backquoted lists."
391 (defun testcover-testcase-dotted-bq (flag extras
)
393 `(a b c .
,(and flag extras%%%
))))
396 (should (equal '(a b c
) (testcover-testcase-dotted-bq nil
'(d e
))))
397 (should (equal '(a b c d e
) (testcover-testcase-dotted-bq t
'(d e
))))
399 ;; ==== backquoted-vector-bug-25316 ====
400 "Testcover reinstruments within backquoted vectors."
401 :expected-result
:failed
403 (defun testcover-testcase-vec (a b c
)
404 `[,a%%%
,(list b%%% c%%%
)%%%
]%%%
)
406 (defun testcover-testcase-vec-in-list (d e f
)
407 `([[,d%%%
,e%%%
] ,f%%%
])%%%
)
409 (defun testcover-testcase-vec-arg (num)
410 (list `[,num%%%
]%%%
)%%%
)
412 (should (equal [1 (2 3)] (testcover-testcase-vec 1 2 3)))
413 (should (equal '([[4 5] 6]) (testcover-testcase-vec-in-list 4 5 6)))
414 (should (equal '([100]) (testcover-testcase-vec-arg 100)))
416 ;; ==== vector-in-macro-spec-bug-25316 ====
417 "Testcover reinstruments within vectors."
418 :expected-result :failed
420 (defmacro testcover-testcase-nth-case (arg vec)
422 (debug (form (vector &rest form))))
423 `(eval (aref ,vec%%% ,arg%%%))%%%)
425 (defun testcover-testcase-use-nth-case (choice val)
426 (testcover-testcase-nth-case choice
432 (should (eql 42 (testcover-testcase-use-nth-case 2 6)))
433 (should (eql 49 (testcover-testcase-use-nth-case 2 7)))
434 (should (eql 0 (testcover-testcase-use-nth-case 1 1 )))
436 ;; ==== mapcar-is-not-compose ====
437 "Mapcar with 1value arguments is not 1value."
438 :expected-result :failed
440 (defvar testcover-testcase-num 0)
441 (defun testcover-testcase-add-num (n)
442 (+ testcover-testcase-num n))
443 (defun testcover-testcase-mapcar-sides ()
444 (mapcar 'testcover-testcase-add-num '(1 2 3)))
446 (setq testcover-testcase-num 1)
447 (should (equal (testcover-testcase-mapcar-sides) '(2 3 4)))
448 (setq testcover-testcase-num 2)
449 (should (equal (testcover-testcase-mapcar-sides) '(3 4 5)))
451 ;; ==== function-with-edebug-spec-bug-25316 ====
452 "Functions can have edebug specs too.
453 See c-make-font-lock-search-function for an example in the Emacs
454 sources. The other issue is that it's ok to use quote in an
455 edebug spec, so testcover needs to cope with that."
456 :expected-result :failed
458 (defun testcover-testcase-make-function (forms)
459 `(lambda (flag) (if flag 0 ,@forms%%%))%%%)
461 (def-edebug-spec testcover-testcase-make-function
462 (("quote" (&rest def-form))))
464 (defun testcover-testcase-thing ()
465 (testcover-testcase-make-function '((+ 1 (+ 2 (+ 3 (+ 4 5))))))%%%)
467 (defun testcover-testcase-use-thing ()
468 (funcall (testcover-testcase-thing)%%% nil)%%%)
470 (should (equal (testcover-testcase-use-thing) 15))
472 ;; ==== backquoted-dotted-alist ====
473 "Testcover can instrument a dotted alist constructed with backquote."
475 (defun testcover-testcase-make-alist (expr entries)
476 `((0 . ,expr%%%) . ,entries%%%)%%%)
478 (should (equal (testcover-testcase-make-alist "foo" '((1 . "bar") (2 . "baz")))
479 '((0 . "foo") (1 . "bar") (2 . "baz"))))
481 ;; ==== coverage-of-the-unknown-symbol-bug-25471 ====
482 "Testcover correctly records coverage of code which uses `unknown'"
483 :expected-result :failed
485 (defun testcover-testcase-how-do-i-know-you (name)
486 (let ((val 'unknown))
487 (when (equal name%%% "Bob")%%%
488 (setq val 'known)!!!)
491 (should (eq (testcover-testcase-how-do-i-know-you "Liz") 'unknown))
493 ;; testcases.el ends here.