]> code.delx.au - gnu-emacs-elpa/blob - test/context-coloring-test.el
Add let test.
[gnu-emacs-elpa] / test / context-coloring-test.el
1 ;;; context-coloring-test.el --- Tests for context coloring -*- lexical-binding: t; -*-
2
3 ;; Copyright (C) 2014-2015 Free Software Foundation, Inc.
4
5 ;; This file is part of GNU Emacs.
6
7 ;; This program is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation, either version 3 of the License, or
10 ;; (at your option) any later version.
11
12 ;; This program is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
16
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20 ;;; Commentary:
21
22 ;; Tests for context coloring.
23
24 ;; Use with `make test'.
25
26 ;;; Code:
27
28 (require 'context-coloring)
29 (require 'ert-async)
30 (require 'js2-mode)
31
32
33 ;;; Test running utilities
34
35 (defconst context-coloring-test-path
36 (file-name-directory (or load-file-name buffer-file-name))
37 "This file's directory.")
38
39 (defun context-coloring-test-read-file (path)
40 "Read a file's contents from PATH into a string."
41 (with-temp-buffer
42 (insert-file-contents (expand-file-name path context-coloring-test-path))
43 (buffer-string)))
44
45 (defun context-coloring-test-setup ()
46 "Prepare before all tests."
47 (setq context-coloring-syntactic-comments nil)
48 (setq context-coloring-syntactic-strings nil))
49
50 (defun context-coloring-test-cleanup ()
51 "Cleanup after all tests."
52 (setq context-coloring-comments-and-strings nil)
53 (setq context-coloring-js-block-scopes nil)
54 (setq context-coloring-colorize-hook nil)
55 (setq context-coloring-check-scopifier-version-hook nil)
56 (setq context-coloring-maximum-face 7)
57 (setq context-coloring-original-maximum-face
58 context-coloring-maximum-face))
59
60 (defmacro context-coloring-test-with-fixture (fixture &rest body)
61 "With the relative FIXTURE, evaluate BODY in a temporary
62 buffer."
63 `(with-temp-buffer
64 (unwind-protect
65 (progn
66 (context-coloring-test-setup)
67 (insert (context-coloring-test-read-file ,fixture))
68 ,@body)
69 (context-coloring-test-cleanup))))
70
71 (defun context-coloring-test-with-temp-buffer-async (callback)
72 "Create a temporary buffer, and evaluate CALLBACK there. A
73 teardown callback is passed to CALLBACK for it to invoke when it
74 is done."
75 (let ((previous-buffer (current-buffer))
76 (temp-buffer (generate-new-buffer " *temp*")))
77 (set-buffer temp-buffer)
78 (funcall
79 callback
80 (lambda ()
81 (and (buffer-name temp-buffer)
82 (kill-buffer temp-buffer))
83 (set-buffer previous-buffer)))))
84
85 (defun context-coloring-test-with-fixture-async
86 (fixture callback &optional setup)
87 "With the relative FIXTURE, evaluate CALLBACK in a temporary
88 buffer. A teardown callback is passed to CALLBACK for it to
89 invoke when it is done. An optional SETUP callback can run
90 arbitrary code before the mode is invoked."
91 (context-coloring-test-with-temp-buffer-async
92 (lambda (done-with-temp-buffer)
93 (context-coloring-test-setup)
94 (when setup (funcall setup))
95 (insert (context-coloring-test-read-file fixture))
96 (funcall
97 callback
98 (lambda ()
99 (context-coloring-test-cleanup)
100 (funcall done-with-temp-buffer))))))
101
102
103 ;;; Test defining utilities
104
105 (defun context-coloring-test-js-mode (fixture callback &optional setup)
106 "Use FIXTURE as the subject matter for test logic in CALLBACK.
107 Optionally, provide setup code to run before the mode is
108 instantiated in SETUP."
109 (context-coloring-test-with-fixture-async
110 fixture
111 (lambda (done-with-test)
112 (js-mode)
113 (context-coloring-mode)
114 (context-coloring-colorize
115 (lambda ()
116 (funcall callback done-with-test))))
117 setup))
118
119 (defmacro context-coloring-test-js2-mode (fixture setup &rest body)
120 "Use FIXTURE as the subject matter for test logic in BODY."
121 `(context-coloring-test-with-fixture
122 ,fixture
123 (require 'js2-mode)
124 (setq js2-mode-show-parse-errors nil)
125 (setq js2-mode-show-strict-warnings nil)
126 (js2-mode)
127 (when ,setup (funcall ,setup))
128 (context-coloring-mode)
129 ,@body))
130
131 (cl-defmacro context-coloring-test-deftest-js-mode (name &key fixture-name)
132 "Define an asynchronous test for `js-mode' with the name NAME
133 in the typical format."
134 (declare (indent defun))
135 (let ((test-name (intern (format "context-coloring-test-js-mode-%s" name)))
136 (fixture (format "./fixtures/%s.js" (or fixture-name name)))
137 (function-name (intern-soft
138 (format "context-coloring-test-js-%s" name)))
139 (setup-function-name (intern-soft
140 (format
141 "context-coloring-test-js-%s-setup" name))))
142 `(ert-deftest-async ,test-name (done)
143 (context-coloring-test-js-mode
144 ,fixture
145 (lambda (teardown)
146 (unwind-protect
147 (,function-name)
148 (funcall teardown))
149 (funcall done))
150 ',setup-function-name))))
151
152 (cl-defmacro context-coloring-test-deftest-js2-mode (name &key fixture-name)
153 "Define a test for `js2-mode' with the name NAME in the typical
154 format."
155 (declare (indent defun))
156 (let ((test-name (intern (format "context-coloring-test-js2-mode-%s" name)))
157 (fixture (format "./fixtures/%s.js" (or fixture-name name)))
158 (function-name (intern-soft
159 (format "context-coloring-test-js-%s" name)))
160 (setup-function-name (intern-soft
161 (format
162 "context-coloring-test-js-%s-setup" name))))
163 `(ert-deftest ,test-name ()
164 (context-coloring-test-js2-mode
165 ,fixture
166 ',setup-function-name
167 (,function-name)))))
168
169 (cl-defmacro context-coloring-test-deftest-emacs-lisp-mode (name
170 body
171 &key setup)
172 "Define a test for `emacs-lisp-mode' with name and fixture as
173 NAME, with BODY containing the assertions, and SETUP defining the
174 environment."
175 (declare (indent defun))
176 (let ((test-name (intern (format "context-coloring-emacs-lisp-mode-%s" name)))
177 (fixture (format "./fixtures/%s.el" name)))
178 `(ert-deftest ,test-name ()
179 (context-coloring-test-with-fixture
180 ,fixture
181 (emacs-lisp-mode)
182 (when ,setup (funcall ,setup))
183 (context-coloring-mode)
184 (funcall ,body)))))
185
186
187 ;;; Assertion functions
188
189 (defun context-coloring-test-assert-position-level (position level)
190 "Assert that POSITION has LEVEL."
191 (let ((face (get-text-property position 'face))
192 actual-level)
193 (when (not (and face
194 (let* ((face-string (symbol-name face))
195 (matches (string-match
196 context-coloring-level-face-regexp
197 face-string)))
198 (when matches
199 (setq actual-level (string-to-number
200 (substring face-string
201 (match-beginning 1)
202 (match-end 1))))
203 (= level actual-level)))))
204 (ert-fail (format (concat "Expected level at position %s, "
205 "which is \"%s\", to be %s; "
206 "but it was %s")
207 position
208 (buffer-substring-no-properties position (1+ position)) level
209 actual-level)))))
210
211 (defun context-coloring-test-assert-position-face (position face-regexp)
212 "Assert that the face at POSITION satisfies FACE-REGEXP."
213 (let ((face (get-text-property position 'face)))
214 (when (or
215 ;; Pass a non-string to do an `eq' check (against a symbol or nil).
216 (unless (stringp face-regexp)
217 (not (eq face-regexp face)))
218 ;; Otherwise do the matching.
219 (when (stringp face-regexp)
220 (not (string-match-p face-regexp (symbol-name face)))))
221 (ert-fail (format (concat "Expected face at position %s, "
222 "which is \"%s\", to be %s; "
223 "but it was %s")
224 position
225 (buffer-substring-no-properties position (1+ position)) face-regexp
226 face)))))
227
228 (defun context-coloring-test-assert-position-comment (position)
229 (context-coloring-test-assert-position-face
230 position "\\`font-lock-comment\\(-delimiter\\)?-face\\'"))
231
232 (defun context-coloring-test-assert-position-string (position)
233 (context-coloring-test-assert-position-face position 'font-lock-string-face))
234
235 (defun context-coloring-test-assert-coloring (map)
236 "Assert that the current buffer's coloring matches MAP."
237 ;; Omit the superfluous, formatting-related leading newline. Can't use
238 ;; `save-excursion' here because if an assertion fails it will cause future
239 ;; tests to get messed up.
240 (goto-char (point-min))
241 (let* ((map (substring map 1))
242 (index 0)
243 char-string
244 char)
245 (while (< index (length map))
246 (setq char-string (substring map index (1+ index)))
247 (setq char (string-to-char char-string))
248 (cond
249 ;; Newline
250 ((= char 10)
251 (next-logical-line)
252 (beginning-of-line))
253 ;; Number
254 ((and (>= char 48)
255 (<= char 57))
256 (context-coloring-test-assert-position-level
257 (point) (string-to-number char-string))
258 (forward-char))
259 ;; ';' = Comment
260 ((= char 59)
261 (context-coloring-test-assert-position-comment (point))
262 (forward-char))
263 ;; 's' = String
264 ((= char 115)
265 (context-coloring-test-assert-position-string (point))
266 (forward-char))
267 (t
268 (forward-char)))
269 (setq index (1+ index)))))
270
271 (defmacro context-coloring-test-assert-region (&rest body)
272 "Assert something about the face of points in a region.
273 Provides the free variables `i', `length', `point', `face' and
274 `actual-level' to the code in BODY."
275 `(let ((i 0)
276 (length (- end start)))
277 (while (< i length)
278 (let* ((point (+ i start))
279 (face (get-text-property point 'face)))
280 ,@body)
281 (setq i (+ i 1)))))
282
283 (defun context-coloring-test-assert-region-level (start end level)
284 "Assert that all points in the range [START, END) are of level
285 LEVEL."
286 (context-coloring-test-assert-region
287 (let (actual-level)
288 (when (not (when face
289 (let* ((face-string (symbol-name face))
290 (matches (string-match
291 context-coloring-level-face-regexp
292 face-string)))
293 (when matches
294 (setq actual-level (string-to-number
295 (substring face-string
296 (match-beginning 1)
297 (match-end 1))))
298 (= level actual-level)))))
299 (ert-fail (format (concat "Expected level in region [%s, %s), "
300 "which is \"%s\", to be %s; "
301 "but at point %s, it was %s")
302 start end
303 (buffer-substring-no-properties start end) level
304 point actual-level))))))
305
306 (defun context-coloring-test-assert-region-face (start end expected-face)
307 "Assert that all points in the range [START, END) have the face
308 EXPECTED-FACE."
309 (context-coloring-test-assert-region
310 (when (not (eq face expected-face))
311 (ert-fail (format (concat "Expected face in region [%s, %s), "
312 "which is \"%s\", to be %s; "
313 "but at point %s, it was %s")
314 start end
315 (buffer-substring-no-properties start end) expected-face
316 point face)))))
317
318 (defun context-coloring-test-assert-region-comment-delimiter (start end)
319 "Assert that all points in the range [START, END) have
320 `font-lock-comment-delimiter-face'."
321 (context-coloring-test-assert-region-face
322 start end 'font-lock-comment-delimiter-face))
323
324 (defun context-coloring-test-assert-region-comment (start end)
325 "Assert that all points in the range [START, END) have
326 `font-lock-comment-face'."
327 (context-coloring-test-assert-region-face
328 start end 'font-lock-comment-face))
329
330 (defun context-coloring-test-assert-region-string (start end)
331 "Assert that all points in the range [START, END) have
332 `font-lock-string-face'."
333 (context-coloring-test-assert-region-face
334 start end 'font-lock-string-face))
335
336 (defun context-coloring-test-assert-message (expected buffer)
337 "Assert that message EXPECTED exists in BUFFER."
338 (when (null (get-buffer buffer))
339 (ert-fail
340 (format
341 (concat
342 "Expected buffer `%s' to have message \"%s\", "
343 "but the buffer did not have any messages.")
344 buffer expected)))
345 (with-current-buffer buffer
346 (let ((messages (split-string
347 (buffer-substring-no-properties
348 (point-min)
349 (point-max))
350 "\n")))
351 (let ((message (car (nthcdr (- (length messages) 2) messages))))
352 (when (not (equal message expected))
353 (ert-fail
354 (format
355 (concat
356 "Expected buffer `%s' to have message \"%s\", "
357 "but instead it was \"%s\"")
358 buffer expected
359 message)))))))
360
361 (defun context-coloring-test-assert-no-message (buffer)
362 "Assert that BUFFER has no message."
363 (when (get-buffer buffer)
364 (ert-fail (format (concat "Expected buffer `%s' to have no messages, "
365 "but it did: `%s'")
366 buffer
367 (with-current-buffer buffer
368 (buffer-string))))))
369
370 (defun context-coloring-test-kill-buffer (buffer)
371 "Kill BUFFER if it exists."
372 (when (get-buffer buffer) (kill-buffer buffer)))
373
374 (defun context-coloring-test-assert-face (level foreground &optional negate)
375 "Assert that a face for LEVEL exists and that its `:foreground'
376 is FOREGROUND, or the inverse if NEGATE is non-nil."
377 (let* ((face (context-coloring-level-face level))
378 actual-foreground)
379 (when (not (or negate
380 face))
381 (ert-fail (format (concat "Expected face for level `%s' to exist; "
382 "but it didn't")
383 level)))
384 (setq actual-foreground (face-attribute face :foreground))
385 (when (funcall (if negate 'identity 'not)
386 (string-equal foreground actual-foreground))
387 (ert-fail (format (concat "Expected face for level `%s' "
388 "%sto have foreground `%s'; "
389 "but it %s.")
390 level
391 (if negate "not " "") foreground
392 (if negate
393 "did" (format "was `%s'" actual-foreground)))))))
394
395 (defun context-coloring-test-assert-not-face (&rest arguments)
396 "Assert that LEVEL does not have a face with `:foreground'
397 FOREGROUND. Apply ARGUMENTS to
398 `context-coloring-test-assert-face', see that function."
399 (apply 'context-coloring-test-assert-face
400 (append arguments '(t))))
401
402 (defun context-coloring-test-assert-error (body error-message)
403 "Assert that BODY signals ERROR-MESSAGE."
404 (let ((error-signaled-p nil))
405 (condition-case err
406 (progn
407 (funcall body))
408 (error
409 (setq error-signaled-p t)
410 (when (not (string-equal (cadr err) error-message))
411 (ert-fail (format (concat "Expected the error \"%s\" to be thrown, "
412 "but instead it was \"%s\".")
413 error-message
414 (cadr err))))))
415 (when (not error-signaled-p)
416 (ert-fail "Expected an error to be thrown, but there wasn't."))))
417
418 (defun context-coloring-test-assert-trimmed (result expected)
419 (when (not (string-equal result expected))
420 (ert-fail "Expected string to be trimmed, but it wasn't.")))
421
422
423 ;;; The tests
424
425 (ert-deftest context-coloring-test-trim ()
426 (context-coloring-test-assert-trimmed (context-coloring-trim "") "")
427 (context-coloring-test-assert-trimmed (context-coloring-trim " ") "")
428 (context-coloring-test-assert-trimmed (context-coloring-trim "a") "a")
429 (context-coloring-test-assert-trimmed (context-coloring-trim " a") "a")
430 (context-coloring-test-assert-trimmed (context-coloring-trim "a ") "a")
431 (context-coloring-test-assert-trimmed (context-coloring-trim " a ") "a"))
432
433 (ert-deftest-async context-coloring-test-async-mode-startup (done)
434 (context-coloring-test-with-fixture-async
435 "./fixtures/empty"
436 (lambda (teardown)
437 (js-mode)
438 (add-hook
439 'context-coloring-colorize-hook
440 (lambda ()
441 ;; If this runs we are implicitly successful; this test only confirms
442 ;; that colorization occurs on mode startup.
443 (funcall teardown)
444 (funcall done)))
445 (context-coloring-mode))))
446
447 (define-derived-mode
448 context-coloring-change-detection-mode
449 fundamental-mode
450 "Testing"
451 "Prevent `context-coloring-test-change-detection' from
452 having any unintentional side-effects on mode support.")
453
454 ;; Simply cannot figure out how to trigger an idle timer; would much rather test
455 ;; that. But (current-idle-time) always returns nil in these tests.
456 (ert-deftest-async context-coloring-test-change-detection (done)
457 (context-coloring-define-dispatch
458 'idle-change
459 :modes '(context-coloring-change-detection-mode)
460 :executable "node"
461 :command "node test/binaries/noop")
462 (context-coloring-test-with-fixture-async
463 "./fixtures/empty"
464 (lambda (teardown)
465 (context-coloring-change-detection-mode)
466 (add-hook
467 'context-coloring-colorize-hook
468 (lambda ()
469 (setq context-coloring-colorize-hook nil)
470 (add-hook
471 'context-coloring-colorize-hook
472 (lambda ()
473 (funcall teardown)
474 (funcall done)))
475 (insert " ")
476 (set-window-buffer (selected-window) (current-buffer))
477 (context-coloring-maybe-colorize)))
478 (context-coloring-mode))))
479
480 (ert-deftest context-coloring-test-check-version ()
481 (when (not (context-coloring-check-version "2.1.3" "3.0.1"))
482 (ert-fail "Expected version 3.0.1 to satisfy 2.1.3, but it didn't."))
483 (when (context-coloring-check-version "3.0.1" "2.1.3")
484 (ert-fail "Expected version 2.1.3 not to satisfy 3.0.1, but it did.")))
485
486 (ert-deftest context-coloring-test-unsupported-mode ()
487 (context-coloring-test-with-fixture
488 "./fixtures/empty"
489 (context-coloring-mode)
490 (context-coloring-test-assert-message
491 "Context coloring is not available for this major mode"
492 "*Messages*")))
493
494 (define-derived-mode
495 context-coloring-test-define-dispatch-error-mode
496 fundamental-mode
497 "Testing"
498 "Prevent `context-coloring-test-define-dispatch-error' from
499 having any unintentional side-effects on mode support.")
500
501 (ert-deftest context-coloring-test-define-dispatch-error ()
502 (context-coloring-test-assert-error
503 (lambda ()
504 (context-coloring-define-dispatch
505 'define-dispatch-no-modes))
506 "No mode defined for dispatch")
507 (context-coloring-test-assert-error
508 (lambda ()
509 (context-coloring-define-dispatch
510 'define-dispatch-no-strategy
511 :modes '(context-coloring-test-define-dispatch-error-mode)))
512 "No colorizer, scopifier or command defined for dispatch"))
513
514 (define-derived-mode
515 context-coloring-test-define-dispatch-scopifier-mode
516 fundamental-mode
517 "Testing"
518 "Prevent `context-coloring-test-define-dispatch-scopifier' from
519 having any unintentional side-effects on mode support.")
520
521 (ert-deftest context-coloring-test-define-dispatch-scopifier ()
522 (context-coloring-define-dispatch
523 'define-dispatch-scopifier
524 :modes '(context-coloring-test-define-dispatch-scopifier-mode)
525 :scopifier (lambda () (vector)))
526 (with-temp-buffer
527 (context-coloring-test-define-dispatch-scopifier-mode)
528 (context-coloring-mode)
529 (context-coloring-colorize)))
530
531 (define-derived-mode
532 context-coloring-test-missing-executable-mode
533 fundamental-mode
534 "Testing"
535 "Prevent `context-coloring-test-define-dispatch-scopifier' from
536 having any unintentional side-effects on mode support.")
537
538 (ert-deftest context-coloring-test-missing-executable ()
539 (context-coloring-define-dispatch
540 'scopifier
541 :modes '(context-coloring-test-missing-executable-mode)
542 :command ""
543 :executable "__should_not_exist__")
544 (with-temp-buffer
545 (context-coloring-test-missing-executable-mode)
546 (context-coloring-mode)))
547
548 (define-derived-mode
549 context-coloring-test-unsupported-version-mode
550 fundamental-mode
551 "Testing"
552 "Prevent `context-coloring-test-unsupported-version' from
553 having any unintentional side-effects on mode support.")
554
555 (ert-deftest-async context-coloring-test-unsupported-version (done)
556 (context-coloring-define-dispatch
557 'outta-date
558 :modes '(context-coloring-test-unsupported-version-mode)
559 :executable "node"
560 :command "node test/binaries/outta-date"
561 :version "v2.1.3")
562 (context-coloring-test-with-fixture-async
563 "./fixtures/empty"
564 (lambda (teardown)
565 (context-coloring-test-unsupported-version-mode)
566 (add-hook
567 'context-coloring-check-scopifier-version-hook
568 (lambda ()
569 (unwind-protect
570 (progn
571 ;; Normally the executable would be something like "outta-date"
572 ;; rather than "node".
573 (context-coloring-test-assert-message
574 "Update to the minimum version of \"node\" (v2.1.3)"
575 "*Messages*"))
576 (funcall teardown))
577 (funcall done)))
578 (context-coloring-mode))))
579
580 (define-derived-mode
581 context-coloring-test-disable-mode-mode
582 fundamental-mode
583 "Testing"
584 "Prevent `context-coloring-test-disable-mode' from having any
585 unintentional side-effects on mode support.")
586
587 (ert-deftest-async context-coloring-test-disable-mode (done)
588 (let (torn-down)
589 (context-coloring-define-dispatch
590 'disable-mode
591 :modes '(context-coloring-test-disable-mode-mode)
592 :executable "node"
593 :command "node test/binaries/noop"
594 :teardown (lambda ()
595 (setq torn-down t)))
596 (context-coloring-test-with-fixture-async
597 "./fixtures/empty"
598 (lambda (teardown)
599 (unwind-protect
600 (progn
601 (context-coloring-test-disable-mode-mode)
602 (context-coloring-mode)
603 (context-coloring-mode -1)
604 (when (not torn-down)
605 (ert-fail "Expected teardown function to have been called, but it wasn't.")))
606 (funcall teardown))
607 (funcall done)))))
608
609 (defvar context-coloring-test-theme-index 0
610 "Unique index for unique theme names.")
611
612 (defun context-coloring-test-get-next-theme ()
613 "Return a unique symbol for a throwaway theme."
614 (prog1
615 (intern (format "context-coloring-test-theme-%s"
616 context-coloring-test-theme-index))
617 (setq context-coloring-test-theme-index
618 (+ context-coloring-test-theme-index 1))))
619
620 (defun context-coloring-test-assert-theme-originally-set-p
621 (settings &optional negate)
622 "Assert that `context-coloring-theme-originally-set-p' returns
623 t for a theme with SETTINGS, or the inverse if NEGATE is
624 non-nil."
625 (let ((theme (context-coloring-test-get-next-theme)))
626 (put theme 'theme-settings settings)
627 (when (funcall (if negate 'identity 'not)
628 (context-coloring-theme-originally-set-p theme))
629 (ert-fail (format (concat "Expected theme `%s' with settings `%s' "
630 "%sto be considered to have defined a level, "
631 "but it %s.")
632 theme settings
633 (if negate "not " "")
634 (if negate "was" "wasn't"))))))
635
636 (defun context-coloring-test-assert-not-theme-originally-set-p (&rest arguments)
637 "Assert that `context-coloring-theme-originally-set-p' does not
638 return t for a theme with SETTINGS. Apply ARGUMENTS to
639 `context-coloring-test-assert-theme-originally-set-p', see that
640 function."
641 (apply 'context-coloring-test-assert-theme-originally-set-p
642 (append arguments '(t))))
643
644 (ert-deftest context-coloring-test-theme-originally-set-p ()
645 (context-coloring-test-assert-theme-originally-set-p
646 '((theme-face context-coloring-level-0-face)))
647 (context-coloring-test-assert-theme-originally-set-p
648 '((theme-face face)
649 (theme-face context-coloring-level-0-face)))
650 (context-coloring-test-assert-theme-originally-set-p
651 '((theme-face context-coloring-level-0-face)
652 (theme-face face)))
653 (context-coloring-test-assert-not-theme-originally-set-p
654 '((theme-face face)))
655 )
656
657 (defun context-coloring-test-assert-theme-settings-highest-level
658 (settings expected-level)
659 "Assert that a theme with SETTINGS has the highest level
660 EXPECTED-LEVEL."
661 (let ((theme (context-coloring-test-get-next-theme)))
662 (put theme 'theme-settings settings)
663 (context-coloring-test-assert-theme-highest-level theme expected-level)))
664
665 (defun context-coloring-test-assert-theme-highest-level
666 (theme expected-level &optional negate)
667 "Assert that THEME has the highest level EXPECTED-LEVEL, or the
668 inverse if NEGATE is non-nil."
669 (let ((highest-level (context-coloring-theme-highest-level theme)))
670 (when (funcall (if negate 'identity 'not) (eq highest-level expected-level))
671 (ert-fail (format (concat "Expected theme with settings `%s' "
672 "%sto have a highest level of `%s', "
673 "but it %s.")
674 (get theme 'theme-settings)
675 (if negate "not " "") expected-level
676 (if negate "did" (format "was %s" highest-level)))))))
677
678 (defun context-coloring-test-assert-theme-not-highest-level (&rest arguments)
679 "Assert that THEME's highest level is not EXPECTED-LEVEL.
680 Apply ARGUMENTS to
681 `context-coloring-test-assert-theme-highest-level', see that
682 function."
683 (apply 'context-coloring-test-assert-theme-highest-level
684 (append arguments '(t))))
685
686 (ert-deftest context-coloring-test-theme-highest-level ()
687 (context-coloring-test-assert-theme-settings-highest-level
688 '((theme-face foo))
689 -1)
690 (context-coloring-test-assert-theme-settings-highest-level
691 '((theme-face context-coloring-level-0-face))
692 0)
693 (context-coloring-test-assert-theme-settings-highest-level
694 '((theme-face context-coloring-level-1-face))
695 1)
696 (context-coloring-test-assert-theme-settings-highest-level
697 '((theme-face context-coloring-level-1-face)
698 (theme-face context-coloring-level-0-face))
699 1)
700 (context-coloring-test-assert-theme-settings-highest-level
701 '((theme-face context-coloring-level-0-face)
702 (theme-face context-coloring-level-1-face))
703 1)
704 )
705
706 (defmacro context-coloring-test-deftest-define-theme (name &rest body)
707 "Define a test with name NAME and an automatically-generated
708 theme symbol available as a free variable `theme'. Side-effects
709 from enabling themes are reversed after BODY is executed and the
710 test completes."
711 (declare (indent defun))
712 (let ((deftest-name (intern
713 (format "context-coloring-test-define-theme-%s" name))))
714 `(ert-deftest ,deftest-name ()
715 (context-coloring-test-kill-buffer "*Warnings*")
716 (context-coloring-test-setup)
717 (let ((theme (context-coloring-test-get-next-theme)))
718 (unwind-protect
719 (progn
720 ,@body)
721 ;; Always cleanup.
722 (disable-theme theme)
723 (context-coloring-test-cleanup))))))
724
725 (defun context-coloring-test-deftheme (theme)
726 "Dynamically define theme THEME."
727 (eval (macroexpand `(deftheme ,theme))))
728
729 (context-coloring-test-deftest-define-theme additive
730 (context-coloring-test-deftheme theme)
731 (context-coloring-define-theme
732 theme
733 :colors '("#aaaaaa"
734 "#bbbbbb"))
735 (context-coloring-test-assert-no-message "*Warnings*")
736 (enable-theme theme)
737 (context-coloring-test-assert-no-message "*Warnings*")
738 (context-coloring-test-assert-face 0 "#aaaaaa")
739 (context-coloring-test-assert-face 1 "#bbbbbb"))
740
741 (defun context-coloring-test-assert-defined-warning (theme)
742 "Assert that a warning about colors already being defined for
743 theme THEME is signaled."
744 (context-coloring-test-assert-message
745 (format (concat "Warning (emacs): Context coloring colors for theme "
746 "`%s' are already defined")
747 theme)
748 "*Warnings*"))
749
750 (context-coloring-test-deftest-define-theme unintentional-override
751 (context-coloring-test-deftheme theme)
752 (custom-theme-set-faces
753 theme
754 '(context-coloring-level-0-face ((t (:foreground "#aaaaaa"))))
755 '(context-coloring-level-1-face ((t (:foreground "#bbbbbb")))))
756 (context-coloring-define-theme
757 theme
758 :colors '("#cccccc"
759 "#dddddd"))
760 (context-coloring-test-assert-defined-warning theme)
761 (context-coloring-test-kill-buffer "*Warnings*")
762 (enable-theme theme)
763 (context-coloring-test-assert-defined-warning theme)
764 (context-coloring-test-assert-face 0 "#cccccc")
765 (context-coloring-test-assert-face 1 "#dddddd"))
766
767 (context-coloring-test-deftest-define-theme intentional-override
768 (context-coloring-test-deftheme theme)
769 (custom-theme-set-faces
770 theme
771 '(context-coloring-level-0-face ((t (:foreground "#aaaaaa"))))
772 '(context-coloring-level-1-face ((t (:foreground "#bbbbbb")))))
773 (context-coloring-define-theme
774 theme
775 :override t
776 :colors '("#cccccc"
777 "#dddddd"))
778 (context-coloring-test-assert-no-message "*Warnings*")
779 (enable-theme theme)
780 (context-coloring-test-assert-no-message "*Warnings*")
781 (context-coloring-test-assert-face 0 "#cccccc")
782 (context-coloring-test-assert-face 1 "#dddddd"))
783
784 (context-coloring-test-deftest-define-theme pre-recede
785 (context-coloring-define-theme
786 theme
787 :recede t
788 :colors '("#aaaaaa"
789 "#bbbbbb"))
790 (context-coloring-test-deftheme theme)
791 (custom-theme-set-faces
792 theme
793 '(context-coloring-level-0-face ((t (:foreground "#cccccc"))))
794 '(context-coloring-level-1-face ((t (:foreground "#dddddd")))))
795 (enable-theme theme)
796 (context-coloring-test-assert-no-message "*Warnings*")
797 (context-coloring-test-assert-face 0 "#cccccc")
798 (context-coloring-test-assert-face 1 "#dddddd"))
799
800 (context-coloring-test-deftest-define-theme pre-recede-delayed-application
801 (context-coloring-define-theme
802 theme
803 :recede t
804 :colors '("#aaaaaa"
805 "#bbbbbb"))
806 (context-coloring-test-deftheme theme)
807 (enable-theme theme)
808 (context-coloring-test-assert-no-message "*Warnings*")
809 (context-coloring-test-assert-face 0 "#aaaaaa")
810 (context-coloring-test-assert-face 1 "#bbbbbb"))
811
812 (context-coloring-test-deftest-define-theme post-recede
813 (context-coloring-test-deftheme theme)
814 (custom-theme-set-faces
815 theme
816 '(context-coloring-level-0-face ((t (:foreground "#aaaaaa"))))
817 '(context-coloring-level-1-face ((t (:foreground "#bbbbbb")))))
818 (context-coloring-define-theme
819 theme
820 :recede t
821 :colors '("#cccccc"
822 "#dddddd"))
823 (context-coloring-test-assert-no-message "*Warnings*")
824 (context-coloring-test-assert-face 0 "#aaaaaa")
825 (context-coloring-test-assert-face 1 "#bbbbbb")
826 (enable-theme theme)
827 (context-coloring-test-assert-no-message "*Warnings*")
828 (context-coloring-test-assert-face 0 "#aaaaaa")
829 (context-coloring-test-assert-face 1 "#bbbbbb"))
830
831 (context-coloring-test-deftest-define-theme recede-not-defined
832 (context-coloring-test-deftheme theme)
833 (custom-theme-set-faces
834 theme
835 '(foo-face ((t (:foreground "#ffffff")))))
836 (context-coloring-define-theme
837 theme
838 :recede t
839 :colors '("#aaaaaa"
840 "#bbbbbb"))
841 (context-coloring-test-assert-no-message "*Warnings*")
842 (context-coloring-test-assert-face 0 "#aaaaaa")
843 (context-coloring-test-assert-face 1 "#bbbbbb")
844 (enable-theme theme)
845 (context-coloring-test-assert-no-message "*Warnings*")
846 (context-coloring-test-assert-face 0 "#aaaaaa")
847 (context-coloring-test-assert-face 1 "#bbbbbb"))
848
849 (context-coloring-test-deftest-define-theme unintentional-obstinance
850 (context-coloring-define-theme
851 theme
852 :colors '("#aaaaaa"
853 "#bbbbbb"))
854 (context-coloring-test-deftheme theme)
855 (custom-theme-set-faces
856 theme
857 '(context-coloring-level-0-face ((t (:foreground "#cccccc"))))
858 '(context-coloring-level-1-face ((t (:foreground "#dddddd")))))
859 (enable-theme theme)
860 (context-coloring-test-assert-defined-warning theme)
861 (context-coloring-test-assert-face 0 "#aaaaaa")
862 (context-coloring-test-assert-face 1 "#bbbbbb"))
863
864 (context-coloring-test-deftest-define-theme intentional-obstinance
865 (context-coloring-define-theme
866 theme
867 :override t
868 :colors '("#aaaaaa"
869 "#bbbbbb"))
870 (context-coloring-test-deftheme theme)
871 (custom-theme-set-faces
872 theme
873 '(context-coloring-level-0-face ((t (:foreground "#cccccc"))))
874 '(context-coloring-level-1-face ((t (:foreground "#dddddd")))))
875 (enable-theme theme)
876 (context-coloring-test-assert-no-message "*Warnings*")
877 (context-coloring-test-assert-face 0 "#aaaaaa")
878 (context-coloring-test-assert-face 1 "#bbbbbb"))
879
880 (defun context-coloring-test-assert-maximum-face (maximum &optional negate)
881 "Assert that `context-coloring-maximum-face' is MAXIMUM, or the
882 inverse if NEGATE is non-nil."
883 (when (funcall (if negate 'identity 'not)
884 (eq context-coloring-maximum-face maximum))
885 (ert-fail (format (concat "Expected `context-coloring-maximum-face' "
886 "%sto be `%s', "
887 "but it %s.")
888 (if negate "not " "") maximum
889 (if negate
890 "was"
891 (format "was `%s'" context-coloring-maximum-face))))))
892
893 (defun context-coloring-test-assert-not-maximum-face (&rest arguments)
894 "Assert that `context-coloring-maximum-face' is not MAXIMUM.
895 Apply ARGUMENTS to `context-coloring-test-assert-maximum-face',
896 see that function."
897 (apply 'context-coloring-test-assert-maximum-face
898 (append arguments '(t))))
899
900 (context-coloring-test-deftest-define-theme disable-cascade
901 (let ((maximum-face-value 9999))
902 (setq context-coloring-maximum-face maximum-face-value)
903 (context-coloring-test-deftheme theme)
904 (context-coloring-define-theme
905 theme
906 :colors '("#aaaaaa"
907 "#bbbbbb"))
908 (let ((second-theme (context-coloring-test-get-next-theme)))
909 (context-coloring-test-deftheme second-theme)
910 (context-coloring-define-theme
911 second-theme
912 :colors '("#cccccc"
913 "#dddddd"
914 "#eeeeee"))
915 (let ((third-theme (context-coloring-test-get-next-theme)))
916 (context-coloring-test-deftheme third-theme)
917 (context-coloring-define-theme
918 third-theme
919 :colors '("#111111"
920 "#222222"
921 "#333333"
922 "#444444"))
923 (enable-theme theme)
924 (enable-theme second-theme)
925 (enable-theme third-theme)
926 (disable-theme third-theme)
927 (context-coloring-test-assert-face 0 "#cccccc")
928 (context-coloring-test-assert-face 1 "#dddddd")
929 (context-coloring-test-assert-face 2 "#eeeeee")
930 (context-coloring-test-assert-maximum-face 2))
931 (disable-theme second-theme)
932 (context-coloring-test-assert-face 0 "#aaaaaa")
933 (context-coloring-test-assert-face 1 "#bbbbbb")
934 (context-coloring-test-assert-maximum-face 1))
935 (disable-theme theme)
936 (context-coloring-test-assert-not-face 0 "#aaaaaa")
937 (context-coloring-test-assert-not-face 1 "#bbbbbb")
938 (context-coloring-test-assert-maximum-face
939 maximum-face-value)))
940
941 (defun context-coloring-test-js-function-scopes ()
942 "Test fixtures/functions-scopes.js."
943 (context-coloring-test-assert-region-level 1 9 0)
944 (context-coloring-test-assert-region-level 9 23 1)
945 (context-coloring-test-assert-region-level 23 25 0)
946 (context-coloring-test-assert-region-level 25 34 1)
947 (context-coloring-test-assert-region-level 34 35 0)
948 (context-coloring-test-assert-region-level 35 52 1)
949 (context-coloring-test-assert-region-level 52 66 2)
950 (context-coloring-test-assert-region-level 66 72 1)
951 (context-coloring-test-assert-region-level 72 81 2)
952 (context-coloring-test-assert-region-level 81 82 1)
953 (context-coloring-test-assert-region-level 82 87 2)
954 (context-coloring-test-assert-region-level 87 89 1))
955
956 (context-coloring-test-deftest-js-mode function-scopes)
957 (context-coloring-test-deftest-js2-mode function-scopes)
958
959 (defun context-coloring-test-js-global ()
960 "Test fixtures/global.js."
961 (context-coloring-test-assert-region-level 20 28 1)
962 (context-coloring-test-assert-region-level 28 35 0)
963 (context-coloring-test-assert-region-level 35 41 1))
964
965 (context-coloring-test-deftest-js-mode global)
966 (context-coloring-test-deftest-js2-mode global)
967
968 (defun context-coloring-test-js-block-scopes ()
969 "Test fixtures/block-scopes.js."
970 (context-coloring-test-assert-region-level 20 64 1)
971 (setq context-coloring-js-block-scopes t)
972 (context-coloring-colorize)
973 (context-coloring-test-assert-region-level 20 27 1)
974 (context-coloring-test-assert-region-level 27 41 2)
975 (context-coloring-test-assert-region-level 41 42 1)
976 (context-coloring-test-assert-region-level 42 64 2))
977
978 (context-coloring-test-deftest-js2-mode block-scopes)
979
980 (defun context-coloring-test-js-catch ()
981 "Test fixtures/js-catch.js."
982 (context-coloring-test-assert-region-level 20 27 1)
983 (context-coloring-test-assert-region-level 27 51 2)
984 (context-coloring-test-assert-region-level 51 52 1)
985 (context-coloring-test-assert-region-level 52 73 2)
986 (context-coloring-test-assert-region-level 73 101 3)
987 (context-coloring-test-assert-region-level 101 102 1)
988 (context-coloring-test-assert-region-level 102 117 3)
989 (context-coloring-test-assert-region-level 117 123 2))
990
991 (context-coloring-test-deftest-js-mode catch)
992 (context-coloring-test-deftest-js2-mode catch)
993
994 (defun context-coloring-test-js-key-names ()
995 "Test fixtures/key-names.js."
996 (context-coloring-test-assert-region-level 20 63 1))
997
998 (context-coloring-test-deftest-js-mode key-names)
999 (context-coloring-test-deftest-js2-mode key-names)
1000
1001 (defun context-coloring-test-js-property-lookup ()
1002 "Test fixtures/property-lookup.js."
1003 (context-coloring-test-assert-region-level 20 26 0)
1004 (context-coloring-test-assert-region-level 26 38 1)
1005 (context-coloring-test-assert-region-level 38 44 0)
1006 (context-coloring-test-assert-region-level 44 52 1)
1007 (context-coloring-test-assert-region-level 57 63 0)
1008 (context-coloring-test-assert-region-level 63 74 1))
1009
1010 (context-coloring-test-deftest-js-mode property-lookup)
1011 (context-coloring-test-deftest-js2-mode property-lookup)
1012
1013 (defun context-coloring-test-js-key-values ()
1014 "Test fixtures/key-values.js."
1015 (context-coloring-test-assert-region-level 78 79 1))
1016
1017 (context-coloring-test-deftest-js-mode key-values)
1018 (context-coloring-test-deftest-js2-mode key-values)
1019
1020 (defun context-coloring-test-js-syntactic-comments-and-strings ()
1021 "Test comments and strings."
1022 (context-coloring-test-assert-region-level 1 8 0)
1023 (context-coloring-test-assert-region-comment-delimiter 9 12)
1024 (context-coloring-test-assert-region-comment 12 16)
1025 (context-coloring-test-assert-region-comment-delimiter 17 20)
1026 (context-coloring-test-assert-region-comment 20 27)
1027 (context-coloring-test-assert-region-string 28 40)
1028 (context-coloring-test-assert-region-level 40 41 0))
1029
1030 (defun context-coloring-test-js-syntactic-comments-and-strings-setup ()
1031 (setq context-coloring-syntactic-comments t)
1032 (setq context-coloring-syntactic-strings t))
1033
1034 (context-coloring-test-deftest-js-mode syntactic-comments-and-strings
1035 :fixture-name comments-and-strings)
1036 (context-coloring-test-deftest-js2-mode syntactic-comments-and-strings
1037 :fixture-name comments-and-strings)
1038
1039 (defalias 'context-coloring-test-js-comments-and-strings
1040 'context-coloring-test-js-syntactic-comments-and-strings
1041 "Test comments and strings. Deprecated.")
1042
1043 (defun context-coloring-test-js-comments-and-strings-setup ()
1044 "Setup comments and strings. Deprecated."
1045 (setq context-coloring-comments-and-strings t))
1046
1047 (context-coloring-test-deftest-js-mode comments-and-strings)
1048 (context-coloring-test-deftest-js2-mode comments-and-strings)
1049
1050 (defun context-coloring-test-js-syntactic-comments ()
1051 "Test syntactic comments."
1052 (context-coloring-test-assert-region-level 1 8 0)
1053 (context-coloring-test-assert-region-comment-delimiter 9 12)
1054 (context-coloring-test-assert-region-comment 12 16)
1055 (context-coloring-test-assert-region-comment-delimiter 17 20)
1056 (context-coloring-test-assert-region-comment 20 27)
1057 (context-coloring-test-assert-region-level 28 41 0))
1058
1059 (defun context-coloring-test-js-syntactic-comments-setup ()
1060 "Setup syntactic comments."
1061 (setq context-coloring-syntactic-comments t))
1062
1063 (context-coloring-test-deftest-js-mode syntactic-comments
1064 :fixture-name comments-and-strings)
1065 (context-coloring-test-deftest-js2-mode syntactic-comments
1066 :fixture-name comments-and-strings)
1067
1068 (defun context-coloring-test-js-syntactic-strings ()
1069 "Test syntactic strings."
1070 (context-coloring-test-assert-region-level 1 28 0)
1071 (context-coloring-test-assert-region-string 28 40)
1072 (context-coloring-test-assert-region-level 40 41 0))
1073
1074 (defun context-coloring-test-js-syntactic-strings-setup ()
1075 "Setup syntactic strings."
1076 (setq context-coloring-syntactic-strings t))
1077
1078 (context-coloring-test-deftest-js-mode syntactic-strings
1079 :fixture-name comments-and-strings)
1080 (context-coloring-test-deftest-js2-mode syntactic-strings
1081 :fixture-name comments-and-strings)
1082
1083 ;; As long as `add-text-properties' doesn't signal an error, this test passes.
1084 (defun context-coloring-test-js-unterminated-comment ()
1085 "Test unterminated multiline comments.")
1086
1087 (context-coloring-test-deftest-js2-mode unterminated-comment)
1088
1089 (context-coloring-test-deftest-emacs-lisp-mode defun
1090 (lambda ()
1091 (context-coloring-test-assert-coloring "
1092 111111 000 1111 111 111111111 1111
1093 11 111 111 111 000011
1094
1095 0000 0 0 00
1096
1097 111111 01
1098 111111 111")))
1099
1100 (context-coloring-test-deftest-emacs-lisp-mode lambda
1101 (lambda ()
1102 (context-coloring-test-assert-coloring "
1103 00000000 1111111 1111
1104 11111111 11 2222222 2222
1105 222 22 12 2221 111 0 00")))
1106
1107 (context-coloring-test-deftest-emacs-lisp-mode quote
1108 (lambda ()
1109 (context-coloring-test-assert-coloring "
1110 (xxxxx x (x)
1111 (xx (xx x 111
1112 111111 1 111 111
1113 111111 1 1111111111 11 111 1 111 1 00001 10000 11 00001 1 100001111")))
1114
1115 (context-coloring-test-deftest-emacs-lisp-mode comment
1116 (lambda ()
1117 ;; Just check that the comment isn't parsed syntactically.
1118 (context-coloring-test-assert-coloring "
1119 (xxxxx x ()
1120 (xx (x xxxxx-xxxx xx) ;;;;;;;;;;
1121 11 00000-0000 11))) ;;;;;;;;;;"))
1122 :setup (lambda ()
1123 (setq context-coloring-syntactic-comments t)))
1124
1125 (context-coloring-test-deftest-emacs-lisp-mode string
1126 (lambda ()
1127 (context-coloring-test-assert-coloring "
1128 (xxxxx x (x)
1129 (xxxxxx x x sss 1 0 sssss 0 1 sssssss11"))
1130 :setup (lambda ()
1131 (setq context-coloring-syntactic-strings t)))
1132
1133 (context-coloring-test-deftest-emacs-lisp-mode unbindable
1134 (lambda ()
1135 (context-coloring-test-assert-coloring "
1136 (xxxxx x ()
1137 (x x 1 11 11 111 11 1 111))")))
1138
1139 (context-coloring-test-deftest-emacs-lisp-mode let
1140 (lambda ()
1141 (context-coloring-test-assert-coloring "
1142 1111 11
1143 11 01
1144 11 000011
1145 1111 1 1 1 000011")))
1146
1147 (context-coloring-test-deftest-emacs-lisp-mode let*
1148 (lambda ()
1149 (context-coloring-test-assert-coloring "
1150 11111 11
1151 11 11
1152 11 000011
1153 1111 1 1 1 0 0 00001
1154 22222 22
1155 22 12
1156 22 00002
1157 22 02
1158 22 222
1159 2222 1 1 2 2 2 000022
1160 1111 1 1 1 0 0 000011")))
1161
1162 (provide 'context-coloring-test)
1163
1164 ;;; context-coloring-test.el ends here