aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test-coverage-core--intersect.el144
1 files changed, 144 insertions, 0 deletions
diff --git a/tests/test-coverage-core--intersect.el b/tests/test-coverage-core--intersect.el
new file mode 100644
index 00000000..00542cb2
--- /dev/null
+++ b/tests/test-coverage-core--intersect.el
@@ -0,0 +1,144 @@
+;;; test-coverage-core--intersect.el --- Tests for cj/--coverage-intersect -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Unit tests for `cj/--coverage-intersect', the pure helper that
+;; combines covered-line data (from LCOV) with changed-line data
+;; (from git diff) into per-file records ready for the report buffer.
+;;
+;; Return shape: a list of plists, one per changed file, sorted by path.
+;; (:path "modules/foo.el"
+;; :changed-lines (10 11 12)
+;; :covered-lines (10 11) ; nil when the file isn't tracked
+;; :uncovered-lines (12) ; nil when the file isn't tracked
+;; :tracked t) ; nil when the file isn't in the LCOV data
+
+;;; Code:
+
+(require 'ert)
+
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'coverage-core)
+
+(defun test-coverage-intersect--hash-of-lines (pairs)
+ "Build a file → line-set hash table from PAIRS.
+Each pair is (FILE . (LINES...)); LINES becomes a hash-table of line → t."
+ (let ((result (make-hash-table :test 'equal)))
+ (dolist (pair pairs)
+ (let ((lines (make-hash-table :test 'eql)))
+ (dolist (line (cdr pair))
+ (puthash line t lines))
+ (puthash (car pair) lines result)))
+ result))
+
+;;; Normal cases
+
+(ert-deftest test-coverage-intersect-single-file-all-covered ()
+ "Normal: one changed file, all lines covered."
+ (let* ((covered (test-coverage-intersect--hash-of-lines
+ '(("foo.el" 10 11 12))))
+ (changed (test-coverage-intersect--hash-of-lines
+ '(("foo.el" 10 11 12))))
+ (result (cj/--coverage-intersect covered changed))
+ (record (car result)))
+ (should (= 1 (length result)))
+ (should (equal "foo.el" (plist-get record :path)))
+ (should (equal '(10 11 12) (plist-get record :covered-lines)))
+ (should (equal nil (plist-get record :uncovered-lines)))
+ (should (equal '(10 11 12) (plist-get record :changed-lines)))
+ (should (eq t (plist-get record :tracked)))))
+
+(ert-deftest test-coverage-intersect-single-file-partial ()
+ "Normal: partial coverage — 10 and 12 covered, 11 not."
+ (let* ((covered (test-coverage-intersect--hash-of-lines
+ '(("foo.el" 10 12 50))))
+ (changed (test-coverage-intersect--hash-of-lines
+ '(("foo.el" 10 11 12))))
+ (result (cj/--coverage-intersect covered changed))
+ (record (car result)))
+ (should (equal '(10 12) (plist-get record :covered-lines)))
+ (should (equal '(11) (plist-get record :uncovered-lines)))
+ (should (eq t (plist-get record :tracked)))))
+
+(ert-deftest test-coverage-intersect-multiple-files-sorted ()
+ "Normal: multiple files sorted by path."
+ (let* ((covered (test-coverage-intersect--hash-of-lines
+ '(("a.el" 1) ("b.el" 5) ("c.el" 10))))
+ (changed (test-coverage-intersect--hash-of-lines
+ '(("c.el" 10) ("a.el" 1) ("b.el" 5))))
+ (result (cj/--coverage-intersect covered changed))
+ (paths (mapcar (lambda (r) (plist-get r :path)) result)))
+ (should (equal '("a.el" "b.el" "c.el") paths))))
+
+;;; Boundary cases
+
+(ert-deftest test-coverage-intersect-file-not-tracked ()
+ "Boundary: file has changed lines but isn't in the covered set at all."
+ (let* ((covered (test-coverage-intersect--hash-of-lines
+ '(("tracked.el" 1 2 3))))
+ (changed (test-coverage-intersect--hash-of-lines
+ '(("README.md" 5 6 7))))
+ (result (cj/--coverage-intersect covered changed))
+ (record (car result)))
+ (should (= 1 (length result)))
+ (should (equal "README.md" (plist-get record :path)))
+ (should (equal '(5 6 7) (plist-get record :changed-lines)))
+ (should (equal nil (plist-get record :covered-lines)))
+ (should (equal nil (plist-get record :uncovered-lines)))
+ (should (eq nil (plist-get record :tracked)))))
+
+(ert-deftest test-coverage-intersect-tracked-file-none-covered ()
+ "Boundary: file is in LCOV but none of the changed lines are covered."
+ (let* ((covered (test-coverage-intersect--hash-of-lines
+ '(("foo.el" 1 2 3))))
+ (changed (test-coverage-intersect--hash-of-lines
+ '(("foo.el" 10 11 12))))
+ (result (cj/--coverage-intersect covered changed))
+ (record (car result)))
+ (should (eq t (plist-get record :tracked)))
+ (should (equal nil (plist-get record :covered-lines)))
+ (should (equal '(10 11 12) (plist-get record :uncovered-lines)))))
+
+(ert-deftest test-coverage-intersect-empty-changed-lines ()
+ "Boundary: file with empty changed-lines (deletion-only) appears with all lists empty."
+ (let* ((covered (test-coverage-intersect--hash-of-lines
+ '(("foo.el" 1 2))))
+ (changed (test-coverage-intersect--hash-of-lines
+ '(("gone.el"))))
+ (result (cj/--coverage-intersect covered changed))
+ (record (car result)))
+ (should (= 1 (length result)))
+ (should (equal "gone.el" (plist-get record :path)))
+ (should (equal nil (plist-get record :changed-lines)))
+ (should (equal nil (plist-get record :covered-lines)))
+ (should (equal nil (plist-get record :uncovered-lines)))))
+
+(ert-deftest test-coverage-intersect-empty-changed-returns-empty ()
+ "Boundary: empty CHANGED hash table returns an empty list, not nil-as-error."
+ (let* ((covered (test-coverage-intersect--hash-of-lines
+ '(("foo.el" 1 2 3))))
+ (changed (make-hash-table :test 'equal))
+ (result (cj/--coverage-intersect covered changed)))
+ (should (listp result))
+ (should (= 0 (length result)))))
+
+(ert-deftest test-coverage-intersect-empty-covered-all-not-tracked ()
+ "Boundary: empty COVERED means every changed file is not-tracked."
+ (let* ((covered (make-hash-table :test 'equal))
+ (changed (test-coverage-intersect--hash-of-lines
+ '(("a.el" 1) ("b.el" 5))))
+ (result (cj/--coverage-intersect covered changed)))
+ (should (= 2 (length result)))
+ (dolist (record result)
+ (should (eq nil (plist-get record :tracked))))))
+
+;;; Error cases
+
+(ert-deftest test-coverage-intersect-nil-inputs-return-empty ()
+ "Error: nil CHANGED returns an empty list rather than erroring."
+ (should (equal nil (cj/--coverage-intersect nil nil)))
+ (should (equal nil (cj/--coverage-intersect
+ (test-coverage-intersect--hash-of-lines '(("x" 1)))
+ nil))))
+
+(provide 'test-coverage-core--intersect)
+;;; test-coverage-core--intersect.el ends here