Subject: bug#25316: 26.0.50; Bugs in testcover-reinstrument

From: Gemini Lasswell <[email-masked]>
Date: Sat, 31 Dec 2016 16:39:38 -0800

I'm working on tests for testcover.el and a refactoring of
testcover-reinstrument to use pcase. In the process I've found these
bugs. The refactoring will fix these as well as make
testcover-reinstrument easier to read and modify.

Since testcover-start requires the code it works on to be saved in a
file, the instructions to reproduce the bugs below all assume that you
have saved the code snippet given in a file called bug.el. If you are
running Emacs 25 and testcover-start doesn't work, load it with this: 
M-: (require 'testcover) RET

I've reproduced all of these using emacs -Q.

1. Wrapping forms in 1value suppresses more splotches than it should.

(defun my-bug (num)
  (1value (- num num (- num 3) (* num -1) 3)))

To reproduce:
M-x testcover-start RET bug.el RET
M-: (my-bug 5) RET
M-x testcover-mark-all RET RET

Result: The form (- num 3) does not have the tan splotch that it should
have. (* num -1) does get a splotch.

2. Testcover splotches backquoted expressions containing only constants.

(defconst my-const "apples")
(defun my-bug ()
  `(,my-const "oranges"))

To reproduce:
M-x testcover-start RET bug.el RET
M-: (my-bug) RET
M-x testcover-mark-all RET RET

Result: The form `(,my-const "oranges") has a tan splotch. But
since it will always evaluate to ("apples" "oranges"), Testcover should
mark it as 1value and not splotch it.

3. Testcover fails to reinstrument inside vectors and backquoted vectors.

(defun my-bug (a b c)
  `[,a ,(list b c)])
  
(defmacro my-nth-case (arg vec)
  (declare (indent 1)
           (debug (form (vector &rest form))))
  `(eval (aref ,vec ,arg)))

(defun my-bug-2 (choice val)
  (my-nth-case choice
    [(+ 1 val)
     (- 1 val)
     (* 7 val)
     (/ 4 val)]))

To reproduce:
M-x testcover-start RET bug.el RET

Followed by either one of these:
M-: (my-bug 1 2 3) RET
M-: (my-bug-2 2 6) RET

Result in both cases: void-variable edebug-freq-count or
wrong-type-argument consp nil depending on if you are running the
current master or not. The errors happen in an edebug-after that did not
get replaced by a testcover-after.

4. Testcover incorrectly parses quoted forms within backquotes.

(defun my-make-list ()
  (list 'defun 'defvar))

(defmacro my-bq-macro (fun)
  (declare (debug (symbolp)))
  `(memq ,fun '(defconst ,@(my-make-list))))

(defun my-use-bq-macro (fun)
  (my-bq-macro fun))

To reproduce:
M-x testcover-start RET bug.el RET

Result: void-variable edebug-freq-count or wrong-type-argument consp
nil, another error from an edebug-after not replaced during
reinstrumentation. C-h v testcover-module-constants RET will show that
testcover was trying to reinstrument the list beginning with defconst as
a top-level form.

5. Testcover doesn't correctly reinstrument code matching an Edebug spec
containing a quote. See c-make-font-lock-search-function for an example
of an Edebug spec containing a quote in the Emacs sources.

(defun my-make-function (forms)
  `(lambda (flag) (if flag 0 ,@forms)))

(def-edebug-spec my-make-function
  (("quote" (&rest def-form))))

(defun my-thing ()
  (my-make-function '((+ 1 (+ 2 (+ 3 (+ 4 5)))))))

(defun my-use-thing ()
  (funcall (my-thing) nil))

To reproduce:
M-x testcover-start RET bug.el RET
M-: (my-use-thing) RET

Result: Emacs will give you the debugger prompt inside the definition of
my-thing, because an edebug-enter didn't get changed to a
testcover-enter in the instrumentation.