Skip to content

Commit

Permalink
lcov: Replace error with cov--warning in cov--lcov-parse
Browse files Browse the repository at this point in the history
`error' is not a good function to use in code called from a minor
mode.  This switch should allow for some unexpected lines and/or bad
state without signalling errors.  No guarantee for data correctness...

Further fixes for AdamNiederer#45.
  • Loading branch information
snogge authored and AdamNiederer committed Jul 27, 2022
1 parent 5d853d2 commit cd3e199
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 37 deletions.
54 changes: 28 additions & 26 deletions cov.el
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
;; Maintainer: Adam Niederer
;; Created: 12 Aug 2016

;; Keywords: coverage gcov c
;; Keywords: coverage gcov c lcov coveralls clover
;; Homepage: https://github.com/AdamNiederer/cov
;; Version: 0.1.0
;; Package-Requires: ((emacs "24.4") (f "0.18.2") (s "1.11.0") (elquery))
Expand Down Expand Up @@ -390,37 +390,38 @@ Return a list `((FILE . ((LINE-NUM EXEC-COUNT) ...)) ...)'."
(while (not (eobp))
(if (looking-at cov--lcov-prefix-re)
(goto-char (match-end 0))
(error "Unable to parse lcov data from %s: %s"
cov-coverage-file
(buffer-substring (line-beginning-position) (line-end-position))))
(cov--warning "Unable to parse lcov data from %s:%d: %s"
cov-coverage-file (line-number-at-pos)
(buffer-substring (line-beginning-position) (line-end-position))))
(pcase (match-string 1)
;; Each SF signals the start of a new SourceFile.
("SF" (if (or sourcefile filelines)
(error "`lcov' parse error, SF with no preceeding end_of_record %s:%d"
cov-coverage-file (line-number-at-pos (point))))
;; SF always hold an absolute path
(setq sourcefile (file-truename
(expand-file-name
(buffer-substring (point) (line-end-position))
(file-name-directory cov-coverage-file))))
(setq filelines
(or (gethash sourcefile data)
(puthash sourcefile (make-hash-table :test 'eql) data))))
(cov--warning
"`lcov' parse error, SF with no preceeding end_of_record %s:%d"
cov-coverage-file (line-number-at-pos))
;; SF always hold an absolute path
(setq sourcefile (file-truename
(expand-file-name
(buffer-substring (point) (line-end-position))
(file-name-directory cov-coverage-file))))
(setq filelines
(or (gethash sourcefile data)
(puthash sourcefile (make-hash-table :test 'eql) data)))))
;; DA:<line-num>,<exec-count>[,...]
("DA"
(if filelines
(if (looking-at (rx (group-n 1 (1+ digit)) ?,
(group-n 2 (1+ digit))
(optional ?, (group (* any)))))
(let ((lineno (string-to-number (match-string 1)))
(count (string-to-number (match-string 2))))
(puthash lineno (+ (gethash lineno filelines 0) count) filelines))
(error "`lcov' parse error, bad DA line %s:%d"
cov-coverage-file (line-number-at-pos (point))))
(error "`lcov' parse error, DA line %s:%d without preceeding SF"
cov-coverage-file (line-number-at-pos (point)))))
;; End of coverage data for a source file, push
;; current file information to `data'
(group-n 2 (1+ digit))
(optional ?, (group (* any)))))
(let ((lineno (string-to-number (match-string 1)))
(count (string-to-number (match-string 2))))
(puthash lineno (+ (gethash lineno filelines 0) count) filelines))
(cov--warning "`lcov' parse error, bad DA line %s:%d"
cov-coverage-file (line-number-at-pos)))
(cov--warning "`lcov' parse error, DA line %s:%d without preceeding SF"
cov-coverage-file (line-number-at-pos))))
;; End of coverage data for a source file, clear the
;; decks for a new SF line
("end_of_record" (setq sourcefile nil filelines nil)))
(forward-line 1))))))
;; TODO: Make it possible - or even mandatory - to use hashes instead of lists
Expand Down Expand Up @@ -523,7 +524,8 @@ Project coveragepy is released at <https://github.com/nedbat/coveragepy/>."
matches))

