]> git.eshelyaron.com Git - emacs.git/commitdiff
New convenience macros ert-with-temp-(file|directory)
authorStefan Kangas <stefan@marxist.se>
Sat, 6 Nov 2021 12:50:46 +0000 (13:50 +0100)
committerStefan Kangas <stefan@marxist.se>
Sat, 6 Nov 2021 18:16:05 +0000 (19:16 +0100)
* lisp/emacs-lisp/ert-x.el
(ert-with-temp-file)
(ert-with-temp-directory): New macros.
* test/lisp/emacs-lisp/ert-x-tests.el
(ert-x-tests-with-temp-directory)
ert-x-tests-with-temp-directory/text-signals-error
(ert-x-tests-with-temp-file)
(ert-x-tests-with-temp-file/handle-error)
(ert-x-tests-with-temp-file/prefix-and-suffix-kwarg)
(ert-x-tests-with-temp-file/text-kwarg)
(ert-x-tests-with-temp-file/unknown-kwargs-signals-error): New tests.

lisp/emacs-lisp/ert-x.el
test/lisp/emacs-lisp/ert-x-tests.el

index a492ef5093fca0a1a61f86e915ff02b11deea7d1..2af956c8a6da8dc0ea5309fa1e1616b22b820065 100644 (file)
@@ -386,6 +386,78 @@ A resource file is defined as any file placed in the resource
 directory as returned by `ert-resource-directory'."
   `(expand-file-name ,file (ert-resource-directory)))
 
+(defvar ert-temp-file-prefix "emacs-test-"
+  "Suffix used by `ert-with-temp-file' and `ert-with-temp-directory'.")
+
+(defvar ert-temp-file-suffix nil
+  "Prefix used by `ert-with-temp-file' and `ert-with-temp-directory'.")
+
+(defmacro ert-with-temp-file (name &rest body)
+  "Bind NAME to the name of a new temporary file and evaluate BODY.
+Delete the temporary file after BODY exits normally or
+non-locally.  NAME will be bound to the file name of the temporary
+file.
+
+The following keyword arguments are supported:
+
+:prefix STRING  If non-nil, pass STRING to `make-temp-file' as
+                the PREFIX argument.  Otherwise, use the value
+                of `ert-temp-file-prefix'.
+
+:suffix STRING  If non-nil, pass STRING to `make-temp-file' as
+                the SUFFIX argument.  Otherwise, use the value
+                of `ert-temp-file-suffix'.
+
+:text STRING    If non-nil, pass STRING to `make-temp-file' as
+                the TEXT argument.
+
+See also `ert-with-temp-directory'."
+  (declare (indent 1) (debug (symbolp body)))
+  (cl-check-type name symbol)
+  (let (keyw prefix suffix directory text extra-keywords)
+    (while (keywordp (setq keyw (car body)))
+      (setq body (cdr body))
+      (pcase keyw
+        (:prefix (setq prefix (pop body)))
+        (:suffix (setq suffix (pop body)))
+        (:directory (setq directory (pop body)))
+        (:text (setq text (pop body)))
+        (_ (push keyw extra-keywords) (pop body))))
+    (when extra-keywords
+      (error "Invalid keywords: %s" (mapconcat #'symbol-name extra-keywords " ")))
+    (let ((temp-file (make-symbol "temp-file"))
+          (prefix (or prefix ert-temp-file-prefix))
+          (suffix (or suffix ert-temp-file-suffix)))
+      `(let* ((,temp-file (,(if directory 'file-name-as-directory 'identity)
+                           (make-temp-file ,prefix ,directory ,suffix ,text)))
+              (,name ,temp-file))
+         (unwind-protect
+             (progn ,@body)
+           (ignore-errors
+             ,(if directory
+                  `(delete-directory ,temp-file :recursive)
+                `(delete-file ,temp-file))))))))
+
+(defmacro ert-with-temp-directory (name &rest body)
+  "Bind NAME to the name of a new temporary directory and evaluate BODY.
+Delete the temporary directory after BODY exits normally or
+non-locally.
+
+NAME is bound to the directory name, not the directory file
+name.  (In other words, it will end with the directory delimiter;
+on Unix-like systems, it will end with \"/\".)
+
+The same keyword arguments are supported as in
+`ert-with-temp-file' (which see), except for :text."
+  (declare (indent 1) (debug (symbolp body)))
+  (let ((tail body) keyw)
+    (while (keywordp (setq keyw (car tail)))
+      (setq tail (cddr tail))
+      (pcase keyw (:text (error "Invalid keyword for directory: :text")))))
+  `(ert-with-temp-file ,name
+     :directory t
+     ,@body))
+
 (provide 'ert-x)
 
 ;;; ert-x.el ends here
index 1784934acb3fb096a237ed0e4ed8d243c01170a1..1eed5bb7b94d78196b8fccf62c7bb44eb7f9e19a 100644 (file)
@@ -271,6 +271,52 @@ desired effect."
     (cl-loop for x in '(0 1 2 3 4 t) do
              (should (equal (c x) (lisp x))))))
 
+(ert-deftest ert-x-tests-with-temp-file ()
+  (let (saved)
+    (ert-with-temp-file fil
+      (setq saved fil)
+      (should (file-exists-p fil))
+      (should (file-regular-p fil)))
+    (should-not (file-exists-p saved))))
+
+(ert-deftest ert-x-tests-with-temp-file/handle-error ()
+  (let (saved)
+    (ignore-errors
+      (ert-with-temp-file fil
+        (setq saved fil)
+        (error "foo")))
+    (should-not (file-exists-p saved))))
+
+(ert-deftest ert-x-tests-with-temp-file/prefix-and-suffix-kwarg ()
+  (ert-with-temp-file fil
+    :prefix "foo"
+    :suffix "bar"
+    (should (string-match "foo.*bar" fil))))
+
+(ert-deftest ert-x-tests-with-temp-file/text-kwarg ()
+  (ert-with-temp-file fil
+    :text "foobar3"
+    (let ((buf (find-file-noselect fil)))
+      (unwind-protect
+          (with-current-buffer buf
+            (should (equal (buffer-string) "foobar3")))
+        (kill-buffer buf)))))
+
+(ert-deftest ert-x-tests-with-temp-file/unknown-kwarg-signals-error ()
+  (should-error
+   (ert-with-temp-file fil :foo "foo" nil)))
+
+(ert-deftest ert-x-tests-with-temp-directory ()
+  (let (saved)
+    (ert-with-temp-directory dir
+      (setq saved dir)
+      (should (file-exists-p dir))
+      (should (file-directory-p dir)))
+    (should-not (file-exists-p saved))))
+
+(ert-deftest ert-x-tests-with-temp-directory/text-signals-error ()
+  (should-error
+   (ert-with-temp-directory dir :text "foo" nil)))
 
 (provide 'ert-x-tests)