diff options
Diffstat (limited to 'tests/test-coverage-core--intersect.el')
| -rw-r--r-- | tests/test-coverage-core--intersect.el | 144 |
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 |