(defun cov--read-and-parse (file-path format)
"Read coverage file FILE-PATH in FORMAT into temp buffer and parse it using `cov--FORMAT-parse'.
"Parse coverage file FILE-PATH in FORMAT.
Load FILE-PATH into temp buffer and parse it using `cov--FORMAT-parse'.
`cov-coverage-file' is set buffer-locally to FILE-PATH."
(with-temp-buffer
(insert-file-contents file-path)
Expand Down
55 changes: 44 additions & 11 deletions test/cov-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -118,24 +118,57 @@ discarded when the buffer is killed."
(with-temp-buffer
(insert "dummy data\n")
(let ((cov-coverage-file "/not/a/real/file/path.info"))
(should (equal
(should-error (cov--lcov-parse (current-buffer))
:type 'error :exclude-subtypes t)
`(error
,(format "Unable to parse lcov data from %s: dummy data" cov-coverage-file)))))))
(mocker-let ((display-warning
(type message &optional level buffer-name)
((:input '(cov "Unable to parse lcov data from /not/a/real/file/path.info:1: dummy data" nil nil) :output nil :occur 1))))
(should-not (cov--lcov-parse (current-buffer)))))))

(ert-deftest cov--lcov-parse-no-end_of_record ()
"Test lcov parsing with missing end_of_record."
:tags '(cov--lcov-parse)
(cov--with-test-buffer "lcov/same-dir/lcov.info"
(goto-char 1)
(delete-matching-lines "end_of_record")
(let ((cov-coverage-file (buffer-file-name)))
(should (equal
(should-error (cov--lcov-parse) :type 'error :exclude-subtypes t)
`(error
,(format "‘lcov’ parse error, SF with no preceeding end_of_record %s:16"
cov-coverage-file)))))))
(let ((cov-coverage-file (buffer-file-name))
(msg-fmt (format "`lcov' parse error, SF with no preceeding end_of_record %s/lcov/same-dir/lcov.info:%%d" test-path)))
(ert-info ((progn "Expect five calls to `display-warning'"))
(mocker-let ((display-warning
(type message &optional level buffer-name)
((:input `(cov ,(format msg-fmt 16) nil nil) :output nil :occur 1)
(:input `(cov ,(format msg-fmt 30) nil nil) :output nil :occur 1)
(:input `(cov ,(format msg-fmt 44) nil nil) :output nil :occur 1)
(:input `(cov ,(format msg-fmt 57) nil nil) :output nil :occur 1)
(:input `(cov ,(format msg-fmt 70) nil nil) :output nil :occur 1))))
(should (equal (cov--lcov-parse)
;; This is the sum of all line counts in lcov.info
'(("/test/lcov/same-dir/extra.c"
(3 2)
(5 12)
(6 48)
(7 282)
(8 242)
(9 3)
(11 1))))))))))

(ert-deftest cov--lcov-parse-da-without-sf ()
"Test lcov parsing where DA occurs without preceeding SF."
:tags '(cov--lcov-parse)
(with-temp-buffer
(insert "DA:3,0\n"
"SF:/test/lcov/same-dir/extra.c\n"
"DA:3,1,D+9fSK6I3QDPStN1zNNHSQ\n"
"end_of_record\n"
"DA:3,1,D+9fSK6I3QDPStN1zNNHSQ\n")
(goto-char 1)
(let ((cov-coverage-file "/not/a/real/file/path.info")
(msg-fmt "`lcov' parse error, DA line /not/a/real/file/path.info:%d without preceeding SF"))
(mocker-let ((display-warning
(type message &optional level buffer-name)
((:input `(cov ,(format msg-fmt 1) nil nil) :output nil :occur 1)
(:input `(cov ,(format msg-fmt 5) nil nil) :output nil :occur 1))))
(should (equal (cov--lcov-parse (current-buffer))
'(("/test/lcov/same-dir/extra.c"
(3 1)))))))))

;; cov--coveralls-parse
(ert-deftest cov--coveralls-parse--basic-test ()
Expand Down

0 comments on commit cd3e199

Please sign in to comment.