aboutsummaryrefslogtreecommitdiff
path: root/tests/test-coverage-core--intersect.el
blob: 00542cb23d042ba0e694776356d8713c86323077 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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