diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/lisp/progmodes/flymake-tests.el | 246 |
1 files changed, 147 insertions, 99 deletions
diff --git a/test/lisp/progmodes/flymake-tests.el b/test/lisp/progmodes/flymake-tests.el index 222c8f11848..5e042f2b082 100644 --- a/test/lisp/progmodes/flymake-tests.el +++ b/test/lisp/progmodes/flymake-tests.el | |||
| @@ -36,6 +36,26 @@ | |||
| 36 | 36 | ||
| 37 | ;; | 37 | ;; |
| 38 | ;; | 38 | ;; |
| 39 | (defun flymake-tests--wait-for-backends () | ||
| 40 | ;; Weirdness here... http://debbugs.gnu.org/17647#25 | ||
| 41 | ;; ... meaning `sleep-for', and even | ||
| 42 | ;; `accept-process-output', won't suffice as ways to get | ||
| 43 | ;; process filters and sentinels to run, though they do work | ||
| 44 | ;; fine in a non-interactive batch session. The only thing | ||
| 45 | ;; that will indeed unblock pending process output is | ||
| 46 | ;; reading an input event, so, as a workaround, use a dummy | ||
| 47 | ;; `read-event' with a very short timeout. | ||
| 48 | (unless noninteractive (read-event "" nil 0.1)) | ||
| 49 | (cl-loop repeat 5 | ||
| 50 | for notdone = (cl-set-difference (flymake-running-backends) | ||
| 51 | (flymake-reporting-backends)) | ||
| 52 | while notdone | ||
| 53 | unless noninteractive do (read-event "" nil 0.1) | ||
| 54 | do (sleep-for (+ 0.5 flymake-no-changes-timeout)) | ||
| 55 | finally (when notdone (ert-fail | ||
| 56 | (format "Some backends not reporting yet %s" | ||
| 57 | notdone))))) | ||
| 58 | |||
| 39 | (cl-defun flymake-tests--call-with-fixture (fn file | 59 | (cl-defun flymake-tests--call-with-fixture (fn file |
| 40 | &key (severity-predicate | 60 | &key (severity-predicate |
| 41 | nil sev-pred-supplied-p)) | 61 | nil sev-pred-supplied-p)) |
| @@ -46,7 +66,6 @@ SEVERITY-PREDICATE is used to setup | |||
| 46 | (visiting (find-buffer-visiting file)) | 66 | (visiting (find-buffer-visiting file)) |
| 47 | (buffer (or visiting (find-file-noselect file))) | 67 | (buffer (or visiting (find-file-noselect file))) |
| 48 | (process-environment (cons "LC_ALL=C" process-environment)) | 68 | (process-environment (cons "LC_ALL=C" process-environment)) |
| 49 | (i 0) | ||
| 50 | (warning-minimum-log-level :error)) | 69 | (warning-minimum-log-level :error)) |
| 51 | (unwind-protect | 70 | (unwind-protect |
| 52 | (with-current-buffer buffer | 71 | (with-current-buffer buffer |
| @@ -55,18 +74,7 @@ SEVERITY-PREDICATE is used to setup | |||
| 55 | (setq-local flymake-proc-diagnostic-type-pred severity-predicate)) | 74 | (setq-local flymake-proc-diagnostic-type-pred severity-predicate)) |
| 56 | (goto-char (point-min)) | 75 | (goto-char (point-min)) |
| 57 | (unless flymake-mode (flymake-mode 1)) | 76 | (unless flymake-mode (flymake-mode 1)) |
| 58 | ;; Weirdness here... http://debbugs.gnu.org/17647#25 | 77 | (flymake-tests--wait-for-backends) |
| 59 | ;; ... meaning `sleep-for', and even | ||
| 60 | ;; `accept-process-output', won't suffice as ways to get | ||
| 61 | ;; process filters and sentinels to run, though they do work | ||
| 62 | ;; fine in a non-interactive batch session. The only thing | ||
| 63 | ;; that will indeed unblock pending process output is | ||
| 64 | ;; reading an input event, so, as a workaround, use a dummy | ||
| 65 | ;; `read-event' with a very short timeout. | ||
| 66 | (unless noninteractive (read-event "" nil 0.1)) | ||
| 67 | (while (and (flymake-is-running) (< (setq i (1+ i)) 10)) | ||
| 68 | (unless noninteractive (read-event "" nil 0.1)) | ||
| 69 | (sleep-for (+ 0.5 flymake-no-changes-timeout))) | ||
| 70 | (funcall fn))) | 78 | (funcall fn))) |
| 71 | (and buffer | 79 | (and buffer |
| 72 | (not visiting) | 80 | (not visiting) |
| @@ -119,38 +127,37 @@ SEVERITY-PREDICATE is used to setup | |||
| 119 | (ert-deftest different-diagnostic-types () | 127 | (ert-deftest different-diagnostic-types () |
| 120 | "Test GCC warning via function predicate." | 128 | "Test GCC warning via function predicate." |
| 121 | (skip-unless (and (executable-find "gcc") (executable-find "make"))) | 129 | (skip-unless (and (executable-find "gcc") (executable-find "make"))) |
| 122 | (flymake-tests--with-flymake | 130 | (let ((flymake-wrap-around nil)) |
| 123 | ("errors-and-warnings.c") | 131 | (flymake-tests--with-flymake |
| 124 | (flymake-goto-next-error) | 132 | ("errors-and-warnings.c") |
| 125 | (should (eq 'flymake-error (face-at-point))) | 133 | (flymake-goto-next-error) |
| 126 | (flymake-goto-next-error) | 134 | (should (eq 'flymake-error (face-at-point))) |
| 127 | (should (eq 'flymake-note (face-at-point))) | 135 | (flymake-goto-next-error) |
| 128 | (flymake-goto-next-error) | 136 | (should (eq 'flymake-note (face-at-point))) |
| 129 | (should (eq 'flymake-warning (face-at-point))) | 137 | (flymake-goto-next-error) |
| 130 | (flymake-goto-next-error) | 138 | (should (eq 'flymake-warning (face-at-point))) |
| 131 | (should (eq 'flymake-error (face-at-point))) | 139 | (flymake-goto-next-error) |
| 132 | (flymake-goto-next-error) | 140 | (should (eq 'flymake-error (face-at-point))) |
| 133 | (should (eq 'flymake-warning (face-at-point))) | 141 | (flymake-goto-next-error) |
| 134 | (flymake-goto-next-error) | 142 | (should (eq 'flymake-warning (face-at-point))) |
| 135 | (should (eq 'flymake-warning (face-at-point))) | 143 | (flymake-goto-next-error) |
| 136 | (let ((flymake-wrap-around nil)) | 144 | (should (eq 'flymake-warning (face-at-point))) |
| 137 | (should-error (flymake-goto-next-error nil nil t))) )) | 145 | (should-error (flymake-goto-next-error nil nil t))))) |
| 138 | 146 | ||
| 139 | (ert-deftest included-c-header-files () | 147 | (ert-deftest included-c-header-files () |
| 140 | "Test inclusion of .h header files." | 148 | "Test inclusion of .h header files." |
| 141 | (skip-unless (and (executable-find "gcc") (executable-find "make"))) | 149 | (skip-unless (and (executable-find "gcc") (executable-find "make"))) |
| 142 | (flymake-tests--with-flymake | 150 | (let ((flymake-wrap-around nil)) |
| 143 | ("some-problems.h") | 151 | (flymake-tests--with-flymake |
| 144 | (flymake-goto-next-error) | 152 | ("some-problems.h") |
| 145 | (should (eq 'flymake-warning (face-at-point))) | 153 | (flymake-goto-next-error) |
| 146 | (flymake-goto-next-error) | 154 | (should (eq 'flymake-warning (face-at-point))) |
| 147 | (should (eq 'flymake-error (face-at-point))) | 155 | (flymake-goto-next-error) |
| 148 | (let ((flymake-wrap-around nil)) | 156 | (should (eq 'flymake-error (face-at-point))) |
| 149 | (should-error (flymake-goto-next-error nil nil t))) ) | 157 | (should-error (flymake-goto-next-error nil nil t))) |
| 150 | (flymake-tests--with-flymake | 158 | (flymake-tests--with-flymake |
| 151 | ("no-problems.h") | 159 | ("no-problems.h") |
| 152 | (let ((flymake-wrap-around nil)) | 160 | (should-error (flymake-goto-next-error nil nil t))))) |
| 153 | (should-error (flymake-goto-next-error nil nil t))) )) | ||
| 154 | 161 | ||
| 155 | (defmacro flymake-tests--assert-set (set | 162 | (defmacro flymake-tests--assert-set (set |
| 156 | should | 163 | should |
| @@ -159,19 +166,15 @@ SEVERITY-PREDICATE is used to setup | |||
| 159 | `(progn | 166 | `(progn |
| 160 | ,@(cl-loop | 167 | ,@(cl-loop |
| 161 | for s in should | 168 | for s in should |
| 162 | collect `(should (memq ,s ,set))) | 169 | collect `(should (memq (quote ,s) ,set))) |
| 163 | ,@(cl-loop | 170 | ,@(cl-loop |
| 164 | for s in should-not | 171 | for s in should-not |
| 165 | collect `(should-not (memq ,s ,set))))) | 172 | collect `(should-not (memq (quote ,s) ,set))))) |
| 166 | 173 | ||
| 167 | (ert-deftest dummy-backends () | 174 | (defun flymake-tests--diagnose-words |
| 168 | "Test GCC warning via function predicate." | 175 | (report-fn type words) |
| 169 | (with-temp-buffer | 176 | "Helper. Call REPORT-FN with diagnostics for WORDS in buffer." |
| 170 | (cl-labels | 177 | (funcall report-fn |
| 171 | ((diagnose | ||
| 172 | (report-fn type words) | ||
| 173 | (funcall | ||
| 174 | report-fn | ||
| 175 | (cl-loop | 178 | (cl-loop |
| 176 | for word in words | 179 | for word in words |
| 177 | append | 180 | append |
| @@ -184,32 +187,34 @@ SEVERITY-PREDICATE is used to setup | |||
| 184 | (match-end 0) | 187 | (match-end 0) |
| 185 | type | 188 | type |
| 186 | (concat word " is wrong"))))))) | 189 | (concat word " is wrong"))))))) |
| 187 | (error-backend | 190 | |
| 188 | (report-fn) | 191 | (ert-deftest dummy-backends () |
| 189 | (run-with-timer | 192 | "Test many different kinds of backends." |
| 190 | 0.5 nil | 193 | (with-temp-buffer |
| 191 | #'diagnose report-fn :error '("manha" "prognata"))) | 194 | (cl-letf |
| 192 | (warning-backend | 195 | (((symbol-function 'error-backend) |
| 193 | (report-fn) | 196 | (lambda (report-fn) |
| 194 | (run-with-timer | 197 | (run-with-timer |
| 195 | 0.5 nil | 198 | 0.5 nil |
| 196 | #'diagnose report-fn :warning '("ut" "dolor"))) | 199 | #'flymake-tests--diagnose-words report-fn :error '("manha" "prognata")))) |
| 197 | (sync-backend | 200 | ((symbol-function 'warning-backend) |
| 198 | (report-fn) | 201 | (lambda (report-fn) |
| 199 | (diagnose report-fn :note '("quis" "commodo"))) | 202 | (run-with-timer |
| 200 | (refusing-backend | 203 | 0.5 nil |
| 201 | (_report-fn) | 204 | #'flymake-tests--diagnose-words report-fn :warning '("ut" "dolor")))) |
| 202 | nil) | 205 | ((symbol-function 'sync-backend) |
| 203 | (panicking-backend | 206 | (lambda (report-fn) |
| 204 | (report-fn) | 207 | (flymake-tests--diagnose-words report-fn :note '("quis" "commodo")))) |
| 205 | (run-with-timer | 208 | ((symbol-function 'panicking-backend) |
| 206 | 0.5 nil | 209 | (lambda (report-fn) |
| 207 | report-fn :panic :explanation "The spanish inquisition!")) | 210 | (run-with-timer |
| 208 | (crashing-backend | 211 | 0.5 nil |
| 209 | (_report-fn) | 212 | report-fn :panic :explanation "The spanish inquisition!"))) |
| 210 | ;; HACK: Shoosh log during tests | 213 | ((symbol-function 'crashing-backend) |
| 211 | (setq-local warning-minimum-log-level :emergency) | 214 | (lambda (_report-fn) |
| 212 | (error "crashed"))) | 215 | ;; HACK: Shoosh log during tests |
| 216 | (setq-local warning-minimum-log-level :emergency) | ||
| 217 | (error "crashed")))) | ||
| 213 | (insert "Lorem ipsum dolor sit amet, consectetur adipiscing | 218 | (insert "Lorem ipsum dolor sit amet, consectetur adipiscing |
| 214 | elit, sed do eiusmod tempor incididunt ut labore et dolore | 219 | elit, sed do eiusmod tempor incididunt ut labore et dolore |
| 215 | manha aliqua. Ut enim ad minim veniam, quis nostrud | 220 | manha aliqua. Ut enim ad minim veniam, quis nostrud |
| @@ -220,31 +225,27 @@ SEVERITY-PREDICATE is used to setup | |||
| 220 | sunt in culpa qui officia deserunt mollit anim id est | 225 | sunt in culpa qui officia deserunt mollit anim id est |
| 221 | laborum.") | 226 | laborum.") |
| 222 | (let ((flymake-diagnostic-functions | 227 | (let ((flymake-diagnostic-functions |
| 223 | (list #'error-backend #'warning-backend #'sync-backend | 228 | (list 'error-backend 'warning-backend 'sync-backend |
| 224 | #'refusing-backend #'panicking-backend | 229 | 'panicking-backend |
| 225 | #'crashing-backend | 230 | 'crashing-backend |
| 226 | ))) | 231 | )) |
| 232 | (flymake-wrap-around nil)) | ||
| 227 | (flymake-mode) | 233 | (flymake-mode) |
| 228 | ;; FIXME: accessing some flymake-ui's internals here... | ||
| 229 | (flymake-tests--assert-set flymake--running-backends | ||
| 230 | (#'error-backend #'warning-backend #'panicking-backend) | ||
| 231 | (#'sync-backend #'crashing-backend #'refusing-backend)) | ||
| 232 | 234 | ||
| 233 | (flymake-tests--assert-set flymake--disabled-backends | 235 | (flymake-tests--assert-set (flymake-running-backends) |
| 234 | (#'crashing-backend) | 236 | (error-backend warning-backend panicking-backend) |
| 235 | (#'error-backend #'warning-backend #'sync-backend | 237 | (crashing-backend)) |
| 236 | #'panicking-backend #'refusing-backend)) | ||
| 237 | 238 | ||
| 238 | (cl-loop repeat 10 while (flymake-is-running) | 239 | (flymake-tests--assert-set (flymake-disabled-backends) |
| 239 | unless noninteractive do (read-event "" nil 0.1) | 240 | (crashing-backend) |
| 240 | do (sleep-for (+ 0.5 flymake-no-changes-timeout))) | 241 | (error-backend warning-backend sync-backend |
| 242 | panicking-backend)) | ||
| 241 | 243 | ||
| 242 | (should (eq flymake--running-backends '())) | 244 | (flymake-tests--wait-for-backends) |
| 243 | 245 | ||
| 244 | (flymake-tests--assert-set flymake--disabled-backends | 246 | (flymake-tests--assert-set (flymake-disabled-backends) |
| 245 | (#'crashing-backend #'panicking-backend) | 247 | (crashing-backend panicking-backend) |
| 246 | (#'error-backend #'warning-backend #'sync-backend | 248 | (error-backend warning-backend sync-backend)) |
| 247 | #'refusing-backend)) | ||
| 248 | 249 | ||
| 249 | (goto-char (point-min)) | 250 | (goto-char (point-min)) |
| 250 | (flymake-goto-next-error) | 251 | (flymake-goto-next-error) |
| @@ -265,8 +266,55 @@ SEVERITY-PREDICATE is used to setup | |||
| 265 | (should (eq 'flymake-warning (face-at-point))) ; dolor | 266 | (should (eq 'flymake-warning (face-at-point))) ; dolor |
| 266 | (flymake-goto-next-error) | 267 | (flymake-goto-next-error) |
| 267 | (should (eq 'flymake-error (face-at-point))) ; prognata | 268 | (should (eq 'flymake-error (face-at-point))) ; prognata |
| 268 | (let ((flymake-wrap-around nil)) | 269 | (should-error (flymake-goto-next-error nil nil t)))))) |
| 269 | (should-error (flymake-goto-next-error nil nil t))))))) | 270 | |
| 271 | (ert-deftest recurrent-backend () | ||
| 272 | "Test a backend that calls REPORT-FN multiple times" | ||
| 273 | (with-temp-buffer | ||
| 274 | (let (tick) | ||
| 275 | (cl-letf | ||
| 276 | (((symbol-function 'eager-backend) | ||
| 277 | (lambda (report-fn) | ||
| 278 | (funcall report-fn nil :explanation "very eager but no diagnostics") | ||
| 279 | (display-buffer (current-buffer)) | ||
| 280 | (run-with-timer | ||
| 281 | 0.5 nil | ||
| 282 | (lambda () | ||
| 283 | (flymake-tests--diagnose-words report-fn :warning '("consectetur")) | ||
| 284 | (setq tick t) | ||
| 285 | (run-with-timer | ||
| 286 | 0.5 nil | ||
| 287 | (lambda () | ||
| 288 | (flymake-tests--diagnose-words report-fn :error '("fugiat")) | ||
| 289 | (setq tick t)))))))) | ||
| 290 | (insert "Lorem ipsum dolor sit amet, consectetur adipiscing | ||
| 291 | elit, sed do eiusmod tempor incididunt ut labore et dolore | ||
| 292 | manha aliqua. Ut enim ad minim veniam, quis nostrud | ||
| 293 | exercitation ullamco laboris nisi ut aliquip ex ea commodo | ||
| 294 | consequat. Duis aute irure dolor in reprehenderit in | ||
| 295 | voluptate velit esse cillum dolore eu fugiat nulla | ||
| 296 | pariatur. Excepteur sint occaecat cupidatat non prognata | ||
| 297 | sunt in culpa qui officia deserunt mollit anim id est | ||
| 298 | laborum.") | ||
| 299 | (let ((flymake-diagnostic-functions | ||
| 300 | (list 'eager-backend)) | ||
| 301 | (flymake-wrap-around nil)) | ||
| 302 | (flymake-mode) | ||
| 303 | (flymake-tests--assert-set (flymake-running-backends) | ||
| 304 | (eager-backend) ()) | ||
| 305 | (cl-loop until tick repeat 4 do (sleep-for 0.2)) | ||
| 306 | (setq tick nil) | ||
| 307 | (goto-char (point-max)) | ||
| 308 | (flymake-goto-prev-error) | ||
| 309 | (should (eq 'flymake-warning (face-at-point))) ; consectetur | ||
| 310 | (should-error (flymake-goto-prev-error nil nil t)) | ||
| 311 | (cl-loop until tick repeat 4 do (sleep-for 0.2)) | ||
| 312 | (flymake-goto-next-error) | ||
| 313 | (should (eq 'flymake-error (face-at-point))) ; fugiat | ||
| 314 | (flymake-goto-prev-error) | ||
| 315 | (should (eq 'flymake-warning (face-at-point))) ; back at consectetur | ||
| 316 | (should-error (flymake-goto-prev-error nil nil t)) | ||
| 317 | ))))) | ||
| 270 | 318 | ||
| 271 | (provide 'flymake-tests) | 319 | (provide 'flymake-tests) |
| 272 | 320 | ||