Subject: bug#30909: 27.0.50; Testcover error on vector containing dotted pair

From: Gemini Lasswell <[email-masked]>
Date: Thu, 22 Mar 2018 11:54:04 -0700

When you ask Testcover to cover code containing a vector which
contains a dotted pair, it results in an error.  I introduced this
bug when I rewrote Testcover last year.

To reproduce first save this snippet in a file called bug.el:

(defun my-func ()
  (equal (vector '(8 . "xxx")) [(8 . "xxx")]))

Then:

M-x testcover-start RET bug.el RET

Result: Wrong type argument: listp, "xxx"

Here's a patch to fix this.  While I was adding a test for it, I
noticed that the docstrings for all of Testcover's tests still mention
reinstrumenting, but Testcover now analyzes code instead of
reinstrumenting it, so I also updated the docstrings.

>From a8dfe700d7c2e9c0fbf3f2b400309b2a92a9d401 Mon Sep 17 00:00:00 2001
From: Gemini Lasswell <[email-masked]>
Date: Sun, 18 Mar 2018 13:07:02 -0700
Subject: [PATCH] Fix bug in Testcover's handling of vectors containing dotted
 lists

* lisp/emacs-lisp/testcover.el (testcover-analyze-coverage-compose):
Handle dotted lists.
* test/lisp/emacs-lisp/testcover-resources/testcases.el:
(dotted-list-in-vector-bug): New test case.
(quotes-within-backquotes-bug-25316, dotted-backquote)
(quoted-backquote, backquoted-vector-bug-25316)
(vector-in-macro-spec-bug, backquoted-dotted-alist): Change
docstrings to mention analyzing code instead of reinstrumenting
it.
---
 lisp/emacs-lisp/testcover.el                          |  8 +++++---
 test/lisp/emacs-lisp/testcover-resources/testcases.el | 19 +++++++++++++------
 2 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/lisp/emacs-lisp/testcover.el b/lisp/emacs-lisp/testcover.el
index e0d2797c0c..d48c79cd77 100644
--- a/lisp/emacs-lisp/testcover.el
+++ b/lisp/emacs-lisp/testcover.el
@@ -644,9 +644,11 @@ testcover-analyze-coverage-compose
   "Analyze a list of FORMS for code coverage using FUNC.
 The list is 1valued if all of its constituent elements are also 1valued."
   (let ((result '1value))
-    (dolist (form forms)
-      (let ((val (funcall func form)))
-        (setq result (testcover-coverage-combine result val))))
+    (while (consp forms)
+      (setq result (testcover-coverage-combine result (funcall func (car forms))))
+      (setq forms (cdr forms)))
+    (when forms
+      (setq result (testcover-coverage-combine result (funcall func forms))))
     result))
 
 (defun testcover-analyze-coverage-backquote (bq-list)
diff --git a/test/lisp/emacs-lisp/testcover-resources/testcases.el b/test/lisp/emacs-lisp/testcover-resources/testcases.el
index c9703b03de..510c735e99 100644
--- a/test/lisp/emacs-lisp/testcover-resources/testcases.el
+++ b/test/lisp/emacs-lisp/testcover-resources/testcases.el
@@ -226,7 +226,7 @@ testcover-testcase-cc
 (should-not (testcover-testcase-cc nil))
 
 ;; ==== quotes-within-backquotes-bug-25316 ====
-"Forms to instrument are found within quotes within backquotes."
+"Forms to analyze are found within quotes within backquotes."
 ;; ====
 (defun testcover-testcase-make-list ()
   (list 'defun 'defvar))
@@ -377,7 +377,7 @@ testcover-testcase-thing
 (should-error (testcover-testcase-thing 3))
 
 ;; ==== dotted-backquote ====
-"Testcover correctly instruments dotted backquoted lists."
+"Testcover can analyze code inside dotted backquoted lists."
 ;; ====
 (defun testcover-testcase-dotted-bq (flag extras)
   (let* ((bq
@@ -388,7 +388,7 @@ testcover-testcase-dotted-bq
 (should (equal '(a b c d e) (testcover-testcase-dotted-bq t '(d e))))
 
 ;; ==== quoted-backquote ====
-"Testcover correctly instruments the quoted backquote symbol."
+"Testcover correctly handles the quoted backquote symbol."
 ;; ====
 (defun testcover-testcase-special-symbols ()
   (list '\` '\, '\,@))
@@ -396,7 +396,7 @@ testcover-testcase-special-symbols
 (should (equal '(\` \, \,@) (testcover-testcase-special-symbols)))
 
 ;; ==== backquoted-vector-bug-25316 ====
-"Testcover reinstruments within backquoted vectors."
+"Testcover can analyze code within backquoted vectors."
 ;; ====
 (defun testcover-testcase-vec (a b c)
   `[,a%%% ,(list b%%% c%%%)%%%]%%%)
@@ -411,8 +411,15 @@ testcover-testcase-vec-arg
 (should (equal '([[4 5] 6]) (testcover-testcase-vec-in-list 4 5 6)))
 (should (equal '([100]) (testcover-testcase-vec-arg 100)))
 
+;; ==== dotted-list-in-vector-bug ====
+"Testcover can analyze dotted pairs within vectors."
+;; ====
+(defun testcover-testcase-vectors-with-dotted-pairs ()
+  (equal [(1 . "x")] [(1 2 . "y")])%%%)
+(should-not (testcover-testcase-vectors-with-dotted-pairs))
+
 ;; ==== vector-in-macro-spec-bug-25316 ====
-"Testcover reinstruments within vectors."
+"Testcover can analyze code inside vectors."
 ;; ====
 (defmacro testcover-testcase-nth-case (arg vec)
   (declare (indent 1)
@@ -466,7 +473,7 @@ testcover-testcase-use-thing
 (should (equal (testcover-testcase-use-thing) 15))
 
 ;; ==== backquoted-dotted-alist ====
-"Testcover can instrument a dotted alist constructed with backquote."
+"Testcover can analyze a dotted alist constructed with backquote."
 ;; ====
 (defun testcover-testcase-make-alist (expr entries)
   `((0 . ,expr%%%) . ,entries%%%)%%%)
-- 
2.15.0