X-Git-Url: https://code.delx.au/gnu-emacs-elpa/blobdiff_plain/af43c43b33726e9212f1050f37ab550f5a6abee3..b2a3e91287b48e727c64e697b7508937af4e622e:/packages/context-coloring/test/context-coloring-test.el diff --git a/packages/context-coloring/test/context-coloring-test.el b/packages/context-coloring/test/context-coloring-test.el index 88a715807..702058924 100644 --- a/packages/context-coloring/test/context-coloring-test.el +++ b/packages/context-coloring/test/context-coloring-test.el @@ -1,4 +1,4 @@ -;;; test/context-coloring-test.el --- Tests for context coloring. -*- lexical-binding: t; -*- +;;; context-coloring-test.el --- Tests for context coloring -*- lexical-binding: t; -*- ;; Copyright (C) 2014-2015 Free Software Foundation, Inc. @@ -19,16 +19,16 @@ ;;; Commentary: -;; Tests for context-coloring. +;; Tests for context coloring. -;; Tests for both synchronous (elisp) and asynchronous (shell command) coloring -;; are available. Basic plugin functionality is also tested. - -;; To run, execute `make test' from the project root. +;; Use with `make test'. ;;; Code: +(require 'cl-lib) +(require 'context-coloring) (require 'ert-async) +(require 'js2-mode) ;;; Test running utilities @@ -38,190 +38,228 @@ "This file's directory.") (defun context-coloring-test-read-file (path) - "Read a file's contents from PATH into a string." + "Return the file's contents from PATH as a string." (with-temp-buffer (insert-file-contents (expand-file-name path context-coloring-test-path)) (buffer-string))) -(defun context-coloring-test-setup () - "Prepare before all tests." - (setq context-coloring-comments-and-strings nil)) - -(defun context-coloring-test-cleanup () - "Cleanup after all tests." - (setq context-coloring-comments-and-strings t) - (setq context-coloring-after-colorize-hook nil) - (setq context-coloring-js-block-scopes nil)) - (defmacro context-coloring-test-with-fixture (fixture &rest body) "With the relative FIXTURE, evaluate BODY in a temporary buffer." `(with-temp-buffer - (unwind-protect - (progn - (context-coloring-test-setup) - (insert (context-coloring-test-read-file ,fixture)) - ,@body) - (context-coloring-test-cleanup)))) + (progn + (insert (context-coloring-test-read-file ,fixture)) + ,@body))) (defun context-coloring-test-with-temp-buffer-async (callback) "Create a temporary buffer, and evaluate CALLBACK there. A teardown callback is passed to CALLBACK for it to invoke when it is done." - (let ((temp-buffer (make-symbol "temp-buffer"))) - (let ((previous-buffer (current-buffer)) - (temp-buffer (generate-new-buffer " *temp*"))) - (set-buffer temp-buffer) - (funcall - callback - (lambda () - (and (buffer-name temp-buffer) - (kill-buffer temp-buffer)) - (set-buffer previous-buffer)))))) - -(defun context-coloring-test-with-fixture-async - (fixture callback &optional setup) + (let ((previous-buffer (current-buffer)) + (temp-buffer (generate-new-buffer " *temp*"))) + (set-buffer temp-buffer) + (funcall + callback + (lambda () + (and (buffer-name temp-buffer) + (kill-buffer temp-buffer)) + (set-buffer previous-buffer))))) + +(defun context-coloring-test-with-fixture-async (fixture callback) "With the relative FIXTURE, evaluate CALLBACK in a temporary buffer. A teardown callback is passed to CALLBACK for it to -invoke when it is done. An optional SETUP callback can run -arbitrary code before the mode is invoked." +invoke when it is done." (context-coloring-test-with-temp-buffer-async (lambda (done-with-temp-buffer) - (context-coloring-test-setup) - (when setup (funcall setup)) (insert (context-coloring-test-read-file fixture)) (funcall callback (lambda () - (context-coloring-test-cleanup) (funcall done-with-temp-buffer)))))) ;;; Test defining utilities -(defun context-coloring-test-js-mode (fixture callback &optional setup) - "Use FIXTURE as the subject matter for test logic in CALLBACK. -Optionally, provide setup code to run before the mode is -instantiated in SETUP." - (context-coloring-test-with-fixture-async - fixture - (lambda (done-with-test) - (js-mode) - (context-coloring-mode) - (context-coloring-colorize - (lambda () - (funcall callback done-with-test)))) - setup)) - -(defmacro context-coloring-test-js2-mode (fixture &rest body) - "Use FIXTURE as the subject matter for test logic in BODY." - `(context-coloring-test-with-fixture - ,fixture - (require 'js2-mode) - (setq js2-mode-show-parse-errors nil) - (setq js2-mode-show-strict-warnings nil) - (js2-mode) - (context-coloring-mode) - ,@body)) - -(defmacro context-coloring-test-deftest-js-mode (name) - "Define an asynchronous test for `js-mode' with the name NAME -in the typical format." - (let ((test-name (intern (format "context-coloring-test-js-mode-%s" name))) - (fixture (format "./fixtures/%s.js" name)) - (function-name (intern-soft - (format "context-coloring-test-js-%s" name)))) - `(ert-deftest-async ,test-name (done) - (context-coloring-test-js-mode - ,fixture - (lambda (teardown) - (unwind-protect - (,function-name) - (funcall teardown)) - (funcall done)))))) - -(defmacro context-coloring-test-deftest-js2-mode (name) - "Define a test for `js2-mode' with the name NAME in the typical -format." - (let ((test-name (intern (format "context-coloring-test-js2-mode-%s" name))) - (fixture (format "./fixtures/%s.js" name)) - (function-name (intern-soft - (format "context-coloring-test-js-%s" name)))) - `(ert-deftest ,test-name () - (context-coloring-test-js2-mode - ,fixture - (,function-name))))) +(cl-defmacro context-coloring-test-define-deftest (name + &key mode + &key extension + &key no-fixture + &key async + &key post-colorization + &key enable-context-coloring-mode + &key get-args + &key before-each + &key after-each) + "Define a deftest defmacro for tests prefixed with NAME. MODE +is called to set up tests' environments. EXTENSION denotes the +suffix for tests' fixture files. If NO-FIXTURE is non-nil, don't +use a fixture. If ASYNC is non-nil, pass a callback to the +defined tests' bodies for them to call when they are done. If +POST-COLORIZATION is non-nil, the tests run after +`context-coloring-colorize' finishes asynchronously. If +ENABLE-CONTEXT-COLORING-MODE is non-nil, `context-coloring-mode' +is activated before tests. GET-ARGS provides arguments to apply +to BEFORE-EACH, AFTER-EACH, and each tests' body, before and +after functions. Functions BEFORE-EACH and AFTER-EACH run before +the major mode is activated before each test, and after each +test, even if an error is signaled." + (declare (indent defun)) + (let ((macro-name (intern (format "context-coloring-test-deftest%s" + (cond + ;; No name means no dash. + ((eq name nil) "") + (t (format "-%s" name))))))) + `(cl-defmacro ,macro-name (name + body + &key fixture + &key before + &key after) + ,(format "Define a test for `%s' suffixed with NAME. + +Function BODY makes assertions. +%s + +Functions BEFORE and AFTER run before and after the test, even if +an error is signaled. + +BODY is run after `context-coloring-mode' is activated, or after +initial colorization if colorization should occur." + (cadr mode) + (cond + (no-fixture " +There is no fixture, unless FIXTURE is specified.") + (t + (format " +The default fixture has a filename matching NAME (plus the +filetype extension, \"%s\"), unless FIXTURE is specified to +override it." + extension)))) + (declare (indent defun)) + ;; Commas in nested backquotes are not evaluated. Binding the variables + ;; here is probably the cleanest workaround. + (let ((mode ,mode) + (get-args ',(cond + (get-args get-args) + (t '(lambda () (list))))) + (args (make-symbol "args")) + (before-each ',before-each) + (after-each ',after-each) + (test-name (intern (format ,(format "%s-%%s" + (cond + (name) + (t "sync"))) name))) + (fixture (cond + (fixture (format "./fixtures/%s" fixture)) + (,no-fixture "./fixtures/empty") + (t (format ,(format "./fixtures/%%s.%s" extension) name))))) + ,@(cond + ((or async post-colorization) + `((let ((post-colorization ,post-colorization)) + `(ert-deftest-async ,test-name (done) + (let ((,args (funcall ,get-args))) + (context-coloring-test-with-fixture-async + ,fixture + (lambda (done-with-fixture) + (when ,before-each (apply ,before-each ,args)) + (,mode) + (when ,before (apply ,before ,args)) + (cond + (,post-colorization + (context-coloring-colorize + (lambda () + (unwind-protect + (progn + (apply ,body ,args)) + (when ,after (apply ,after ,args)) + (when ,after-each (apply ,after-each ,args)) + (funcall done-with-fixture)) + (funcall done)))) + (t + ;; Leave error handling up to the user. + (apply ,body (append + (list (lambda () + (when ,after (apply ,after ,args)) + (when ,after-each (apply ,after-each ,args)) + (funcall done-with-fixture) + (funcall done))) + ,args))))))))))) + (t + `((let ((enable-context-coloring-mode ,enable-context-coloring-mode)) + `(ert-deftest ,test-name () + (let ((,args (funcall ,get-args))) + (context-coloring-test-with-fixture + ,fixture + (when ,before-each (apply ,before-each ,args)) + (,mode) + (when ,before (apply ,before ,args)) + (when ,enable-context-coloring-mode (context-coloring-mode)) + (unwind-protect + (progn + (apply ,body ,args)) + (when ,after (apply ,after ,args)) + (when ,after-each (apply ,after-each ,args)))))))))))))) + +(context-coloring-test-define-deftest nil + :mode #'fundamental-mode + :no-fixture t) + +(context-coloring-test-define-deftest async + :mode #'fundamental-mode + :no-fixture t + :async t) + +(context-coloring-test-define-deftest js + :mode #'js-mode + :extension "js" + :post-colorization t) + +(context-coloring-test-define-deftest js2 + :mode #'js2-mode + :extension "js" + :enable-context-coloring-mode t + :before-each (lambda () + (setq js2-mode-show-parse-errors nil) + (setq js2-mode-show-strict-warnings nil))) + +(defmacro context-coloring-test-deftest-js-js2 (&rest args) + "Simultaneously define the same test for js and js2 (with +ARGS)." + (declare (indent defun)) + `(progn + (context-coloring-test-deftest-js ,@args) + (context-coloring-test-deftest-js2 ,@args))) + +(context-coloring-test-define-deftest emacs-lisp + :mode #'emacs-lisp-mode + :extension "el" + :enable-context-coloring-mode t) + +(context-coloring-test-define-deftest define-theme + :mode #'fundamental-mode + :no-fixture t + :get-args (lambda () + (list (context-coloring-test-get-next-theme))) + :after-each (lambda (theme) + (setq context-coloring-maximum-face 7) + (setq context-coloring-original-maximum-face + context-coloring-maximum-face) + (disable-theme theme) + (context-coloring-test-kill-buffer "*Warnings*"))) ;;; Assertion functions -(defmacro context-coloring-test-assert-region (&rest body) - "Assert something about the face of points in a region. -Provides the free variables `i', `length', `point', `face' and -`actual-level' to the code in BODY." - `(let ((i 0) - (length (- end start))) - (while (< i length) - (let* ((point (+ i start)) - (face (get-text-property point 'face)) - actual-level) - ,@body) - (setq i (+ i 1))))) - -(defun context-coloring-test-assert-region-level (start end level) - "Assert that all points in the range [START, END) are of level -LEVEL." - (context-coloring-test-assert-region - (when (not (when face - (let* ((face-string (symbol-name face)) - (matches (string-match - context-coloring-level-face-regexp - face-string))) - (when matches - (setq actual-level (string-to-number - (substring face-string - (match-beginning 1) - (match-end 1)))) - (= level actual-level))))) - (ert-fail (format (concat "Expected level in region [%s, %s), " - "which is \"%s\", to be %s; " - "but at point %s, it was %s") - start end - (buffer-substring-no-properties start end) level - point actual-level))))) - -(defun context-coloring-test-assert-region-face (start end expected-face) - "Assert that all points in the range [START, END) have the face -EXPECTED-FACE." - (context-coloring-test-assert-region - (when (not (eq face expected-face)) - (ert-fail (format (concat "Expected face in region [%s, %s), " - "which is \"%s\", to be %s; " - "but at point %s, it was %s") - start end - (buffer-substring-no-properties start end) expected-face - point face))))) - -(defun context-coloring-test-assert-region-comment-delimiter (start end) - "Assert that all points in the range [START, END) have -`font-lock-comment-delimiter-face'." - (context-coloring-test-assert-region-face - start end 'font-lock-comment-delimiter-face)) - -(defun context-coloring-test-assert-region-comment (start end) - "Assert that all points in the range [START, END) have -`font-lock-comment-face'." - (context-coloring-test-assert-region-face - start end 'font-lock-comment-face)) - -(defun context-coloring-test-assert-region-string (start end) - "Assert that all points in the range [START, END) have -`font-lock-string-face'." - (context-coloring-test-assert-region-face - start end 'font-lock-string-face)) +(defun context-coloring-test-get-last-message () + "Get the last message in the current messages bufffer." + (let ((messages (split-string + (buffer-substring-no-properties + (point-min) + (point-max)) + "\n"))) + (car (nthcdr (- (length messages) 2) messages)))) (defun context-coloring-test-assert-message (expected buffer) - "Assert that message EXPECTED exists in BUFFER." + "Assert that message EXPECTED is at the end of BUFFER." (when (null (get-buffer buffer)) (ert-fail (format @@ -230,20 +268,28 @@ EXPECTED-FACE." "but the buffer did not have any messages.") buffer expected))) (with-current-buffer buffer - (let ((messages (split-string - (buffer-substring-no-properties - (point-min) - (point-max)) - "\n"))) - (let ((message (car (nthcdr (- (length messages) 2) messages)))) - (when (not (equal message expected)) + (let ((message (context-coloring-test-get-last-message))) + (when (not (equal message expected)) + (ert-fail + (format + (concat + "Expected buffer `%s' to have message \"%s\", " + "but instead it was \"%s\"") + buffer expected + message)))))) + +(defun context-coloring-test-assert-not-message (expected buffer) + "Assert that message EXPECTED is not at the end of BUFFER." + (when (get-buffer buffer) + (with-current-buffer buffer + (let ((message (context-coloring-test-get-last-message))) + (when (equal message expected) (ert-fail (format (concat - "Expected buffer `%s' to have message \"%s\", " - "but instead it was \"%s\"") - buffer expected - message))))))) + "Expected buffer `%s' not to have message \"%s\", " + "but it did") + buffer expected))))))) (defun context-coloring-test-assert-no-message (buffer) "Assert that BUFFER has no message." @@ -254,9 +300,196 @@ EXPECTED-FACE." (with-current-buffer buffer (buffer-string)))))) -(defun context-coloring-test-kill-buffer (buffer) - "Kill BUFFER if it exists." - (when (get-buffer buffer) (kill-buffer buffer))) +(defun context-coloring-test-assert-error (body error-message) + "Assert that BODY signals ERROR-MESSAGE." + (let ((error-signaled-p nil)) + (condition-case err + (progn + (funcall body)) + (error + (setq error-signaled-p t) + (when (not (string-equal (cadr err) error-message)) + (ert-fail (format (concat "Expected the error \"%s\" to be thrown, " + "but instead it was \"%s\".") + error-message + (cadr err)))))) + (when (not error-signaled-p) + (ert-fail "Expected an error to be thrown, but there wasn't.")))) + + +;;; Miscellaneous tests + +(defun context-coloring-test-assert-trimmed (result expected) + "Assert that RESULT is trimmed like EXPECTED." + (when (not (string-equal result expected)) + (ert-fail "Expected string to be trimmed, but it wasn't."))) + +(context-coloring-test-deftest trim + (lambda () + (context-coloring-test-assert-trimmed (context-coloring-trim "") "") + (context-coloring-test-assert-trimmed (context-coloring-trim " ") "") + (context-coloring-test-assert-trimmed (context-coloring-trim "a") "a") + (context-coloring-test-assert-trimmed (context-coloring-trim " a") "a") + (context-coloring-test-assert-trimmed (context-coloring-trim "a ") "a") + (context-coloring-test-assert-trimmed (context-coloring-trim " a ") "a"))) + +(context-coloring-test-deftest-async mode-startup + (lambda (done) + (js-mode) + (add-hook + 'context-coloring-colorize-hook + (lambda () + ;; If this runs we are implicitly successful; this test only confirms + ;; that colorization occurs on mode startup. + (funcall done))) + (context-coloring-mode)) + :after (lambda () + ;; TODO: This won't run if there is a timeout. Will probably have to + ;; roll our own `ert-deftest-async'. + (setq context-coloring-colorize-hook nil))) + +(defmacro context-coloring-test-define-derived-mode (name) + "Define a derived mode exclusively for any test with NAME." + (let ((name (intern (format "context-coloring-test-%s-mode" name)))) + `(define-derived-mode ,name fundamental-mode "Testing"))) + +(context-coloring-test-define-derived-mode change-detection) + +;; Simply cannot figure out how to trigger an idle timer; would much rather test +;; that. But (current-idle-time) always returns nil in these tests. +(context-coloring-test-deftest-async change-detection + (lambda (done) + (context-coloring-define-dispatch + 'idle-change + :modes '(context-coloring-test-change-detection-mode) + :executable "node" + :command "node test/binaries/noop") + (context-coloring-test-change-detection-mode) + (add-hook + 'context-coloring-colorize-hook + (lambda () + (setq context-coloring-colorize-hook nil) + (add-hook + 'context-coloring-colorize-hook + (lambda () + (funcall done))) + (insert " ") + (set-window-buffer (selected-window) (current-buffer)) + (context-coloring-maybe-colorize-with-buffer (current-buffer)))) + (context-coloring-mode)) + :after (lambda () + (setq context-coloring-colorize-hook nil))) + +(context-coloring-test-deftest check-version + (lambda () + (when (not (context-coloring-check-version "2.1.3" "3.0.1")) + (ert-fail "Expected version 3.0.1 to satisfy 2.1.3, but it didn't.")) + (when (context-coloring-check-version "3.0.1" "2.1.3") + (ert-fail "Expected version 2.1.3 not to satisfy 3.0.1, but it did.")))) + +(context-coloring-test-deftest unsupported-mode + (lambda () + (context-coloring-mode) + (context-coloring-test-assert-message + "Context coloring is not available for this major mode" + "*Messages*"))) + +(context-coloring-test-deftest derived-mode + (lambda () + (lisp-interaction-mode) + (context-coloring-mode) + (context-coloring-test-assert-not-message + "Context coloring is not available for this major mode" + "*Messages*"))) + +(context-coloring-test-define-derived-mode define-dispatch-error) + +(context-coloring-test-deftest define-dispatch-error + (lambda () + (context-coloring-test-assert-error + (lambda () + (context-coloring-define-dispatch + 'define-dispatch-no-modes)) + "No mode defined for dispatch") + (context-coloring-test-assert-error + (lambda () + (context-coloring-define-dispatch + 'define-dispatch-no-strategy + :modes '(context-coloring-test-define-dispatch-error-mode))) + "No colorizer or command defined for dispatch"))) + +(context-coloring-test-define-derived-mode missing-executable) + +(context-coloring-test-deftest missing-executable + (lambda () + (context-coloring-define-dispatch + 'scopifier + :modes '(context-coloring-test-missing-executable-mode) + :command "" + :executable "__should_not_exist__") + (context-coloring-test-missing-executable-mode) + (context-coloring-mode))) + +(context-coloring-test-define-derived-mode unsupported-version) + +(context-coloring-test-deftest-async unsupported-version + (lambda (done) + (context-coloring-define-dispatch + 'outta-date + :modes '(context-coloring-test-unsupported-version-mode) + :executable "node" + :command "node test/binaries/outta-date" + :version "v2.1.3") + (context-coloring-test-unsupported-version-mode) + (add-hook + 'context-coloring-check-scopifier-version-hook + (lambda () + (unwind-protect + (progn + ;; Normally the executable would be something like "outta-date" + ;; rather than "node". + (context-coloring-test-assert-message + "Update to the minimum version of \"node\" (v2.1.3)" + "*Messages*")) + (funcall done)))) + (context-coloring-mode)) + :after (lambda () + (setq context-coloring-check-scopifier-version-hook nil))) + +(context-coloring-test-define-derived-mode disable-mode) + +(context-coloring-test-deftest-async disable-mode + (lambda (done) + (let (torn-down) + (context-coloring-define-dispatch + 'disable-mode + :modes '(context-coloring-test-disable-mode-mode) + :executable "node" + :command "node test/binaries/noop" + :teardown (lambda () + (setq torn-down t))) + (unwind-protect + (progn + (context-coloring-test-disable-mode-mode) + (context-coloring-mode) + (context-coloring-mode -1) + (when (not torn-down) + (ert-fail "Expected teardown function to have been called, but it wasn't."))) + (funcall done))))) + + +;;; Theme tests + +(defvar context-coloring-test-theme-index 0 + "Unique index for unique theme names.") + +(defun context-coloring-test-get-next-theme () + "Return a unique symbol for a throwaway theme." + (prog1 + (intern (format "context-coloring-test-theme-%s" + context-coloring-test-theme-index)) + (setq context-coloring-test-theme-index + (+ context-coloring-test-theme-index 1)))) (defun context-coloring-test-assert-face (level foreground &optional negate) "Assert that a face for LEVEL exists and that its `:foreground' @@ -269,52 +502,31 @@ is FOREGROUND, or the inverse if NEGATE is non-nil." "but it didn't") level))) (setq actual-foreground (face-attribute face :foreground)) - (when (funcall (if negate 'identity 'not) + (when (funcall (if negate #'identity #'not) (string-equal foreground actual-foreground)) (ert-fail (format (concat "Expected face for level `%s' " "%sto have foreground `%s'; " "but it %s.") level (if negate "not " "") foreground - (if negate "did" (format "was `%s'" actual-foreground))))))) + (if negate + "did" (format "was `%s'" actual-foreground))))))) (defun context-coloring-test-assert-not-face (&rest arguments) "Assert that LEVEL does not have a face with `:foreground' FOREGROUND. Apply ARGUMENTS to `context-coloring-test-assert-face', see that function." - (apply 'context-coloring-test-assert-face + (apply #'context-coloring-test-assert-face (append arguments '(t)))) - -;;; The tests - -(ert-deftest context-coloring-test-unsupported-mode () - (context-coloring-test-with-fixture - "./fixtures/function-scopes.js" - (context-coloring-mode) - (context-coloring-test-assert-message - "Context coloring is not available for this major mode" - "*Messages*"))) - -(defvar context-coloring-test-theme-index 0 - "Unique index for unique theme names.") - -(defun context-coloring-test-get-next-theme () - "Return a unique symbol for a throwaway theme." - (prog1 - (intern (format "context-coloring-test-theme-%s" - context-coloring-test-theme-index)) - (setq context-coloring-test-theme-index - (+ context-coloring-test-theme-index 1)))) - (defun context-coloring-test-assert-theme-originally-set-p (settings &optional negate) - "Assert that `context-coloring-theme-originally-set-p' returns -t for a theme with SETTINGS, or the inverse if NEGATE is + "Assert that `context-coloring-theme-originally-set-p' will +return t for a theme with SETTINGS, or the inverse if NEGATE is non-nil." (let ((theme (context-coloring-test-get-next-theme))) (put theme 'theme-settings settings) - (when (funcall (if negate 'identity 'not) + (when (funcall (if negate #'identity #'not) (context-coloring-theme-originally-set-p theme)) (ert-fail (format (concat "Expected theme `%s' with settings `%s' " "%sto be considered to have defined a level, " @@ -328,21 +540,21 @@ non-nil." return t for a theme with SETTINGS. Apply ARGUMENTS to `context-coloring-test-assert-theme-originally-set-p', see that function." - (apply 'context-coloring-test-assert-theme-originally-set-p + (apply #'context-coloring-test-assert-theme-originally-set-p (append arguments '(t)))) -(ert-deftest context-coloring-test-theme-originally-set-p () - (context-coloring-test-assert-theme-originally-set-p - '((theme-face context-coloring-level-0-face))) - (context-coloring-test-assert-theme-originally-set-p - '((theme-face face) - (theme-face context-coloring-level-0-face))) - (context-coloring-test-assert-theme-originally-set-p - '((theme-face context-coloring-level-0-face) - (theme-face face))) - (context-coloring-test-assert-not-theme-originally-set-p - '((theme-face face))) - ) +(context-coloring-test-deftest theme-originally-set-p + (lambda () + (context-coloring-test-assert-theme-originally-set-p + '((theme-face context-coloring-level-0-face))) + (context-coloring-test-assert-theme-originally-set-p + '((theme-face face) + (theme-face context-coloring-level-0-face))) + (context-coloring-test-assert-theme-originally-set-p + '((theme-face context-coloring-level-0-face) + (theme-face face))) + (context-coloring-test-assert-not-theme-originally-set-p + '((theme-face face))))) (defun context-coloring-test-assert-theme-settings-highest-level (settings expected-level) @@ -357,7 +569,7 @@ EXPECTED-LEVEL." "Assert that THEME has the highest level EXPECTED-LEVEL, or the inverse if NEGATE is non-nil." (let ((highest-level (context-coloring-theme-highest-level theme))) - (when (funcall (if negate 'identity 'not) (eq highest-level expected-level)) + (when (funcall (if negate #'identity #'not) (eq highest-level expected-level)) (ert-fail (format (concat "Expected theme with settings `%s' " "%sto have a highest level of `%s', " "but it %s.") @@ -370,61 +582,49 @@ inverse if NEGATE is non-nil." Apply ARGUMENTS to `context-coloring-test-assert-theme-highest-level', see that function." - (apply 'context-coloring-test-assert-theme-highest-level + (apply #'context-coloring-test-assert-theme-highest-level (append arguments '(t)))) -(ert-deftest context-coloring-test-theme-highest-level () - (context-coloring-test-assert-theme-settings-highest-level - '((theme-face foo)) - -1) - (context-coloring-test-assert-theme-settings-highest-level - '((theme-face context-coloring-level-0-face)) - 0) - (context-coloring-test-assert-theme-settings-highest-level - '((theme-face context-coloring-level-1-face)) - 1) - (context-coloring-test-assert-theme-settings-highest-level - '((theme-face context-coloring-level-1-face) - (theme-face context-coloring-level-0-face)) - 1) - (context-coloring-test-assert-theme-settings-highest-level - '((theme-face context-coloring-level-0-face) - (theme-face context-coloring-level-1-face)) - 1) - ) - -(defmacro context-coloring-test-deftest-define-theme (name &rest body) - "Define a test with name NAME and an automatically-generated -theme symbol available as a free variable `theme'. Side-effects -from enabling themes are reversed after BODY is executed and the -test completes." - (declare (indent defun)) - (let ((deftest-name (intern - (format "context-coloring-test-define-theme-%s" name)))) - `(ert-deftest ,deftest-name () - (context-coloring-test-kill-buffer "*Warnings*") - (let ((theme (context-coloring-test-get-next-theme))) - (unwind-protect - (progn - ,@body) - ;; Always cleanup. - (disable-theme theme)))))) +(context-coloring-test-deftest theme-highest-level + (lambda () + (context-coloring-test-assert-theme-settings-highest-level + '((theme-face foo)) + -1) + (context-coloring-test-assert-theme-settings-highest-level + '((theme-face context-coloring-level-0-face)) + 0) + (context-coloring-test-assert-theme-settings-highest-level + '((theme-face context-coloring-level-1-face)) + 1) + (context-coloring-test-assert-theme-settings-highest-level + '((theme-face context-coloring-level-1-face) + (theme-face context-coloring-level-0-face)) + 1) + (context-coloring-test-assert-theme-settings-highest-level + '((theme-face context-coloring-level-0-face) + (theme-face context-coloring-level-1-face)) + 1))) + +(defun context-coloring-test-kill-buffer (buffer) + "Kill BUFFER if it exists." + (when (get-buffer buffer) (kill-buffer buffer))) (defun context-coloring-test-deftheme (theme) "Dynamically define theme THEME." (eval (macroexpand `(deftheme ,theme)))) (context-coloring-test-deftest-define-theme additive - (context-coloring-test-deftheme theme) - (context-coloring-define-theme - theme - :colors '("#aaaaaa" - "#bbbbbb")) - (context-coloring-test-assert-no-message "*Warnings*") - (enable-theme theme) - (context-coloring-test-assert-no-message "*Warnings*") - (context-coloring-test-assert-face 0 "#aaaaaa") - (context-coloring-test-assert-face 1 "#bbbbbb")) + (lambda (theme) + (context-coloring-test-deftheme theme) + (context-coloring-define-theme + theme + :colors '("#aaaaaa" + "#bbbbbb")) + (context-coloring-test-assert-no-message "*Warnings*") + (enable-theme theme) + (context-coloring-test-assert-no-message "*Warnings*") + (context-coloring-test-assert-face 0 "#aaaaaa") + (context-coloring-test-assert-face 1 "#bbbbbb"))) (defun context-coloring-test-assert-defined-warning (theme) "Assert that a warning about colors already being defined for @@ -436,127 +636,147 @@ theme THEME is signaled." "*Warnings*")) (context-coloring-test-deftest-define-theme unintentional-override - (context-coloring-test-deftheme theme) - (custom-theme-set-faces - theme - '(context-coloring-level-0-face ((t (:foreground "#aaaaaa")))) - '(context-coloring-level-1-face ((t (:foreground "#bbbbbb"))))) - (context-coloring-define-theme - theme - :colors '("#cccccc" - "#dddddd")) - (context-coloring-test-assert-defined-warning theme) - (context-coloring-test-kill-buffer "*Warnings*") - (enable-theme theme) - (context-coloring-test-assert-defined-warning theme) - (context-coloring-test-assert-face 0 "#cccccc") - (context-coloring-test-assert-face 1 "#dddddd")) + (lambda (theme) + (context-coloring-test-deftheme theme) + (custom-theme-set-faces + theme + '(context-coloring-level-0-face ((t (:foreground "#aaaaaa")))) + '(context-coloring-level-1-face ((t (:foreground "#bbbbbb"))))) + (context-coloring-define-theme + theme + :colors '("#cccccc" + "#dddddd")) + (context-coloring-test-assert-defined-warning theme) + (context-coloring-test-kill-buffer "*Warnings*") + (enable-theme theme) + (context-coloring-test-assert-defined-warning theme) + (context-coloring-test-assert-face 0 "#cccccc") + (context-coloring-test-assert-face 1 "#dddddd"))) (context-coloring-test-deftest-define-theme intentional-override - (context-coloring-test-deftheme theme) - (custom-theme-set-faces - theme - '(context-coloring-level-0-face ((t (:foreground "#aaaaaa")))) - '(context-coloring-level-1-face ((t (:foreground "#bbbbbb"))))) - (context-coloring-define-theme - theme - :override t - :colors '("#cccccc" - "#dddddd")) - (context-coloring-test-assert-no-message "*Warnings*") - (enable-theme theme) - (context-coloring-test-assert-no-message "*Warnings*") - (context-coloring-test-assert-face 0 "#cccccc") - (context-coloring-test-assert-face 1 "#dddddd")) + (lambda (theme) + (context-coloring-test-deftheme theme) + (custom-theme-set-faces + theme + '(context-coloring-level-0-face ((t (:foreground "#aaaaaa")))) + '(context-coloring-level-1-face ((t (:foreground "#bbbbbb"))))) + (context-coloring-define-theme + theme + :override t + :colors '("#cccccc" + "#dddddd")) + (context-coloring-test-assert-no-message "*Warnings*") + (enable-theme theme) + (context-coloring-test-assert-no-message "*Warnings*") + (context-coloring-test-assert-face 0 "#cccccc") + (context-coloring-test-assert-face 1 "#dddddd"))) (context-coloring-test-deftest-define-theme pre-recede - (context-coloring-define-theme - theme - :recede t - :colors '("#aaaaaa" - "#bbbbbb")) - (context-coloring-test-deftheme theme) - (custom-theme-set-faces - theme - '(context-coloring-level-0-face ((t (:foreground "#cccccc")))) - '(context-coloring-level-1-face ((t (:foreground "#dddddd"))))) - (enable-theme theme) - (context-coloring-test-assert-no-message "*Warnings*") - (context-coloring-test-assert-face 0 "#cccccc") - (context-coloring-test-assert-face 1 "#dddddd")) + (lambda (theme) + (context-coloring-define-theme + theme + :recede t + :colors '("#aaaaaa" + "#bbbbbb")) + (context-coloring-test-deftheme theme) + (custom-theme-set-faces + theme + '(context-coloring-level-0-face ((t (:foreground "#cccccc")))) + '(context-coloring-level-1-face ((t (:foreground "#dddddd"))))) + (enable-theme theme) + (context-coloring-test-assert-no-message "*Warnings*") + (context-coloring-test-assert-face 0 "#cccccc") + (context-coloring-test-assert-face 1 "#dddddd"))) + +(context-coloring-test-deftest-define-theme pre-recede-delayed-application + (lambda (theme) + (context-coloring-define-theme + theme + :recede t + :colors '("#aaaaaa" + "#bbbbbb")) + (context-coloring-test-deftheme theme) + (enable-theme theme) + (context-coloring-test-assert-no-message "*Warnings*") + (context-coloring-test-assert-face 0 "#aaaaaa") + (context-coloring-test-assert-face 1 "#bbbbbb"))) (context-coloring-test-deftest-define-theme post-recede - (context-coloring-test-deftheme theme) - (custom-theme-set-faces - theme - '(context-coloring-level-0-face ((t (:foreground "#aaaaaa")))) - '(context-coloring-level-1-face ((t (:foreground "#bbbbbb"))))) - (context-coloring-define-theme - theme - :recede t - :colors '("#cccccc" - "#dddddd")) - (context-coloring-test-assert-no-message "*Warnings*") - (context-coloring-test-assert-face 0 "#aaaaaa") - (context-coloring-test-assert-face 1 "#bbbbbb") - (enable-theme theme) - (context-coloring-test-assert-no-message "*Warnings*") - (context-coloring-test-assert-face 0 "#aaaaaa") - (context-coloring-test-assert-face 1 "#bbbbbb")) + (lambda (theme) + (context-coloring-test-deftheme theme) + (custom-theme-set-faces + theme + '(context-coloring-level-0-face ((t (:foreground "#aaaaaa")))) + '(context-coloring-level-1-face ((t (:foreground "#bbbbbb"))))) + (context-coloring-define-theme + theme + :recede t + :colors '("#cccccc" + "#dddddd")) + (context-coloring-test-assert-no-message "*Warnings*") + (context-coloring-test-assert-face 0 "#aaaaaa") + (context-coloring-test-assert-face 1 "#bbbbbb") + (enable-theme theme) + (context-coloring-test-assert-no-message "*Warnings*") + (context-coloring-test-assert-face 0 "#aaaaaa") + (context-coloring-test-assert-face 1 "#bbbbbb"))) (context-coloring-test-deftest-define-theme recede-not-defined - (context-coloring-test-deftheme theme) - (custom-theme-set-faces - theme - '(foo-face ((t (:foreground "#ffffff"))))) - (context-coloring-define-theme - theme - :recede t - :colors '("#aaaaaa" - "#bbbbbb")) - (context-coloring-test-assert-no-message "*Warnings*") - (context-coloring-test-assert-face 0 "#aaaaaa") - (context-coloring-test-assert-face 1 "#bbbbbb") - (enable-theme theme) - (context-coloring-test-assert-no-message "*Warnings*") - (context-coloring-test-assert-face 0 "#aaaaaa") - (context-coloring-test-assert-face 1 "#bbbbbb")) + (lambda (theme) + (context-coloring-test-deftheme theme) + (custom-theme-set-faces + theme + '(foo-face ((t (:foreground "#ffffff"))))) + (context-coloring-define-theme + theme + :recede t + :colors '("#aaaaaa" + "#bbbbbb")) + (context-coloring-test-assert-no-message "*Warnings*") + (context-coloring-test-assert-face 0 "#aaaaaa") + (context-coloring-test-assert-face 1 "#bbbbbb") + (enable-theme theme) + (context-coloring-test-assert-no-message "*Warnings*") + (context-coloring-test-assert-face 0 "#aaaaaa") + (context-coloring-test-assert-face 1 "#bbbbbb"))) (context-coloring-test-deftest-define-theme unintentional-obstinance - (context-coloring-define-theme - theme - :colors '("#aaaaaa" - "#bbbbbb")) - (context-coloring-test-deftheme theme) - (custom-theme-set-faces - theme - '(context-coloring-level-0-face ((t (:foreground "#cccccc")))) - '(context-coloring-level-1-face ((t (:foreground "#dddddd"))))) - (enable-theme theme) - (context-coloring-test-assert-defined-warning theme) - (context-coloring-test-assert-face 0 "#aaaaaa") - (context-coloring-test-assert-face 1 "#bbbbbb")) + (lambda (theme) + (context-coloring-define-theme + theme + :colors '("#aaaaaa" + "#bbbbbb")) + (context-coloring-test-deftheme theme) + (custom-theme-set-faces + theme + '(context-coloring-level-0-face ((t (:foreground "#cccccc")))) + '(context-coloring-level-1-face ((t (:foreground "#dddddd"))))) + (enable-theme theme) + (context-coloring-test-assert-defined-warning theme) + (context-coloring-test-assert-face 0 "#aaaaaa") + (context-coloring-test-assert-face 1 "#bbbbbb"))) (context-coloring-test-deftest-define-theme intentional-obstinance - (context-coloring-define-theme - theme - :override t - :colors '("#aaaaaa" - "#bbbbbb")) - (context-coloring-test-deftheme theme) - (custom-theme-set-faces - theme - '(context-coloring-level-0-face ((t (:foreground "#cccccc")))) - '(context-coloring-level-1-face ((t (:foreground "#dddddd"))))) - (enable-theme theme) - (context-coloring-test-assert-no-message "*Warnings*") - (context-coloring-test-assert-face 0 "#aaaaaa") - (context-coloring-test-assert-face 1 "#bbbbbb")) + (lambda (theme) + (context-coloring-define-theme + theme + :override t + :colors '("#aaaaaa" + "#bbbbbb")) + (context-coloring-test-deftheme theme) + (custom-theme-set-faces + theme + '(context-coloring-level-0-face ((t (:foreground "#cccccc")))) + '(context-coloring-level-1-face ((t (:foreground "#dddddd"))))) + (enable-theme theme) + (context-coloring-test-assert-no-message "*Warnings*") + (context-coloring-test-assert-face 0 "#aaaaaa") + (context-coloring-test-assert-face 1 "#bbbbbb"))) (defun context-coloring-test-assert-maximum-face (maximum &optional negate) "Assert that `context-coloring-maximum-face' is MAXIMUM, or the inverse if NEGATE is non-nil." - (when (funcall (if negate 'identity 'not) + (when (funcall (if negate #'identity #'not) (eq context-coloring-maximum-face maximum)) (ert-fail (format (concat "Expected `context-coloring-maximum-face' " "%sto be `%s', " @@ -570,152 +790,483 @@ inverse if NEGATE is non-nil." "Assert that `context-coloring-maximum-face' is not MAXIMUM. Apply ARGUMENTS to `context-coloring-test-assert-maximum-face', see that function." - (apply 'context-coloring-test-assert-maximum-face + (apply #'context-coloring-test-assert-maximum-face (append arguments '(t)))) (context-coloring-test-deftest-define-theme disable-cascade - (context-coloring-test-deftheme theme) - (context-coloring-define-theme - theme - :colors '("#aaaaaa" - "#bbbbbb")) - (let ((second-theme (context-coloring-test-get-next-theme))) - (context-coloring-test-deftheme second-theme) - (context-coloring-define-theme - second-theme - :colors '("#cccccc" - "#dddddd" - "#eeeeee")) - (let ((third-theme (context-coloring-test-get-next-theme))) - (context-coloring-test-deftheme third-theme) + (lambda (theme) + (let ((maximum-face-value 9999)) + (setq context-coloring-maximum-face maximum-face-value) + (context-coloring-test-deftheme theme) (context-coloring-define-theme - third-theme - :colors '("#111111" - "#222222" - "#333333" - "#444444")) - (enable-theme theme) - (enable-theme second-theme) - (enable-theme third-theme) - (disable-theme third-theme) - (context-coloring-test-assert-face 0 "#cccccc") - (context-coloring-test-assert-face 1 "#dddddd") - (context-coloring-test-assert-face 2 "#eeeeee") - (context-coloring-test-assert-maximum-face 2)) - (disable-theme second-theme) - (context-coloring-test-assert-face 0 "#aaaaaa") - (context-coloring-test-assert-face 1 "#bbbbbb") - (context-coloring-test-assert-maximum-face 1)) - (disable-theme theme) - (context-coloring-test-assert-not-face 0 "#aaaaaa") - (context-coloring-test-assert-not-face 1 "#bbbbbb") - (context-coloring-test-assert-not-maximum-face 1)) - -(defun context-coloring-test-js-function-scopes () - "Test fixtures/functions-scopes.js." - (context-coloring-test-assert-region-level 1 9 0) - (context-coloring-test-assert-region-level 9 23 1) - (context-coloring-test-assert-region-level 23 25 0) - (context-coloring-test-assert-region-level 25 34 1) - (context-coloring-test-assert-region-level 34 35 0) - (context-coloring-test-assert-region-level 35 52 1) - (context-coloring-test-assert-region-level 52 66 2) - (context-coloring-test-assert-region-level 66 72 1) - (context-coloring-test-assert-region-level 72 81 2) - (context-coloring-test-assert-region-level 81 82 1) - (context-coloring-test-assert-region-level 82 87 2) - (context-coloring-test-assert-region-level 87 89 1)) - -(context-coloring-test-deftest-js-mode function-scopes) -(context-coloring-test-deftest-js2-mode function-scopes) - -(defun context-coloring-test-js-global () - "Test fixtures/global.js." - (context-coloring-test-assert-region-level 20 28 1) - (context-coloring-test-assert-region-level 28 35 0) - (context-coloring-test-assert-region-level 35 41 1)) - -(context-coloring-test-deftest-js-mode global) -(context-coloring-test-deftest-js2-mode global) - -(defun context-coloring-test-js-block-scopes () - "Test fixtures/block-scopes.js." - (context-coloring-test-assert-region-level 20 64 1) - (setq context-coloring-js-block-scopes t) - (context-coloring-colorize) - (context-coloring-test-assert-region-level 20 27 1) - (context-coloring-test-assert-region-level 27 41 2) - (context-coloring-test-assert-region-level 41 42 1) - (context-coloring-test-assert-region-level 42 64 2)) - -(context-coloring-test-deftest-js2-mode block-scopes) - -(defun context-coloring-test-js-catch () - "Test fixtures/js-catch.js." - (context-coloring-test-assert-region-level 20 27 1) - (context-coloring-test-assert-region-level 27 51 2) - (context-coloring-test-assert-region-level 51 52 1) - (context-coloring-test-assert-region-level 52 73 2) - (context-coloring-test-assert-region-level 73 101 3) - (context-coloring-test-assert-region-level 101 102 1) - (context-coloring-test-assert-region-level 102 117 3) - (context-coloring-test-assert-region-level 117 123 2)) - -(context-coloring-test-deftest-js-mode catch) -(context-coloring-test-deftest-js2-mode catch) - -(defun context-coloring-test-js-key-names () - "Test fixtures/key-names.js." - (context-coloring-test-assert-region-level 20 63 1)) - -(context-coloring-test-deftest-js-mode key-names) -(context-coloring-test-deftest-js2-mode key-names) - -(defun context-coloring-test-js-property-lookup () - "Test fixtures/property-lookup.js." - (context-coloring-test-assert-region-level 20 26 0) - (context-coloring-test-assert-region-level 26 38 1) - (context-coloring-test-assert-region-level 38 44 0) - (context-coloring-test-assert-region-level 44 52 1) - (context-coloring-test-assert-region-level 57 63 0) - (context-coloring-test-assert-region-level 63 74 1)) - -(context-coloring-test-deftest-js-mode property-lookup) -(context-coloring-test-deftest-js2-mode property-lookup) - -(defun context-coloring-test-js-key-values () - "Test fixtures/key-values.js." - (context-coloring-test-assert-region-level 78 79 1)) - -(context-coloring-test-deftest-js-mode key-values) -(context-coloring-test-deftest-js2-mode key-values) - -(defun context-coloring-test-js-comments-and-strings () - "Test fixtures/comments-and-strings.js." - (context-coloring-test-assert-region-comment-delimiter 1 4) - (context-coloring-test-assert-region-comment 4 8) - (context-coloring-test-assert-region-comment-delimiter 9 12) - (context-coloring-test-assert-region-comment 12 19) - (context-coloring-test-assert-region-string 20 32) - (context-coloring-test-assert-region-level 32 33 0)) - -(ert-deftest-async context-coloring-test-js-mode-comments-and-strings (done) - (context-coloring-test-js-mode - "./fixtures/comments-and-strings.js" - (lambda (teardown) - (unwind-protect - (context-coloring-test-js-comments-and-strings) - (funcall teardown)) - (funcall done)) - (lambda () - (setq context-coloring-comments-and-strings t)))) - -(ert-deftest context-coloring-test-js2-mode-comments-and-strings () - (context-coloring-test-js2-mode - "./fixtures/comments-and-strings.js" - (setq context-coloring-comments-and-strings t) - (context-coloring-colorize) - (context-coloring-test-js-comments-and-strings))) + theme + :colors '("#aaaaaa" + "#bbbbbb")) + (let ((second-theme (context-coloring-test-get-next-theme))) + (context-coloring-test-deftheme second-theme) + (context-coloring-define-theme + second-theme + :colors '("#cccccc" + "#dddddd" + "#eeeeee")) + (let ((third-theme (context-coloring-test-get-next-theme))) + (context-coloring-test-deftheme third-theme) + (context-coloring-define-theme + third-theme + :colors '("#111111" + "#222222" + "#333333" + "#444444")) + (enable-theme theme) + (enable-theme second-theme) + (enable-theme third-theme) + (disable-theme third-theme) + (context-coloring-test-assert-face 0 "#cccccc") + (context-coloring-test-assert-face 1 "#dddddd") + (context-coloring-test-assert-face 2 "#eeeeee") + (context-coloring-test-assert-maximum-face 2)) + (disable-theme second-theme) + (context-coloring-test-assert-face 0 "#aaaaaa") + (context-coloring-test-assert-face 1 "#bbbbbb") + (context-coloring-test-assert-maximum-face 1)) + (disable-theme theme) + (context-coloring-test-assert-not-face 0 "#aaaaaa") + (context-coloring-test-assert-not-face 1 "#bbbbbb") + (context-coloring-test-assert-maximum-face + maximum-face-value)))) + + +;;; Coloring tests + +(defun context-coloring-test-assert-position-level (position level) + "Assert that POSITION has LEVEL." + (let ((face (get-text-property position 'face)) + actual-level) + (when (not (and face + (let* ((face-string (symbol-name face)) + (matches (string-match + context-coloring-level-face-regexp + face-string))) + (when matches + (setq actual-level (string-to-number + (substring face-string + (match-beginning 1) + (match-end 1)))) + (= level actual-level))))) + (ert-fail (format (concat "Expected level at position %s, " + "which is \"%s\", to be %s; " + "but it was %s") + position + (buffer-substring-no-properties position (1+ position)) level + actual-level))))) + +(defun context-coloring-test-assert-position-face (position face-regexp) + "Assert that the face at POSITION satisfies FACE-REGEXP." + (let ((face (get-text-property position 'face))) + (when (or + ;; Pass a non-string to do an `equal' check (against a symbol or nil). + (unless (stringp face-regexp) + (not (equal face-regexp face))) + ;; Otherwise do the matching. + (when (stringp face-regexp) + (not (string-match-p face-regexp (symbol-name face))))) + (ert-fail (format (concat "Expected face at position %s, " + "which is \"%s\", to be %s; " + "but it was %s") + position + (buffer-substring-no-properties position (1+ position)) face-regexp + face))))) + +(defun context-coloring-test-assert-position-comment (position) + "Assert that the face at POSITION is a comment." + (context-coloring-test-assert-position-face + position "\\`font-lock-comment\\(-delimiter\\)?-face\\'")) + +(defun context-coloring-test-assert-position-constant-comment (position) + "Assert that the face at POSITION is a constant comment." + (context-coloring-test-assert-position-face position '(font-lock-constant-face + font-lock-comment-face))) + +(defun context-coloring-test-assert-position-string (position) + "Assert that the face at POSITION is a string." + (context-coloring-test-assert-position-face position 'font-lock-string-face)) + +(defun context-coloring-test-assert-position-nil (position) + "Assert that the face at POSITION is nil." + (context-coloring-test-assert-position-face position nil)) + +(defun context-coloring-test-assert-coloring (map) + "Assert that the current buffer's coloring will match MAP. + +MAP's newlines should correspond to the current fixture. + +The following characters appearing in MAP assert coloring for +corresponding points in the fixture: + +0-9: Level equals number. +C: Face is constant comment. +c: Face is comment. +n: Face is nil. +s: Face is string. + +Any other characters are discarded. Characters \"x\" and any +other non-letters are guaranteed to always be discarded." + ;; Omit the superfluous, formatting-related leading newline. Can't use + ;; `save-excursion' here because if an assertion fails it will cause future + ;; tests to get messed up. + (goto-char (point-min)) + (let* ((map (substring map 1)) + (index 0) + char-string + char) + (while (< index (length map)) + (setq char-string (substring map index (1+ index))) + (setq char (string-to-char char-string)) + (cond + ;; Newline + ((= char 10) + (forward-line) + (beginning-of-line)) + ;; Number + ((and (>= char 48) + (<= char 57)) + (context-coloring-test-assert-position-level + (point) (string-to-number char-string)) + (forward-char)) + ;; 'C' = Constant comment + ((= char 67) + (context-coloring-test-assert-position-constant-comment (point)) + (forward-char)) + ;; 'c' = Comment + ((= char 99) + (context-coloring-test-assert-position-comment (point)) + (forward-char)) + ;; 'n' = nil + ((= char 110) + (context-coloring-test-assert-position-nil (point)) + (forward-char)) + ;; 's' = String + ((= char 115) + (context-coloring-test-assert-position-string (point)) + (forward-char)) + (t + (forward-char))) + (setq index (1+ index))))) + +(context-coloring-test-deftest-js-js2 function-scopes + (lambda () + (context-coloring-test-assert-coloring " +000 0 0 11111111 11 110 +11111111 011 1 + 111 1 1 22222222 22 221 + 22222222 122 22 +1"))) + +(context-coloring-test-deftest-js-js2 global + (lambda () + (context-coloring-test-assert-coloring " +(xxxxxxxx () { + 111 1 1 00000001xxx11 +}());"))) + +(context-coloring-test-deftest-js2 block-scopes + (lambda () + (context-coloring-test-assert-coloring " +(xxxxxxxx () { + 11 111 2 + 222 12 + 222 22 + 2 +}());")) + :before (lambda () + (setq context-coloring-js-block-scopes t)) + :after (lambda () + (setq context-coloring-js-block-scopes nil))) + +(context-coloring-test-deftest-js-js2 catch + (lambda () + (context-coloring-test-assert-coloring " +(xxxxxxxx () { + 111 11 22222 222 2 + 222 1 2 22 + 222 22 33333 333 3 + 333 1 3 33 + 3 + 2 +}());"))) + +(context-coloring-test-deftest-js-js2 key-names + (lambda () + (context-coloring-test-assert-coloring " +(xxxxxxxx () { + 111111 1 + 11 11 + 1 1 1 + 11 +}());"))) + +(context-coloring-test-deftest-js-js2 property-lookup + (lambda () + (context-coloring-test-assert-coloring " +(xxxxxxxx () { + 0000001111111 + 0000001 111111 + 00000011111111111 +}());"))) + +(context-coloring-test-deftest-js-js2 key-values + (lambda () + (context-coloring-test-assert-coloring " +(xxxxxxxx () { + xxx x; + (xxxxxxxx () { + xxxxxx { + x: 1 + }; + }()); +}());"))) + +(context-coloring-test-deftest-js-js2 syntactic-comments-and-strings + (lambda () + (context-coloring-test-assert-coloring " +0000 00 +ccccccc +cccccccccc +ssssssssssss0")) + :fixture "comments-and-strings.js") + +(context-coloring-test-deftest-js-js2 syntactic-comments + (lambda () + (context-coloring-test-assert-coloring " +0000 00 +ccccccc +cccccccccc +0000000000000")) + :fixture "comments-and-strings.js" + :before (lambda () + (setq context-coloring-syntactic-strings nil)) + :after (lambda () + (setq context-coloring-syntactic-strings t))) + +(context-coloring-test-deftest-js-js2 syntactic-strings + (lambda () + (context-coloring-test-assert-coloring " +0000 00 +0000000 +0000000000 +ssssssssssss0")) + :fixture "comments-and-strings.js" + :before (lambda () + (setq context-coloring-syntactic-comments nil)) + :after (lambda () + (setq context-coloring-syntactic-comments t))) + +(context-coloring-test-deftest-js2 unterminated-comment + ;; As long as `add-text-properties' doesn't signal an error, this test passes. + (lambda ())) + +(context-coloring-test-deftest-emacs-lisp defun + (lambda () + (context-coloring-test-assert-coloring " +111111 000 1111 111 111111111 1111 + 11 111 111 111 000011 + +0000 0 0 00 + +111111 01 +111111 111 +111111 0 1sss11"))) + +(context-coloring-test-deftest-emacs-lisp defadvice + (lambda () + (context-coloring-test-assert-coloring " +1111111111 0 1111111 111111 11111 111 111111111 + 2222 222 122 + 22 1 2221"))) + +(context-coloring-test-deftest-emacs-lisp lambda + (lambda () + (context-coloring-test-assert-coloring " +00000000 1111111 1111 + 11111111 11 2222222 2222 + 222 22 12 2221 111 0 00"))) + +(context-coloring-test-deftest-emacs-lisp quote + (lambda () + (context-coloring-test-assert-coloring " +(xxxxx 0000000 00 00000) +(xxx () (xxxxxxxxx (,0000))) + +(xxxxx x (x) + (xx (xx x 111 + 111111 1 111 111 + 111111 1 1111111111 11 111 1 111 1 00001 10000 11 00001 1 10000 + sss ccc + 1111 + +(xxxxxx '(sss cc + sss cc + )) + +(xxxxxx () 111111 11111)"))) + +(context-coloring-test-deftest-emacs-lisp splice + (lambda () + (context-coloring-test-assert-coloring " +(xxxxxx () + 111111 00001 100001)"))) + +(context-coloring-test-deftest-emacs-lisp comment + (lambda () + ;; Just check that the comment isn't parsed syntactically. + (context-coloring-test-assert-coloring " +(xxxxx x () + (xx (x xxxxx-xxxx xx) cccccccccc + 11 00000-0000 11))) cccccccccc"))) + +(context-coloring-test-deftest-emacs-lisp string + (lambda () + (context-coloring-test-assert-coloring " +(xxxxx x (x) + (xxxxxx x x sss 1 0 sssss 0 1 sssssss11"))) + +(context-coloring-test-deftest-emacs-lisp ignored + (lambda () + (context-coloring-test-assert-coloring " +(xxxxx x () + (x x 1 11 11 111 111 11 11 11 1 111 (1 1 1)))"))) + +(context-coloring-test-deftest-emacs-lisp sexp + (lambda () + (context-coloring-test-assert-coloring " +(xxx () + `,@sss + `,@11 + `,@11)"))) + +(context-coloring-test-deftest-emacs-lisp let + (lambda () + (context-coloring-test-assert-coloring " +1111 11 + 11 01 + 11 00001 + 11 2222 22 + 22 02 + 22 000022 + 2222 2 2 2 00002211 + 1111 1 1 1 000011 + +1111 cc ccccccc + 1sss11"))) + +(context-coloring-test-deftest-emacs-lisp let* + (lambda () + (context-coloring-test-assert-coloring " +11111 11 + 11 11 + 11 000011 + 1111 1 1 1 0 0 00001 + 22222 22 + 22 12 + 22 00002 + 22 02 + 22 222 + 2222 1 1 2 2 2 000022 + 1111 1 1 1 0 0 000011"))) + +(context-coloring-test-deftest-emacs-lisp cond + (lambda () + (context-coloring-test-assert-coloring " +(xxx (x) + 11111 + 11 11 + 10000 11 + 1111 1 00001 11 + 11 11111 1 000011 + cc c + sss1)"))) + +(context-coloring-test-deftest-emacs-lisp condition-case + (lambda () + (context-coloring-test-assert-coloring " +1111111111-1111 111 + 111111 000 00001 + 111111 111 00001 + 1111111 111111 111 000011 + +(111111111-1111-111111-11111 111 + cc c + (xxx () 222) + (11111 (xxx () 222)) + sss)"))) + +(context-coloring-test-deftest-emacs-lisp dolist + (lambda () + (context-coloring-test-assert-coloring " +1111111 111111 + 2222222 2222 1111 2222222 + 3333333 33 33 222 1111 2222223321"))) + +(defun context-coloring-test-insert-unread-space () + "Simulate the insertion of a space as if by a user." + (setq unread-command-events (cons '(t . 32) + unread-command-events))) + +(defun context-coloring-test-remove-faces () + "Remove all faces in the current buffer." + (remove-text-properties (point-min) (point-max) '(face nil))) + +(context-coloring-test-deftest-emacs-lisp iteration + (lambda () + (let ((context-coloring-elisp-sexps-per-pause 2)) + (context-coloring-colorize) + (context-coloring-test-assert-coloring " +cc `CC' `CC' +(xxxxx x ())") + (context-coloring-test-remove-faces) + (context-coloring-test-insert-unread-space) + (context-coloring-colorize) + ;; Coloring is interrupted after the first "sexp" (the comment in this + ;; case). + (context-coloring-test-assert-coloring " +cc `CC' `CC' +nnnnnn n nnn")))) + +(context-coloring-test-deftest-emacs-lisp changed + (lambda () + (context-coloring-test-remove-faces) + ;; Goto line 3. + (goto-char (point-min)) + (forward-line (1- 3)) + (insert " ") + ;; Mock `pos-visible-in-window-p' because in batch mode `get-buffer-window' + ;; returns nil. Emacs must not have a window in that environment. + (cl-letf (((symbol-function 'pos-visible-in-window-p) + (let ((calls 0)) + (lambda () + (prog1 + ;; First and third calls start from center. Second and + ;; fourth calls are made immediately after moving past + ;; the first defun in either direction "off screen". + (cond + ((= calls 0) t) + ((= calls 1) nil) + ((= calls 2) t) + ((= calls 4) nil)) + (setq calls (1+ calls))))))) + (context-coloring-colorize)) + (context-coloring-test-assert-coloring " +nnnn n nnn nnnnnnnn +0000 + +0000 +nnnnn n nnn nnnnnnnn"))) + +(context-coloring-test-deftest-emacs-lisp unbalanced-parenthesis + (lambda () + (context-coloring-test-assert-coloring " +1111 111 +nnnn nn"))) (provide 'context-coloring-test)