diff --git a/.travis.yml b/.travis.yml index 3e80f82a8..571704789 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ before_install: - export PATH="/home/travis/.evm/bin:$PATH" - evm config path /tmp - evm install $EVM_EMACS --use - - cp test/init.test.el init.el + - cp init.test.el init.el - INSECURE=1 YES=1 make install env: - EVM_EMACS=emacs-25.1-travis diff --git a/Makefile b/Makefile index ee1e54456..3e8a05282 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ # Ensure emacs always runs from this makefile's PWD -EMACS_LIBS=-l core/core.el -EMACS=emacs --batch --eval '(setq user-emacs-directory default-directory)' $(EMACS_LIBS) -TEST_EMACS=$(EMACS) --eval '(setq noninteractive nil)' $(EMACS_LIBS) -TESTS=$(shell find test/ -type f -name 'test-*.el') -MODULES=$(shell find modules/ -maxdepth 2 -type d) +EMACS_FLAGS=--eval '(setq user-emacs-directory default-directory)' -l core/core.el +EMACS=emacs --batch $(EMACS_FLAGS) +EMACSI=emacs -q $(EMACS_FLAGS) + +MODULES=$(patsubst modules/%, %, $(shell find modules/ -maxdepth 2 -type d)) # Tasks all: autoloads autoremove install update @@ -30,8 +30,8 @@ core: init.el clean @$(EMACS) -f doom/compile -- init.el core $(MODULES): init.el .local/autoloads.el - @rm -fv $(shell find $@ -maxdepth 2 -type f -name '*.elc') - @$(EMACS) -f doom/compile -- $@ + @rm -fv $(shell find modules/$@ -type f -name '*.elc') + @$(EMACS) -f doom/compile -- modules/$@ clean: @$(EMACS) -f doom/clean-compiled @@ -43,10 +43,18 @@ clean-pcache: @$(EMACS) -l persistent-soft --eval '(delete-directory pcache-directory t)' test: init.el .local/autoloads.el - @$(TEST_EMACS) $(patsubst %,-l %, $(TESTS)) -l test/run.el + @$(EMACS) -f doom/run-tests -$(TESTS): init.el .local/autoloads.el - @$(TEST_EMACS) $(patsubst %,-l %, $@) -l test/run.el +test\:core $(patsubst %, test\:%, $(MODULES)): init.el .local/autoloads.el + @$(EMACS) -f doom/run-tests -- $(subst test:, , $@) + +# run tests interactively +testi: init.el .local/autoloads.el + @DEBUG=1 $(EMACSI) -f doom/run-tests -f ert + +# For running Emacs from a different folder than ~/.emacs.d +run: + @emacs $(EMACS_FLAGS) -l init.el doctor: @./bin/doctor @@ -62,4 +70,4 @@ init.el: @$(EMACS) -f doom/compile -- $< -.PHONY: all test $(TESTS) $(MODULES) +.PHONY: all test $(MODULES) diff --git a/core/autoload/test.el b/core/autoload/test.el index 3d505033c..e799fb02b 100644 --- a/core/autoload/test.el +++ b/core/autoload/test.el @@ -1,10 +1,15 @@ ;;; core/autoload/test.el -*- lexical-binding: t; -*- ;;;###autoload -(defmacro def-test-group! (name &rest body) - (declare (indent defun)) +(defmacro def-test! (name &rest body) + "Define a namespaced ERT test." + (declare (indent defun) (doc-string 2)) (unless (plist-get body :disabled) - (dolist (form body) - (when (eq (car form) 'ert-deftest) - (setf (cadr form) (intern (format "test-%s-%s" name (symbol-name (cadr form))))))) - `(progn ,@body))) + `(ert-deftest + ,(cl-loop with path = (file-relative-name (file-name-sans-extension load-file-name) + doom-emacs-dir) + for (rep . with) in '(("/test/" . "/") ("/" . ":")) + do (setq path (replace-regexp-in-string rep with path t t)) + finally return (intern (format "%s::%s" path name))) () + () + ,@body))) diff --git a/core/core-packages.el b/core/core-packages.el index b6a136453..fd8131ef9 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -367,20 +367,16 @@ throw an error if the file doesn't exist." (defmacro require! (module submodule &optional reload-p) "Like `require', but for doom modules. Will load a module's config.el file if it hasn't already, and if it exists." - (when (or (not noninteractive) - (bound-and-true-p byte-compile-current-file) - reload-p) - (let ((loaded-p (doom-module-loaded-p module submodule))) - (when (or reload-p (not loaded-p)) - (unless loaded-p - (doom--enable-module module submodule t)) - `(condition-case-unless-debug ex - (load! config ,(doom-module-path module submodule) t) - ('error - (lwarn 'doom-modules :error - "%s in '%s %s' -> %s" - (car ex) ,module ',submodule (error-message-string ex)))))))) - + (let ((loaded-p (doom-module-loaded-p module submodule))) + (when (or reload-p (not loaded-p)) + (unless loaded-p + (doom--enable-module module submodule t)) + `(condition-case-unless-debug ex + (load! config ,(doom-module-path module submodule) t) + ('error + (lwarn 'doom-modules :error + "%s in '%s %s' -> %s" + (car ex) ,module ',submodule (error-message-string ex))))))) (defmacro featurep! (module submodule) "Convenience macro that wraps `doom-module-loaded-p'." @@ -532,7 +528,7 @@ If ONLY-RECOMPILE-P is non-nil, only recompile out-of-date files." (doom-initialize-packages t t) (let ((targets (cond ((equal (car command-line-args-left) "--") - (cl-loop for file in command-line-args-left + (cl-loop for file in (cdr command-line-args-left) if (file-exists-p file) collect (expand-file-name file) finally do (setq command-line-args-left nil)) ) @@ -604,6 +600,65 @@ package files." and do (message "Deleted %s" (file-relative-name path))) (message "Everything is clean")))) +(defun doom/run-tests (&optional modules) + "Run all loaded tests, specified by MODULES (a list of module cons cells) or +command line args following a double dash (each arg should be in the +'module/submodule' format). + +If neither is available, run all tests in all enabled modules." + (interactive) ;; TODO Add completing-read selection of tests + ;; FIXME Refactor this + (condition-case-unless-debug ex + (let (targets) + ;; ensure DOOM is initialized + (let (noninteractive) + (unload-feature 'core t) + (load (expand-file-name "init.el" user-emacs-directory) nil t)) + (run-hooks 'emacs-startup-hook) + ;; collect targets + (cond ((and command-line-args-left + (equal (car command-line-args-left) "--")) + (cl-loop for arg in (cdr argv) + if (equal arg "core") + do (push (expand-file-name "test/" doom-core-dir) targets) + else + collect + (cl-destructuring-bind (car cdr) (split-string arg "/" t) + (cons (intern (concat ":" car)) + (and (cadr consp) (intern cdr)))) + into args + finally do (setq modules args + command-line-args-left nil))) + + (modules + (unless (cl-loop for module in modules + unless (and (consp module) + (keywordp (car module)) + (symbolp (cdr module))) + return t) + (error "Expected a list of cons, got: %s" modules))) + + (t + (setq modules (doom--module-pairs) + targets (list (expand-file-name "test/" doom-core-dir))))) + ;; resolve targets to a list of test files and load them + (cl-loop with targets = + (append targets + (cl-loop for (module . submodule) in modules + collect (doom-module-path module submodule "test/"))) + for dir in targets + if (file-directory-p dir) + nconc (reverse (directory-files-recursively dir "\\.el$")) + into items + finally do (quiet! (mapc #'load-file items))) + ;; run all loaded tests + (when noninteractive + (ert-run-tests-batch-and-exit))) + ('error + (lwarn 'doom-test :error + "%s -> %s" + (car ex) (error-message-string ex))))) + ;; ;; Package.el modifications diff --git a/core/core-popups.el b/core/core-popups.el index 0cacb3773..cbf2adcfe 100644 --- a/core/core-popups.el +++ b/core/core-popups.el @@ -73,6 +73,7 @@ is enabled/disabled.'") ("^\\*doom:" :regexp t :size 0.35 :noesc t :select t :modeline t) ("^\\*doom " :regexp t :noselect t :autokill t :autoclose t) ;; built-in (emacs) + ("*ert*" :same t :modeline t) ("*info*" :size 0.5 :select t :autokill t) ("*Backtrace*" :size 20 :noselect t) ("*Warnings*" :size 8 :noselect t) diff --git a/core/test/autoload-buffers.el b/core/test/autoload-buffers.el new file mode 100644 index 000000000..1b372010d --- /dev/null +++ b/core/test/autoload-buffers.el @@ -0,0 +1,99 @@ +;; -*- no-byte-compile: t; -*- +;;; core/test/autoload-buffers.el + +(defmacro -with-temp-buffers! (buffer-args &rest body) + (declare (indent defun)) + (let (buffers) + (dolist (bsym buffer-args) + (push `(,bsym (get-buffer-create ,(symbol-name bsym))) + buffers)) + `(let* (,@buffers + (buffer-list (list ,@(reverse (mapcar #'car buffers))))) + ,@body + (mapc #'kill-buffer buffer-list)))) + +;; +(def-test! get-buffers + (-with-temp-buffers! (a b c) + (should (cl-every #'buffer-live-p buffer-list)) + (should (equal buffer-list (list a b c))) + (dolist (buf (list (cons a doom-emacs-dir) + (cons b doom-emacs-dir) + (cons c "/tmp/"))) + (with-current-buffer (car buf) + (setq-local default-directory (cdr buf)))) + (with-current-buffer a + ;; should produce all buffers + (let ((buffers (doom-buffer-list))) + (should (cl-every (lambda (x) (memq x buffers)) (list a b c)))) + ;; should produce only project buffers + (let ((buffers (doom-buffer-list t))) + (should (cl-every (lambda (x) (memq x buffers)) (list a b))) + (should-not (memq c buffers)))) + ;; If no project is available, just get all buffers + (with-current-buffer c + (let ((buffers (doom-buffer-list t))) + (should (cl-every (lambda (x) (memq x buffers)) (list a b c))))))) + +(def-test! get-real-buffers + (-with-temp-buffers! (a b c d) + (dolist (buf (list a b)) + (with-current-buffer buf + (setq-local buffer-file-name "x"))) + (with-current-buffer c + (rename-buffer "*C*")) + (with-current-buffer d + (doom-popup-mode +1)) + (let ((buffers (doom-real-buffers-list buffer-list))) + (should (= (length buffers) 2)) + (should (cl-every (lambda (x) (memq x buffers)) (list a b))) + (should (cl-notany (lambda (x) (memq x buffers)) (list c d)))))) + +(def-test! kill-buffers + (-with-temp-buffers! (a b) + (doom-kill-buffer a) + (should-not (buffer-live-p a)) + ;; modified buffer + (with-current-buffer b + (set-buffer-modified-p t)) + (doom-kill-buffer b t) + (should-not (buffer-live-p a)))) + +(def-test! kill-buffer-then-show-real-buffer + (-with-temp-buffers! (a b c d) + (dolist (buf (list a b d)) + (with-current-buffer buf + (setq-local buffer-file-name "x"))) + (should (cl-every #'buffer-live-p buffer-list)) + (switch-to-buffer a) + (should (eq (current-buffer) a)) + (should (eq (selected-window) (get-buffer-window a))) + (should (doom-kill-buffer a)) + (should (eq (current-buffer) b)) + (should (doom-kill-buffer)) + (should (eq (current-buffer) d)) + (doom/kill-this-buffer) + (should (eq (current-buffer) (doom-fallback-buffer))))) + +(def-test! matching-buffers + (-with-temp-buffers! (a b c) + (let ((buffers (doom-matching-buffers "^[ac]$"))) + (should (= 2 (length buffers))) + (should (cl-every #'bufferp buffers)) + (should (cl-every (lambda (x) (memq x buffers)) (list a c))) + (should (equal (reverse buffers) + (doom-matching-buffers "^[ac]$" buffer-list)))))) + +(def-test! buffers-in-mode + (-with-temp-buffers! (a b c d e) + (dolist (buf (list a b)) + (with-current-buffer buf + (emacs-lisp-mode))) + (dolist (buf (list c d e)) + (with-current-buffer buf + (text-mode))) + (let ((el-buffers (doom-buffers-in-mode 'emacs-lisp-mode)) + (txt-buffers (doom-buffers-in-mode 'text-mode))) + (should (cl-every #'buffer-live-p (append el-buffers txt-buffers))) + (should (= 2 (length el-buffers))) + (should (= 3 (length txt-buffers)))))) diff --git a/core/test/autoload-debug.el b/core/test/autoload-debug.el new file mode 100644 index 000000000..32f1090a7 --- /dev/null +++ b/core/test/autoload-debug.el @@ -0,0 +1,19 @@ +;; -*- no-byte-compile: t; -*- +;;; core/test/autoload-debug.el + +(def-test! what-face + (with-temp-buffer + (insert (propertize "Hello " 'face 'font-lock-keyword-face)) + (insert "world") + + (should (equal (doom/what-face (point-min)) '((font-lock-keyword-face) ()))) + (should-not (doom/what-face (point-max))))) + +(def-test! what-face-overlays + (with-temp-buffer + (insert "Hello world") + (let ((ov (make-overlay 1 6))) + (overlay-put ov 'face 'font-lock-keyword-face)) + + (should (equal (doom/what-face (point-min)) '(() (font-lock-keyword-face)))) + (should-not (doom/what-face (point-max))))) diff --git a/core/test/autoload-message.el b/core/test/autoload-message.el new file mode 100644 index 000000000..c3e456a2f --- /dev/null +++ b/core/test/autoload-message.el @@ -0,0 +1,41 @@ +;; -*- no-byte-compile: t; -*- +;;; core/test/autoload-message.el + +;; ansi messages +(def-test! ansi-format + (let ((noninteractive t)) + (should (equal (format! "Hello %s" "World") + "Hello World")) + (should (equal (format! (red "Hello %s" "World")) + "Hello World")) + (should (equal (format! (green "Hello %s" "World")) + (format "\e[%dm%s\e[0m" + (cdr (assq 'green doom-message-fg)) + "Hello World"))) + (should (equal (format! (on-red "Hello %s" "World")) + (format "\e[%dm%s\e[0m" + (cdr (assq 'on-red doom-message-bg)) + "Hello World"))) + (should (equal (format! (bold "Hello %s" "World")) + (format "\e[%dm%s\e[0m" + (cdr (assq 'bold doom-message-fx)) + "Hello World"))))) + +(def-test! ansi-format-nested + (let ((noninteractive t)) + (should (equal (format! (bold (red "Hello %s" "World"))) + (format "\e[%dm%s\e[0m" 1 + (format "\e[%dm%s\e[0m" 31 "Hello World")))) + (should (equal (format! (on-red (bold "Hello %s" "World"))) + (format "\e[%dm%s\e[0m" 41 + (format "\e[%dm%s\e[0m" 1 "Hello World")))) + (should (equal (format! (dark (white "Hello %s" "World"))) + (format "\e[%dm%s\e[0m" 2 + (format "\e[%dm%s\e[0m" 37 "Hello World")))))) + +(def-test! ansi-format-apply + (let ((noninteractive t)) + (should (equal (format! (color 'red "Hello %s" "World")) + (format! (red "Hello %s" "World")))) + (should (equal (format! (color (if nil 'red 'blue) "Hello %s" "World")) + (format! (blue "Hello %s" "World")))))) diff --git a/core/test/autoload-package.el b/core/test/autoload-package.el new file mode 100644 index 000000000..e2c59e91a --- /dev/null +++ b/core/test/autoload-package.el @@ -0,0 +1,75 @@ +;; -*- no-byte-compile: t; -*- +;;; core/test/autoload-package.el + +(defun -new-package (name version &optional reqs) + (package-desc-create :name name :version version :reqs reqs)) + +(defmacro -with-temp-packages! (&rest forms) + "Run FORMS in the context of a temporary package setup (as in, it won't +affects your Emacs packages)." + `(let* ((doom-local-dir ,(expand-file-name "test/.local/" doom-emacs-dir)) + (doom-packages-dir (concat doom-local-dir "packages/")) + (doom-etc-dir (concat doom-local-dir "etc/")) + (doom-cache-dir (concat doom-local-dir "cache/")) + (package-user-dir (expand-file-name "elpa" doom-packages-dir)) + package-alist + package-archive-contents + package-initialize) + (package-initialize) + ,@forms)) + + +;; +;; Tests +;; + +(def-test! backend-detection + (let ((package-alist `((doom-dummy ,(-new-package 'doom-dummy '(20160405 1234))))) + (quelpa-cache '((doom-quelpa-dummy :fetcher github :repo "hlissner/does-not-exist"))) + (quelpa-initialized-p t)) + (should (eq (doom-package-backend 'doom-dummy) 'elpa)) + (should (eq (doom-package-backend 'doom-quelpa-dummy) 'quelpa)))) + +(def-test! elpa-outdated-detection + (cl-letf (((symbol-function 'package-refresh-contents) (lambda (&rest _)))) + (let* ((doom--last-refresh (current-time)) + (package-alist + `((doom-dummy ,(-new-package 'doom-dummy '(20160405 1234))))) + (package-archive-contents + `((doom-dummy ,(-new-package 'doom-dummy '(20170405 1234))))) + (outdated (doom-package-outdated-p 'doom-dummy))) + (should outdated) + (should (equal outdated '(doom-dummy (20160405 1234) (20170405 1234))))))) + +;; TODO quelpa-outdated-detection + +(def-test! get-packages + (let ((quelpa-initialized-p t) + (doom-packages '((doom-dummy))) + (package-alist + `((doom-dummy nil) + (doom-dummy-dep nil))) + doom-core-packages) + (cl-letf (((symbol-function 'doom-initialize-packages) (lambda (&rest _)))) + (should (equal (doom-get-packages) '((doom-dummy))))))) + +(def-test! orphaned-packages + "Test `doom-get-orphaned-packages', which gets a list of packages that are +no longer enabled or depended on." + (let ((doom-packages '((doom-dummy))) + (package-alist + `((doom-dummy ,(-new-package 'doom-dummy '(20160405 1234) '((doom-dummy-dep (1 0))))) + (doom-dummy-unwanted ,(-new-package 'doom-dummy-unwanted '(20160601 1234))) + (doom-dummy-dep ,(-new-package 'doom-dummy-dep '(20160301 1234))))) + doom-core-packages) + (cl-letf (((symbol-function 'doom-initialize-packages) (lambda (&rest _)))) + (should (equal (doom-get-orphaned-packages) '(doom-dummy-unwanted)))))) + +(def-test! missing-packages + "Test `doom-get-missing-packages, which gets a list of enabled packages that +aren't installed." + (let ((doom-packages '((doom-dummy) (doom-dummy-installed))) + (package-alist `((doom-dummy-installed ,(-new-package 'doom-dummy-installed '(20160405 1234))))) + doom-core-packages) + (cl-letf (((symbol-function 'doom-initialize-packages) (lambda (&rest _)))) + (should (equal (doom-get-missing-packages) '((doom-dummy))))))) diff --git a/core/test/core-lib.el b/core/test/core-lib.el new file mode 100644 index 000000000..dc1aa1346 --- /dev/null +++ b/core/test/core-lib.el @@ -0,0 +1,81 @@ +;; -*- no-byte-compile: t; -*- +;;; core/test/core-lib.el + +;; `add-hook!' +(def-test! add-one-to-one-hook + (let (hooks) + (add-hook! 'hooks 'a-hook) + (should (equal hooks '(a-hook))))) + +(def-test! add-many-to-one-hook + (let (hooks) + (add-hook! 'hooks '(hook-a hook-b hook-c)) + (should (equal hooks '(hook-c hook-b hook-a))))) + +(def-test! add-one-to-many-hooks + (let (hooks-a hooks-b hooks-c) + (add-hook! '(hooks-a hooks-b hooks-c) 'a-hook) + (should (equal hooks-a '(a-hook))) + (should (equal hooks-b '(a-hook))) + (should (equal hooks-c '(a-hook))))) + +(def-test! add-many-to-many-hooks + (let (hooks-a hooks-b hooks-c) + (add-hook! '(hooks-a hooks-b hooks-c) '(hook-a hook-b hook-c)) + (should (equal hooks-a '(hook-c hook-b hook-a))) + (should (equal hooks-b '(hook-c hook-b hook-a))) + (should (equal hooks-c '(hook-c hook-b hook-a))))) + +(def-test! add-non-literal-hooks + (let (some-mode-hook) + (add-hook! some-mode 'a-hook) + (should (equal some-mode-hook '(a-hook))))) + +;; `remove-hook!' +(def-test! remove-hooks + (let ((hooks-a '(hook-c hook-b hook-a)) + (hooks-b '(hook-c hook-b hook-a)) + (hooks-c '(hook-c hook-b hook-a))) + (remove-hook! '(hooks-a hooks-b hooks-c) '(hook-a hook-b hook-c)) + (should (null hooks-a)) + (should (null hooks-b)) + (should (null hooks-c)))) + +(def-test! remove-hook-forms + (let (hooks) + (add-hook! 'hooks (message "Hello world")) + (should hooks) + (remove-hook! 'hooks (message "Hello world")) + (should (null hooks)))) + +;; `add-transient-hook!' +(def-test! transient-hooks + (let (hooks value) + (add-transient-hook! 'hooks (setq value t)) + (run-hooks 'hooks) + (should (eq value t)) + (should (null hooks)))) + +(def-test! transient-function + (let (value) + (add-transient-hook! #'ignore (setq value (not value))) + (ignore t) + (should (eq value t)) + ;; repeat to ensure it was only run once + (ignore t) + (should (eq value t)))) + +(def-test! unquote + (should (equal (doom-unquote '(quote (a b c))) '(a b c))) + ;; nested + (should (equal (doom-unquote '(quote (quote (a b c)))) '(a b c))) + ;; sub-quote + (should (equal (doom-unquote '(quote (a (quote b) c))) '(a (quote b) c)))) + +(def-test! enlist + (should (equal (doom-enlist 'a) '(a))) + (should (equal (doom-enlist '(a)) '(a)))) + + +;; TODO `associate!' +;; TODO `def-setting!' & `set!' diff --git a/test/init.test.el b/init.test.el similarity index 65% rename from test/init.test.el rename to init.test.el index 73a02cbb3..f3741e8cb 100644 --- a/test/init.test.el +++ b/init.test.el @@ -1,4 +1,4 @@ -;;; init.el +;;; init.test.el -- for automated unit tests -*- lexical-binding: t; -*- (require 'core (concat user-emacs-directory "core/core")) diff --git a/modules/feature/evil/test/autoload-files.el b/modules/feature/evil/test/autoload-files.el new file mode 100644 index 000000000..762e39fbe --- /dev/null +++ b/modules/feature/evil/test/autoload-files.el @@ -0,0 +1,46 @@ +;; -*- no-byte-compile: t; -*- +;;; feature/evil/test/autoload-files.el + +(defmacro -with-temp-files! (src dest &rest body) + "Run FORMS in the context of a temporary package setup (as in, it won't +affects your Emacs packages)." + (declare (indent 2) (doc-string 3)) + `(let ((it ,src) + (other ,dest)) + (with-temp-file it + (insert "Hello world")) + (unwind-protect + (progn + (should (file-exists-p it)) + (find-file-literally it) + (should (equal (buffer-string) "Hello world")) + (should (equal (buffer-file-name) it)) + (let ((inhibit-message (not doom-debug-mode))) + ,@body)) + (ignore-errors (delete-file it)) + ,(if dest `(ignore-errors (delete-file other)))))) + +;; +(def-test! move-this-file + ":mv" + (-with-temp-files! "/tmp/doom-buffer" "/tmp/doom-buffer-new" + (should-error (+evil:move-this-file it)) + (should (+evil:move-this-file other t)) + (should (file-exists-p other)) + (should (not (file-exists-p it))))) + +(def-test! copy-this-file + ":cp" + (-with-temp-files! "/tmp/doom-buffer-2" "/tmp/doom-buffer-2-new" + (should-error (+evil:copy-this-file it)) + (should (+evil:copy-this-file other t)) + (should (file-exists-p other)) + (should (file-exists-p it)))) + +(def-test! delete-this-file + ":rm" + (-with-temp-files! "/tmp/doom-buffer-3" nil + (should-error (+evil:delete-this-file "this-file-does-not-exist")) + (should (+evil:delete-this-file nil t)) + (should (not (file-exists-p it))))) + diff --git a/test/modules/feature/test-evil.el b/modules/feature/evil/test/evil.el similarity index 53% rename from test/modules/feature/test-evil.el rename to modules/feature/evil/test/evil.el index eacf00972..806c6beaa 100644 --- a/test/modules/feature/test-evil.el +++ b/modules/feature/evil/test/evil.el @@ -1,30 +1,9 @@ -;;; test/modules/feature/test-evil.el +;; -*- no-byte-compile: t; -*- +;;; feature/evil/test/evil.el -(require! :feature evil t) - -(defalias 'do-it '+evil*ex-replace-special-filenames) - -(defmacro do-files! (src dest &rest body) - (declare (indent defun)) - `(let ((it ,src) - (other ,dest)) - (with-temp-file it - (insert "Hello world")) - - (unwind-protect - (progn - (should (file-exists-p it)) - (find-file-literally it) - (should (equal (buffer-string) "Hello world")) - (should (equal (buffer-file-name) it)) - (let ((inhibit-message (not doom-debug-mode))) - ,@body)) - (ignore-errors (delete-file it)) - ,(if dest `(ignore-errors (delete-file other)))))) - -;; -(def-test-group! feature/evil - (ert-deftest custom-file-modifiers () +;; `+evil*ex-replace-special-filenames' +(def-test! file-modifiers + (cl-flet ((do-it #'+evil*ex-replace-special-filenames)) (let ((buffer-file-name "~/.emacs.d/test/modules/feature/test-evil.el") (default-directory "~/.emacs.d/test/modules/")) (should (equal (do-it "%") "feature/test-evil.el")) @@ -39,9 +18,10 @@ (should (equal (do-it "%:s?e?x?") "fxature/test-evil.el")) (should (equal (do-it "%:gs?e?x?") "fxaturx/txst-xvil.xl")) (should (equal (file-truename (do-it "%:p")) - (file-truename buffer-file-name))))) + (file-truename buffer-file-name)))))) - (ert-deftest custom-nested-file-modifiers () +(def-test! nested-file-modifiers + (cl-flet ((do-it #'+evil*ex-replace-special-filenames)) (let ((buffer-file-name "~/vim/src/version.c") (default-directory "~/vim/")) (should (equal (do-it "%:p") (expand-file-name "~/vim/src/version.c"))) @@ -54,9 +34,10 @@ (should (equal (do-it "%:p:t") "version.c")) (should (equal (do-it "%:r") "src/version")) (should (equal (do-it "%:p:r") (expand-file-name "~/vim/src/version"))) - (should (equal (do-it "%:t:r") "version")))) + (should (equal (do-it "%:t:r") "version"))))) - (ert-deftest custom-empty-file-modifiers () +(def-test! empty-file-modifiers + (cl-flet ((do-it #'+evil*ex-replace-special-filenames)) (let (buffer-file-name default-directory) (should (equal (do-it "%") "")) (should (equal (do-it "%:r") "")) @@ -67,24 +48,5 @@ (should (equal (do-it "%:~") "")) (should (equal (do-it "%:s?e?x?") "")) (should (equal (do-it "%:gs?e?x?") "")) - (should (equal (do-it "%:P") "")))) + (should (equal (do-it "%:P") ""))))) - (ert-deftest move-this-file () - (do-files! "/tmp/doom-buffer" "/tmp/doom-buffer-new" - (should-error (+evil:move-this-file it)) - (should (+evil:move-this-file other t)) - (should (file-exists-p other)) - (should (not (file-exists-p it))))) - - (ert-deftest copy-this-file () - (do-files! "/tmp/doom-buffer-2" "/tmp/doom-buffer-2-new" - (should-error (+evil:copy-this-file it)) - (should (+evil:copy-this-file other t)) - (should (file-exists-p other)) - (should (file-exists-p it)))) - - (ert-deftest delete-this-file () - (do-files! "/tmp/doom-buffer-3" nil - (should-error (+evil:delete-this-file "this-file-does-not-exist")) - (should (+evil:delete-this-file nil t)) - (should (not (file-exists-p it)))))) diff --git a/modules/tools/password-store/test/autoload-pass.el b/modules/tools/password-store/test/autoload-pass.el new file mode 100644 index 000000000..33d539259 --- /dev/null +++ b/modules/tools/password-store/test/autoload-pass.el @@ -0,0 +1,35 @@ +;; -*- no-byte-compile: t; -*- +;;; tools/password-store/test/autoload-pass.el + +(defmacro -with-passwords! (buffer-args &rest body) + (declare (indent defun)) + `(cl-letf + (((symbol-function 'auth-pass-parse-entry) + (lambda (entry) + (when (equal entry "fake/source") + '((secret . "defuse-account-gad") + ("login" . "HL2532-GANDI") + ("alt-login" . "hlissner") + ("email" . "henrik@lissner.net") + ("url" . "https://www.gandi.net/login")))))) + ,@body)) + +;; +(def-test! get-field + (-with-passwords! + (should (equal (+pass-get-field "fake/source" "login") + "HL2532-GANDI")) + (should (equal (+pass-get-field "fake/source" "email") + "henrik@lissner.net")) + (should (equal (+pass-get-field "fake/source" '("alt-login" "email")) + "hlissner")) + (should (equal (+pass-get-field "fake/source" '("username" "email")) + "henrik@lissner.net")) + (should-not (+pass-get-field "fake/source" '("x" "y" "z"))) + + (should-error (+pass-get-field "nonexistent/source" "login")))) + +(def-test! get-login + (-with-passwords! + (should (equal (+pass-get-user "fake/source") "HL2532-GANDI")) + (should (equal (+pass-get-secret "fake/source") "defuse-account-gad")))) diff --git a/test/core/autoload/test-buffers.el b/test/core/autoload/test-buffers.el deleted file mode 100644 index 3658b9f70..000000000 --- a/test/core/autoload/test-buffers.el +++ /dev/null @@ -1,95 +0,0 @@ -;;; test/core/autoload/test-buffers.el - -(defmacro with-temp-buffers! (buffer-args &rest body) - (declare (indent defun)) - (let (buffers) - (dolist (bsym buffer-args) - (push `(,bsym (get-buffer-create ,(symbol-name bsym))) - buffers)) - `(let* (,@buffers - (buffer-list (list ,@(reverse (mapcar #'car buffers))))) - ,@body - (mapc #'kill-buffer buffer-list)))) - -(def-test-group! core/autoload/buffers - (ert-deftest get-buffers () - (with-temp-buffers! (a b c) - (should (cl-every #'buffer-live-p buffer-list)) - (should (equal buffer-list (list a b c))) - (dolist (buf (list (cons a doom-emacs-dir) - (cons b doom-emacs-dir) - (cons c "/tmp/"))) - (with-current-buffer (car buf) - (setq-local default-directory (cdr buf)))) - (with-current-buffer a - ;; should produce all buffers - (let ((buffers (doom-buffer-list))) - (should (cl-every (lambda (x) (memq x buffers)) (list a b c)))) - ;; should produce only project buffers - (let ((buffers (doom-buffer-list t))) - (should (cl-every (lambda (x) (memq x buffers)) (list a b))) - (should-not (memq c buffers)))) - ;; If no project is available, just get all buffers - (with-current-buffer c - (let ((buffers (doom-buffer-list t))) - (should (cl-every (lambda (x) (memq x buffers)) (list a b c))))))) - - (ert-deftest get-real-buffers () - (with-temp-buffers! (a b c d) - (dolist (buf (list a b)) - (with-current-buffer buf (setq-local buffer-file-name "x"))) - (with-current-buffer c - (rename-buffer "*C*")) - (with-current-buffer d - (doom-popup-mode +1)) - (let ((buffers (doom-real-buffers-list buffer-list))) - (should (= (length buffers) 2)) - (should (cl-every (lambda (x) (memq x buffers)) (list a b))) - (should (cl-notany (lambda (x) (memq x buffers)) (list c d)))))) - - (ert-deftest kill-buffers () - (with-temp-buffers! (a b) - (doom-kill-buffer a) - (should-not (buffer-live-p a)) - ;; modified buffer - (with-current-buffer b - (set-buffer-modified-p t)) - (doom-kill-buffer b t) - (should-not (buffer-live-p a)))) - - (ert-deftest kill-buffer-then-show-real-buffer () - (with-temp-buffers! (a b c d) - (dolist (buf (list a b d)) - (with-current-buffer buf (setq-local buffer-file-name "x"))) - (should (cl-every #'buffer-live-p buffer-list)) - (switch-to-buffer a) - (should (eq (current-buffer) a)) - (should (eq (selected-window) (get-buffer-window a))) - (should (doom-kill-buffer a)) - (should (eq (current-buffer) b)) - (should (doom-kill-buffer)) - (should (eq (current-buffer) d)) - (doom/kill-this-buffer) - (should (eq (current-buffer) (doom-fallback-buffer))))) - - (ert-deftest matching-buffers () - (with-temp-buffers! (a b c) - (let ((buffers (doom-matching-buffers "^[ac]$"))) - (should (= 2 (length buffers))) - (should (cl-every #'bufferp buffers)) - (should (cl-every (lambda (x) (memq x buffers)) (list a c))) - (should (equal (reverse buffers) (doom-matching-buffers "^[ac]$" buffer-list)))))) - - (ert-deftest buffers-in-mode () - (with-temp-buffers! (a b c d e) - (dolist (buf (list a b)) - (with-current-buffer buf - (emacs-lisp-mode))) - (dolist (buf (list c d e)) - (with-current-buffer buf - (text-mode))) - (let ((el-buffers (doom-buffers-in-mode 'emacs-lisp-mode)) - (txt-buffers (doom-buffers-in-mode 'text-mode))) - (should (cl-every #'buffer-live-p (append el-buffers txt-buffers))) - (should (= 2 (length el-buffers))) - (should (= 3 (length txt-buffers))))))) diff --git a/test/core/autoload/test-debug.el b/test/core/autoload/test-debug.el deleted file mode 100644 index 64959a60b..000000000 --- a/test/core/autoload/test-debug.el +++ /dev/null @@ -1,19 +0,0 @@ -;;; test/core/autoload/test-debug.el - -(def-test-group! core/autoload/debug - (ert-deftest what-face () - (with-temp-buffer - (insert (propertize "Hello " 'face 'font-lock-keyword-face)) - (insert "world") - - (should (equal (doom/what-face (point-min)) '((font-lock-keyword-face) ()))) - (should-not (doom/what-face (point-max))))) - - (ert-deftest what-face-overlays () - (with-temp-buffer - (insert "Hello world") - (let ((ov (make-overlay 1 6))) - (overlay-put ov 'face 'font-lock-keyword-face)) - - (should (equal (doom/what-face (point-min)) '(() (font-lock-keyword-face)))) - (should-not (doom/what-face (point-max)))))) diff --git a/test/core/autoload/test-message.el b/test/core/autoload/test-message.el deleted file mode 100644 index d8da5fade..000000000 --- a/test/core/autoload/test-message.el +++ /dev/null @@ -1,41 +0,0 @@ -;;; test/core/autoload/test-message.el - -(def-test-group! core/autoload/message - ;; ansi messages - (ert-deftest ansi-format () - (let ((noninteractive t)) - (should (equal (format! "Hello %s" "World") - "Hello World")) - (should (equal (format! (red "Hello %s" "World")) - "Hello World")) - (should (equal (format! (green "Hello %s" "World")) - (format "\e[%dm%s\e[0m" - (cdr (assq 'green doom-message-fg)) - "Hello World"))) - (should (equal (format! (on-red "Hello %s" "World")) - (format "\e[%dm%s\e[0m" - (cdr (assq 'on-red doom-message-bg)) - "Hello World"))) - (should (equal (format! (bold "Hello %s" "World")) - (format "\e[%dm%s\e[0m" - (cdr (assq 'bold doom-message-fx)) - "Hello World"))))) - - (ert-deftest ansi-format-nested () - (let ((noninteractive t)) - (should (equal (format! (bold (red "Hello %s" "World"))) - (format "\e[%dm%s\e[0m" 1 - (format "\e[%dm%s\e[0m" 31 "Hello World")))) - (should (equal (format! (on-red (bold "Hello %s" "World"))) - (format "\e[%dm%s\e[0m" 41 - (format "\e[%dm%s\e[0m" 1 "Hello World")))) - (should (equal (format! (dark (white "Hello %s" "World"))) - (format "\e[%dm%s\e[0m" 2 - (format "\e[%dm%s\e[0m" 37 "Hello World")))))) - - (ert-deftest ansi-format-apply () - (let ((noninteractive t)) - (should (equal (format! (color 'red "Hello %s" "World")) - (format! (red "Hello %s" "World")))) - (should (equal (format! (color (if nil 'red 'blue) "Hello %s" "World")) - (format! (blue "Hello %s" "World"))))))) diff --git a/test/core/autoload/test-package.el b/test/core/autoload/test-package.el deleted file mode 100644 index a1b3cde18..000000000 --- a/test/core/autoload/test-package.el +++ /dev/null @@ -1,79 +0,0 @@ -;;; test/core/autoload/test-package.el - -(defun test-package-new (name version &optional reqs) - (package-desc-create :name name :version version :reqs reqs)) - -;; TODO -(defmacro with-temp-packages! (&rest forms) - "Run FORMS in the context of a temporary package setup (as in, it won't -affects your Emacs packages)." - `(let* ((doom-local-dir ,(expand-file-name "test/.local/" doom-emacs-dir)) - (doom-packages-dir (concat doom-local-dir "packages/")) - (doom-etc-dir (concat doom-local-dir "etc/")) - (doom-cache-dir (concat doom-local-dir "cache/")) - (package-user-dir (expand-file-name "elpa" doom-packages-dir)) - package-alist - package-archive-contents - package-initialize) - (package-initialize) - ,@forms)) - - -;; -;; Tests -;; - -(def-test-group! core/autoload/package - (ert-deftest backend-detection () - "TODO" - (let ((package-alist `((doom-dummy ,(test-package-new 'doom-dummy '(20160405 1234))))) - (quelpa-cache '((doom-quelpa-dummy :fetcher github :repo "hlissner/does-not-exist"))) - (quelpa-initialized-p t)) - (should (eq (doom-package-backend 'doom-dummy) 'elpa)) - (should (eq (doom-package-backend 'doom-quelpa-dummy) 'quelpa)))) - - (ert-deftest elpa-outdated-detection () - "TODO" - (cl-letf (((symbol-function 'package-refresh-contents) (lambda (&rest _)))) - (let* ((doom--last-refresh (current-time)) - (package-alist - `((doom-dummy ,(test-package-new 'doom-dummy '(20160405 1234))))) - (package-archive-contents - `((doom-dummy ,(test-package-new 'doom-dummy '(20170405 1234))))) - (outdated (doom-package-outdated-p 'doom-dummy))) - (should outdated) - (should (equal outdated '(doom-dummy (20160405 1234) (20170405 1234))))))) - - ;; TODO quelpa-outdated-detection - - (ert-deftest get-packages () - "TODO" - (let ((quelpa-initialized-p t) - (doom-packages '((doom-dummy))) - (package-alist - `((doom-dummy nil) - (doom-dummy-dep nil))) - doom-core-packages) - (cl-letf (((symbol-function 'doom-initialize-packages) (lambda (&rest _)))) - (should (equal (doom-get-packages) '((doom-dummy))))))) - - (ert-deftest orphaned-packages () - "Test `doom-get-orphaned-packages', which gets a list of packages that are -no longer enabled or depended on." - (let ((doom-packages '((doom-dummy))) - (package-alist - `((doom-dummy ,(test-package-new 'doom-dummy '(20160405 1234) '((doom-dummy-dep (1 0))))) - (doom-dummy-unwanted ,(test-package-new 'doom-dummy-unwanted '(20160601 1234))) - (doom-dummy-dep ,(test-package-new 'doom-dummy-dep '(20160301 1234))))) - doom-core-packages) - (cl-letf (((symbol-function 'doom-initialize-packages) (lambda (&rest _)))) - (should (equal (doom-get-orphaned-packages) '(doom-dummy-unwanted)))))) - - (ert-deftest missing-packages () - "Test `doom-get-missing-packages, which gets a list of enabled packages that -aren't installed." - (let ((doom-packages '((doom-dummy) (doom-dummy-installed))) - (package-alist `((doom-dummy-installed ,(test-package-new 'doom-dummy-installed '(20160405 1234))))) - doom-core-packages) - (cl-letf (((symbol-function 'doom-initialize-packages) (lambda (&rest _)))) - (should (equal (doom-get-missing-packages) '((doom-dummy)))))))) diff --git a/test/core/test-core-lib.el b/test/core/test-core-lib.el deleted file mode 100644 index 8b4efdad1..000000000 --- a/test/core/test-core-lib.el +++ /dev/null @@ -1,72 +0,0 @@ -;;; ../test/test-core-lib.el - -(def-test-group! core-lib - ;; `add-hook!' - (ert-deftest add-one-to-one-hook () - (let (hooks) - (add-hook! 'hooks 'a-hook) - (should (equal hooks '(a-hook))))) - - (ert-deftest add-many-to-one-hook () - (let (hooks) - (add-hook! 'hooks '(hook-a hook-b hook-c)) - (should (equal hooks '(hook-c hook-b hook-a))))) - - (ert-deftest add-one-to-many-hooks () - (let (hooks-a hooks-b hooks-c) - (add-hook! '(hooks-a hooks-b hooks-c) 'a-hook) - (should (equal hooks-a '(a-hook))) - (should (equal hooks-b '(a-hook))) - (should (equal hooks-c '(a-hook))))) - - (ert-deftest add-many-to-many-hooks () - (let (hooks-a hooks-b hooks-c) - (add-hook! '(hooks-a hooks-b hooks-c) '(hook-a hook-b hook-c)) - (should (equal hooks-a '(hook-c hook-b hook-a))) - (should (equal hooks-b '(hook-c hook-b hook-a))) - (should (equal hooks-c '(hook-c hook-b hook-a))))) - - (ert-deftest add-non-literal-hooks () - (let (some-mode-hook) - (add-hook! some-mode 'a-hook) - (should (equal some-mode-hook '(a-hook))))) - - ;; `remove-hook!' - (ert-deftest remove-hooks () - (let ((hooks-a '(hook-c hook-b hook-a)) - (hooks-b '(hook-c hook-b hook-a)) - (hooks-c '(hook-c hook-b hook-a))) - (remove-hook! '(hooks-a hooks-b hooks-c) '(hook-a hook-b hook-c)) - (should (null hooks-a)) - (should (null hooks-b)) - (should (null hooks-c)))) - - (ert-deftest remove-hook-forms () - (let (hooks) - (add-hook! 'hooks (message "Hello world")) - (should hooks) - (remove-hook! 'hooks (message "Hello world")) - (should (null hooks)))) - - ;; `add-transient-hook!' - (ert-deftest transient-hooks () - (let (hooks value) - (add-transient-hook! 'hooks (setq value t)) - (run-hooks 'hooks) - (should (eq value t)) - (should (null hooks)))) - - (ert-deftest transient-function () - (let (value) - (add-transient-hook! #'ignore (setq value (not value))) - (ignore t) - (should (eq value t)) - ;; repeat to ensure it was only run once - (ignore t) - (should (eq value t)))) - - ;; TODO `associate!' - - ;; TODO `def-setting!' & `set!' - - ) diff --git a/test/modules/tools/test-password-store.el b/test/modules/tools/test-password-store.el deleted file mode 100644 index a1222c365..000000000 --- a/test/modules/tools/test-password-store.el +++ /dev/null @@ -1,23 +0,0 @@ -;;; test/modules/feature/test-password-store.el - -(require! :tools password-store t) - -;; -(def-test-group! tools/password-store - (ert-deftest get-field () - (let ((data `((secret . "defuse-account-gad") - ("login" . "HL2532-GANDI") - ("alt-login" . "hlissner") - ("email" . "henrik@lissner.net") - ("url" . "https://www.gandi.net/login")))) - (should (equal (+pass-get-field data "login") - "HL2532-GANDI")) - (should (equal (+pass-get-field data "email") - "henrik@lissner.net")) - (should (equal (+pass-get-field data '("alt-login" "email")) - "hlissner")) - (should (equal (+pass-get-field data '("username" "email")) - "henrik@lissner.net")) - (should-not (+pass-get-field data '("x" "y" "z")))) - - (should-error (+pass-get-field nil nil)))) diff --git a/test/run.el b/test/run.el deleted file mode 100644 index a12170082..000000000 --- a/test/run.el +++ /dev/null @@ -1,6 +0,0 @@ -;;; ../test/setup.el - -(setq-default debug-on-error nil) - -(run-hooks 'emacs-startup-hook) -(ert-run-tests-batch-and-exit) diff --git a/test/test-basic.el b/test/test-basic.el deleted file mode 100644 index 5be1826ad..000000000 --- a/test/test-basic.el +++ /dev/null @@ -1,4 +0,0 @@ -;;; ../test/test-basic.el - -(ert-deftest doom-basic () - (should t))