]> git.eshelyaron.com Git - emacs.git/commitdiff
Port Eshell tests to Android
authorPo Lu <luangruo@yahoo.com>
Wed, 26 Feb 2025 08:03:12 +0000 (16:03 +0800)
committerEshel Yaron <me@eshelyaron.com>
Fri, 28 Feb 2025 11:17:16 +0000 (12:17 +0100)
* test/infra/android/test-controller.el (ats-run-test): Run
tests in a temp buffer.

* test/lisp/eshell/em-alias-tests.el (ert, em-alias)
(eshell-tests-helpers):

* test/lisp/eshell/em-basic-tests.el (em-basic)
(eshell-tests-helpers):

* test/lisp/eshell/em-cmpl-tests.el (em-unix)
(eshell-tests-helpers):

* test/lisp/eshell/em-dirs-tests.el (em-dirs)
(eshell-tests-helpers):

* test/lisp/eshell/em-extpipe-tests.el (ert-x)
(eshell-tests-helpers):

* test/lisp/eshell/em-glob-tests.el (ert, eshell-tests-helpers):

* test/lisp/eshell/em-hist-tests.el (eshell)
(eshell-tests-helpers):

* test/lisp/eshell/em-pred-tests.el (em-pred)
(eshell-tests-helpers):

* test/lisp/eshell/em-prompt-tests.el (em-prompt)
(eshell-tests-helpers):

* test/lisp/eshell/em-script-tests.el (em-script)
(eshell-tests-helpers):

* test/lisp/eshell/em-unix-tests.el (ert-x)
(eshell-tests-helpers):

* test/lisp/eshell/esh-arg-tests.el (eshell)
(eshell-tests-helpers):

* test/lisp/eshell/esh-cmd-tests.el (eshell)
(eshell-tests-helpers):

* test/lisp/eshell/esh-ext-tests.el (eshell)
(eshell-tests-helpers):

* test/lisp/eshell/esh-io-tests.el (eshell)
(eshell-tests-helpers):

* test/lisp/eshell/esh-mode-tests.el (em-prompt)
(eshell-tests-helpers):

* test/lisp/eshell/esh-proc-tests.el (em-prompt)
(eshell-tests-helpers):

* test/lisp/eshell/esh-util-tests.el (esh-util)
(eshell-tests-helpers):

* test/lisp/eshell/esh-var-tests.el (eshell)
(eshell-tests-helpers):

* test/lisp/eshell/eshell-tests.el (esh-mode)
(eshell-tests-helpers): Load `eshell-tests-helpers' from the
resource directory.

* test/lisp/eshell/resources/eshell-tests-helpers.el: Move from
`test/lisp/eshell'.

(cherry picked from commit 3e496fc31746517440285c2cd9f2b4a09c227d7b)

23 files changed:
test/infra/android/test-controller.el
test/lisp/eshell/em-alias-tests.el
test/lisp/eshell/em-basic-tests.el
test/lisp/eshell/em-cmpl-tests.el
test/lisp/eshell/em-dirs-tests.el
test/lisp/eshell/em-extpipe-tests.el
test/lisp/eshell/em-glob-tests.el
test/lisp/eshell/em-hist-tests.el
test/lisp/eshell/em-pred-tests.el
test/lisp/eshell/em-prompt-tests.el
test/lisp/eshell/em-script-tests.el
test/lisp/eshell/em-unix-tests.el
test/lisp/eshell/esh-arg-tests.el
test/lisp/eshell/esh-cmd-tests.el
test/lisp/eshell/esh-ext-tests.el
test/lisp/eshell/esh-io-tests.el
test/lisp/eshell/esh-mode-tests.el
test/lisp/eshell/esh-proc-tests.el
test/lisp/eshell/esh-util-tests.el
test/lisp/eshell/esh-var-tests.el
test/lisp/eshell/eshell-tests-helpers.el [deleted file]
test/lisp/eshell/eshell-tests.el
test/lisp/eshell/resources/eshell-tests-helpers.el [new file with mode: 0644]

index 89b9b93f7b1d4ff6f29f8a15fe9bd32fc424ef02..d318c9a0d4b39a3a245657a1b1d621cc750329d0 100644 (file)
@@ -2442,7 +2442,11 @@ Display the output of the tests executed in a buffer."
                                        (with-current-buffer temp-buffer
                                          (insert message "\n")))))
                                (let ((noninteractive t))
-                                 (ert-run-tests-batch ',selector))
+                                 ;; Prevent activation of the mark and
+                                 ;; other actions taken by the tests
+                                 ;; from affecting the test buffer.
+                                 (with-temp-buffer
+                                   (ert-run-tests-batch ',selector)))
                                (insert "=== Test execution complete ===\n")
                                (buffer-substring-no-properties
                                 (point-min) (point-max)))))))
index 2386e04bbd33fdc9a60bf904e2a0c4d3f7b6cf48..51af80af14800a6c81395cabef5571f76fb35e1a 100644 (file)
 ;;; Code:
 
 (require 'ert)
+(require 'ert-x)
 (require 'esh-mode)
 (require 'eshell)
 (require 'em-alias)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 ;;; Tests:
 
 (ert-deftest em-alias-test/simple-alias ()
index ee2a624cf6fc185431179f81a7c326d20dd03e95..cd141dc440e75eb94955ded86e64f043b20190bb 100644 (file)
 
 (require 'ert)
 (require 'em-basic)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 ;;; Tests:
 
index 5b4fc5b48b1e4d9fc0c8e0e3ce079f77cbc3fc0e..f7f8958d8165b86dc4b5ef1d2f90d731419810c2 100644 (file)
 (require 'em-hist)
 (require 'em-tramp)
 (require 'em-unix)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 (defvar eshell-test-value nil)
 
index ae3c19aa022eca33cb97bef239dad61ae4bbf50a..a3e2ad7287c88682dd20d6ebaaf0548f0ce4ccdb 100644 (file)
 (require 'esh-mode)
 (require 'eshell)
 (require 'em-dirs)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 ;;; Tests:
 
 \f
index ed7ed2a35b83f6911fd1a78bf93bd494dff7c1ce..b2c552563414c7f661eca29529ef5f28061f3e39 100644 (file)
 (require 'cl-lib)
 (require 'ert)
 (require 'ert-x)
+(require 'ert-x)
 (require 'em-extpipe)
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 (defmacro em-extpipe-tests--deftest (name input &rest body)
   (declare (indent 2))
index 4bc32848518b3146546514303cbe967dbf7c2ae8..fd5ef537a0b212a4e7e4ff513f02dc223888e944 100644 (file)
 
 (require 'tramp)
 (require 'ert)
+(require 'ert-x)
 (require 'em-glob)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 (defvar eshell-prefer-lisp-functions)
 
index f0bb4dd16c3b27ee0eca1106718de55409788538..6288ae071dc7d891aa22c4dcf05837cb020be1aa 100644 (file)
 (require 'ert-x)
 (require 'em-hist)
 (require 'eshell)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 (cl-defun em-hist-test/check-history-file (file-name expected &optional
                                                      (expected-ring t))
index a050c6426e91fb61fb0823b33656a07fa483add5..05ee5d4c4c3a0b4651307d1f501a20b07b90d03d 100644 (file)
 (require 'eshell)
 (require 'em-glob)
 (require 'em-pred)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 (defvar eshell-test-value nil)
 
index 62ad76f644bdab401142ca202ac5de991ca79c23..73cd6b144784bcd5ac8f43e2e43bc80bf0f893af 100644 (file)
 (require 'ert)
 (require 'eshell)
 (require 'em-prompt)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 (defmacro em-prompt-test--with-multiline (&rest body)
   "Execute BODY with a multiline Eshell prompt."
index 3259022957bf6332d5db4135d59aa5d844428f84..01dc5fd9a72fd117265ad1cfe9c61a90cf5a5306 100644 (file)
 (require 'esh-mode)
 (require 'eshell)
 (require 'em-script)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 (defvar eshell-execute-file-output)
 
index 59cd0034507d5a75cfda0fa0cbb0f1b455042644..b8969c5568a3ccac5ce813aa06462fabc1704ca6 100644 (file)
@@ -30,8 +30,9 @@
   (defvar this-directory (file-name-directory
                           (or load-file-name default-directory))))
 
+(require 'ert-x)
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers" this-directory))
+         (ert-resource-file "eshell-tests-helpers"))
 
 ;;; Tests:
 
index f498cf6674cbc5b16a5556c8f5c720139013383a..4c34711ec2e9069e8658b25f5566b282a7678c9a 100644 (file)
 (require 'ert)
 (require 'esh-mode)
 (require 'eshell)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 (defvar eshell-test-value nil)
 
index 7c04749e7eceb5a1355d953b28cf9823e604de51..25e6c0fda7c441777e62327f74eb2e2027272b48 100644 (file)
 (require 'ert)
 (require 'esh-mode)
 (require 'eshell)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 (defvar eshell-test-value nil)
 
index 696e679ccec51613c261f445e7728a260ebd0826..c6f5c48ae3ec7ea7eb2c6712696682665508985a 100644 (file)
 (require 'esh-mode)
 (require 'esh-ext)
 (require 'eshell)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 ;;; Tests:
 
index 0b25ad812fa29ae06e6bc7bd0fdc45d3d5e4ef42..d95b52297c738a2c375845a1f580c3856f0568d6 100644 (file)
 (require 'ert-x)
 (require 'esh-mode)
 (require 'eshell)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 (defvar eshell-test-value nil)
 
index 052f62d6b9bed603a0984b9118276222b8174def..b80230293698e5beaf972978270f62e754780255 100644 (file)
 (require 'eshell)
 (require 'em-banner)
 (require 'em-prompt)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 ;;; Tests:
 
index 16f8d82e976aa11d2dae575597787a9f9d8d4995..2ef8b9d7536862ef3a7fdbc6dad8649854a66f74 100644 (file)
 (require 'esh-mode)
 (require 'eshell)
 (require 'em-prompt)                    ; For `eshell-previous-prompt'
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 (defvar esh-proc-test--output-cmd
   (concat "sh -c '"
index 6967dbcf0125abc7ef34f0ff65f19f04c18d41c8..39fc6288110562fd2a4c15701dcadc0255023602 100644 (file)
 (require 'tramp)
 (require 'ert)
 (require 'esh-util)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 ;;; Tests:
 
index 153f8418153dcce998d135fb2330f81e1d5600cc..20575d93407d06bfab66fd64a110578c9c1e5c12 100644 (file)
 (require 'esh-mode)
 (require 'esh-var)
 (require 'eshell)
+(require 'ert-x)
 
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 (defvar eshell-test-value nil)
 (defvar eshell-test-begin nil)
diff --git a/test/lisp/eshell/eshell-tests-helpers.el b/test/lisp/eshell/eshell-tests-helpers.el
deleted file mode 100644 (file)
index 870e199..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-;;; eshell-tests-helpers.el --- Eshell test suite helpers  -*- lexical-binding:t -*-
-
-;; Copyright (C) 1999-2025 Free Software Foundation, Inc.
-
-;; Author: John Wiegley <johnw@gnu.org>
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Eshell test suite helpers.
-
-;;; Code:
-
-(require 'ert)
-(require 'ert-x)
-(require 'esh-mode)
-(require 'eshell)
-
-(defvar eshell-aliases-file nil)
-(defvar eshell-command-aliases-list nil)
-(defvar eshell-history-file-name nil)
-(defvar eshell-last-dir-ring-file-name nil)
-
-(defvar eshell-test--max-wait-time 5
-  "The maximum amount of time to wait for a condition to resolve, in seconds.
-See `eshell-wait-for'.")
-
-(defun eshell-tests-remote-accessible-p ()
-  "Return if a test involving remote files can proceed.
-If using this function, be sure to load `tramp' near the
-beginning of the test file."
-  (ignore-errors
-    (and
-     (file-remote-p ert-remote-temporary-file-directory)
-     (file-directory-p ert-remote-temporary-file-directory)
-     (file-writable-p ert-remote-temporary-file-directory))))
-
-(defmacro with-temp-eshell-settings (&rest body)
-  "Configure Eshell to leave no trace behind, and then evaluate BODY."
-  (declare (indent 0))
-  `(ert-with-temp-directory eshell-directory-name
-     (let (;; We want no history file, so prevent Eshell from falling
-           ;; back on $HISTFILE.
-           (process-environment (cons "HISTFILE" process-environment))
-           ;; Enable process debug instrumentation.  We may be able to
-           ;; remove this eventually once we're confident that all the
-           ;; process bugs have been worked out.  (At that point, we can
-           ;; just enable this selectively when needed.)  See also
-           ;; `eshell-test-command-result' below.
-           (eshell-debug-command (cons 'process eshell-debug-command))
-           (eshell-aliases-file nil)
-           (eshell-command-aliases-list nil)
-           (eshell-history-file-name nil)
-           (eshell-last-dir-ring-file-name nil)
-           (eshell-module-loading-messages nil))
-       ,@body)))
-
-(defmacro with-temp-eshell (&rest body)
-  "Evaluate BODY in a temporary Eshell buffer."
-  (declare (indent 0))
-  `(save-current-buffer
-     (with-temp-eshell-settings
-       (let ((eshell-buffer (eshell t)))
-         (unwind-protect
-             (with-current-buffer eshell-buffer
-               ,@body)
-           (let (kill-buffer-query-functions)
-             (kill-buffer eshell-buffer)))))))
-
-(defmacro eshell-with-temp-buffer (bufname text &rest body)
-  "Create a temporary buffer containing TEXT and evaluate BODY there.
-BUFNAME will be set to the name of the temporary buffer."
-  (declare (indent 2))
-  `(with-temp-buffer
-     (insert ,text)
-     (rename-buffer "eshell-temp-buffer" t)
-     (let ((,bufname (buffer-name)))
-       ,@body)))
-
-(defun eshell-wait-for (predicate &optional message)
-  "Wait until PREDICATE returns non-nil.
-If this takes longer than `eshell-test--max-wait-time', raise an
-error.  MESSAGE is an optional message to use if this times out."
-  (let ((start (current-time))
-        (message (or message "timed out waiting for condition")))
-    (while (not (funcall predicate))
-      (when (> (float-time (time-since start))
-               eshell-test--max-wait-time)
-        (error message))
-      (sit-for 0.1))))
-
-(defun eshell-wait-for-subprocess (&optional all)
-  "Wait until there is no interactive subprocess running in Eshell.
-If ALL is non-nil, wait until there are no Eshell subprocesses at
-all running.
-
-If this takes longer than `eshell-test--max-wait-time',
-raise an error."
-  (eshell-wait-for
-   (lambda ()
-     (not (if all eshell-process-list (eshell-interactive-process-p))))))
-
-(defun eshell-get-debug-logs ()
-  "Get debug command logs for displaying on test failures."
-  (when (get-buffer eshell-debug-command-buffer)
-    (let ((separator (make-string 40 ?-)))
-      (with-current-buffer eshell-debug-command-buffer
-        (string-replace "\f" separator (buffer-string))))))
-
-(defun eshell-insert-command (command &optional func)
-  "Insert a COMMAND at the end of the buffer.
-After inserting, call FUNC.  If FUNC is nil, instead call
-`eshell-send-input'."
-  (goto-char eshell-last-output-end)
-  (insert-and-inherit command)
-  (funcall (or func 'eshell-send-input)))
-
-(defun eshell-last-input ()
-  "Return the input of the last Eshell command."
-  (buffer-substring-no-properties
-   eshell-last-input-start eshell-last-input-end))
-
-(defun eshell-last-output ()
-  "Return the output of the last Eshell command."
-  (buffer-substring-no-properties
-   (eshell-beginning-of-output) (eshell-end-of-output)))
-
-(defun eshell-test-file-string (file)
-  "Return the contents of FILE as a string."
-  (with-temp-buffer
-    (insert-file-contents file)
-    (buffer-string)))
-
-(defun eshell-match-output (regexp)
-  "Test whether the output of the last command matches REGEXP."
-  (string-match-p regexp (eshell-last-output)))
-
-(defun eshell-match-output--explainer (regexp)
-  "Explain the result of `eshell-match-output'."
-  `(mismatched-output
-    (command ,(eshell-last-input))
-    (output ,(eshell-last-output))
-    (regexp ,regexp)))
-
-(put 'eshell-match-output 'ert-explainer #'eshell-match-output--explainer)
-
-(defun eshell-match-command-output (command regexp &optional func
-                                            ignore-errors)
-  "Insert a COMMAND at the end of the buffer and match the output with REGEXP.
-FUNC is the function to call after inserting the text (see
-`eshell-insert-command').
-
-If IGNORE-ERRORS is non-nil, ignore any errors signaled when
-inserting the command."
-  (ert-info (#'eshell-get-debug-logs :prefix "Command logs: ")
-    (let ((debug-on-error (and (not ignore-errors) debug-on-error)))
-      (eshell-insert-command command func))
-    (eshell-wait-for-subprocess)
-    (should (eshell-match-output regexp))))
-
-(defvar eshell-history-file-name)
-
-(defun eshell-test-command-result (command)
-  "Like `eshell-command-result', but not using HOME."
-  (ert-with-temp-directory eshell-directory-name
-    (let ((eshell-history-file-name nil)
-          ;; Enable process debug instrumentation.  See
-          ;; `with-temp-eshell' above.
-          (eshell-debug-command (cons 'process eshell-debug-command)))
-      (eshell-command-result command))))
-
-(defun eshell-command-result--equal (_command actual expected)
-  "Compare the ACTUAL result of a COMMAND with its EXPECTED value."
-  (equal actual expected))
-
-(defun eshell-command-result--equal-explainer (command actual expected)
-  "Explain the result of `eshell-command-result--equal'."
-  `(nonequal-result
-    (command ,command)
-    (result ,actual)
-    (expected ,expected)))
-
-(put 'eshell-command-result--equal 'ert-explainer
-     #'eshell-command-result--equal-explainer)
-
-(defun eshell-command-result-equal (command result)
-  "Execute COMMAND non-interactively and compare it to RESULT."
-  (ert-info (#'eshell-get-debug-logs :prefix "Command logs: ")
-    (let ((eshell-module-loading-messages nil))
-      (should (eshell-command-result--equal
-               command
-               (eshell-test-command-result command)
-               result)))))
-
-(defun eshell-command-result--match (_command regexp actual)
-  "Compare the ACTUAL result of a COMMAND with REGEXP."
-  (string-match regexp actual))
-
-(defun eshell-command-result--match-explainer (command regexp actual)
-  "Explain the result of `eshell-command-result--match'."
-  `(mismatched-result
-    (command ,command)
-    (result ,actual)
-    (regexp ,regexp)))
-
-(put 'eshell-command-result--match 'ert-explainer
-     #'eshell-command-result--match-explainer)
-
-(defun eshell-command-result-match (command regexp)
-  "Execute COMMAND non-interactively and compare it to REGEXP."
-  (ert-info (#'eshell-get-debug-logs :prefix "Command logs: ")
-    (let ((eshell-module-loading-messages nil))
-      (should (eshell-command-result--match
-               command regexp
-               (eshell-test-command-result command))))))
-
-(provide 'eshell-tests-helpers)
-
-;;; eshell-tests-helpers.el ends here
index 6565a4be65c939ca068a41e2849fa751138dc538..99e4528ab00ad7a6536ae3c7e0f3da6b3542f62a 100644 (file)
 (require 'ert)
 (require 'ert-x)
 (require 'esh-mode)
+(require 'ert-x)
 (require 'eshell)
 (require 'eshell-tests-helpers
-         (expand-file-name "eshell-tests-helpers"
-                           (file-name-directory (or load-file-name
-                                                    default-directory))))
+         (ert-resource-file "eshell-tests-helpers"))
 
 (defvar eshell-test-value nil)
 (defvar eshell-command-output)
diff --git a/test/lisp/eshell/resources/eshell-tests-helpers.el b/test/lisp/eshell/resources/eshell-tests-helpers.el
new file mode 100644 (file)
index 0000000..870e199
--- /dev/null
@@ -0,0 +1,233 @@
+;;; eshell-tests-helpers.el --- Eshell test suite helpers  -*- lexical-binding:t -*-
+
+;; Copyright (C) 1999-2025 Free Software Foundation, Inc.
+
+;; Author: John Wiegley <johnw@gnu.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Eshell test suite helpers.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'esh-mode)
+(require 'eshell)
+
+(defvar eshell-aliases-file nil)
+(defvar eshell-command-aliases-list nil)
+(defvar eshell-history-file-name nil)
+(defvar eshell-last-dir-ring-file-name nil)
+
+(defvar eshell-test--max-wait-time 5
+  "The maximum amount of time to wait for a condition to resolve, in seconds.
+See `eshell-wait-for'.")
+
+(defun eshell-tests-remote-accessible-p ()
+  "Return if a test involving remote files can proceed.
+If using this function, be sure to load `tramp' near the
+beginning of the test file."
+  (ignore-errors
+    (and
+     (file-remote-p ert-remote-temporary-file-directory)
+     (file-directory-p ert-remote-temporary-file-directory)
+     (file-writable-p ert-remote-temporary-file-directory))))
+
+(defmacro with-temp-eshell-settings (&rest body)
+  "Configure Eshell to leave no trace behind, and then evaluate BODY."
+  (declare (indent 0))
+  `(ert-with-temp-directory eshell-directory-name
+     (let (;; We want no history file, so prevent Eshell from falling
+           ;; back on $HISTFILE.
+           (process-environment (cons "HISTFILE" process-environment))
+           ;; Enable process debug instrumentation.  We may be able to
+           ;; remove this eventually once we're confident that all the
+           ;; process bugs have been worked out.  (At that point, we can
+           ;; just enable this selectively when needed.)  See also
+           ;; `eshell-test-command-result' below.
+           (eshell-debug-command (cons 'process eshell-debug-command))
+           (eshell-aliases-file nil)
+           (eshell-command-aliases-list nil)
+           (eshell-history-file-name nil)
+           (eshell-last-dir-ring-file-name nil)
+           (eshell-module-loading-messages nil))
+       ,@body)))
+
+(defmacro with-temp-eshell (&rest body)
+  "Evaluate BODY in a temporary Eshell buffer."
+  (declare (indent 0))
+  `(save-current-buffer
+     (with-temp-eshell-settings
+       (let ((eshell-buffer (eshell t)))
+         (unwind-protect
+             (with-current-buffer eshell-buffer
+               ,@body)
+           (let (kill-buffer-query-functions)
+             (kill-buffer eshell-buffer)))))))
+
+(defmacro eshell-with-temp-buffer (bufname text &rest body)
+  "Create a temporary buffer containing TEXT and evaluate BODY there.
+BUFNAME will be set to the name of the temporary buffer."
+  (declare (indent 2))
+  `(with-temp-buffer
+     (insert ,text)
+     (rename-buffer "eshell-temp-buffer" t)
+     (let ((,bufname (buffer-name)))
+       ,@body)))
+
+(defun eshell-wait-for (predicate &optional message)
+  "Wait until PREDICATE returns non-nil.
+If this takes longer than `eshell-test--max-wait-time', raise an
+error.  MESSAGE is an optional message to use if this times out."
+  (let ((start (current-time))
+        (message (or message "timed out waiting for condition")))
+    (while (not (funcall predicate))
+      (when (> (float-time (time-since start))
+               eshell-test--max-wait-time)
+        (error message))
+      (sit-for 0.1))))
+
+(defun eshell-wait-for-subprocess (&optional all)
+  "Wait until there is no interactive subprocess running in Eshell.
+If ALL is non-nil, wait until there are no Eshell subprocesses at
+all running.
+
+If this takes longer than `eshell-test--max-wait-time',
+raise an error."
+  (eshell-wait-for
+   (lambda ()
+     (not (if all eshell-process-list (eshell-interactive-process-p))))))
+
+(defun eshell-get-debug-logs ()
+  "Get debug command logs for displaying on test failures."
+  (when (get-buffer eshell-debug-command-buffer)
+    (let ((separator (make-string 40 ?-)))
+      (with-current-buffer eshell-debug-command-buffer
+        (string-replace "\f" separator (buffer-string))))))
+
+(defun eshell-insert-command (command &optional func)
+  "Insert a COMMAND at the end of the buffer.
+After inserting, call FUNC.  If FUNC is nil, instead call
+`eshell-send-input'."
+  (goto-char eshell-last-output-end)
+  (insert-and-inherit command)
+  (funcall (or func 'eshell-send-input)))
+
+(defun eshell-last-input ()
+  "Return the input of the last Eshell command."
+  (buffer-substring-no-properties
+   eshell-last-input-start eshell-last-input-end))
+
+(defun eshell-last-output ()
+  "Return the output of the last Eshell command."
+  (buffer-substring-no-properties
+   (eshell-beginning-of-output) (eshell-end-of-output)))
+
+(defun eshell-test-file-string (file)
+  "Return the contents of FILE as a string."
+  (with-temp-buffer
+    (insert-file-contents file)
+    (buffer-string)))
+
+(defun eshell-match-output (regexp)
+  "Test whether the output of the last command matches REGEXP."
+  (string-match-p regexp (eshell-last-output)))
+
+(defun eshell-match-output--explainer (regexp)
+  "Explain the result of `eshell-match-output'."
+  `(mismatched-output
+    (command ,(eshell-last-input))
+    (output ,(eshell-last-output))
+    (regexp ,regexp)))
+
+(put 'eshell-match-output 'ert-explainer #'eshell-match-output--explainer)
+
+(defun eshell-match-command-output (command regexp &optional func
+                                            ignore-errors)
+  "Insert a COMMAND at the end of the buffer and match the output with REGEXP.
+FUNC is the function to call after inserting the text (see
+`eshell-insert-command').
+
+If IGNORE-ERRORS is non-nil, ignore any errors signaled when
+inserting the command."
+  (ert-info (#'eshell-get-debug-logs :prefix "Command logs: ")
+    (let ((debug-on-error (and (not ignore-errors) debug-on-error)))
+      (eshell-insert-command command func))
+    (eshell-wait-for-subprocess)
+    (should (eshell-match-output regexp))))
+
+(defvar eshell-history-file-name)
+
+(defun eshell-test-command-result (command)
+  "Like `eshell-command-result', but not using HOME."
+  (ert-with-temp-directory eshell-directory-name
+    (let ((eshell-history-file-name nil)
+          ;; Enable process debug instrumentation.  See
+          ;; `with-temp-eshell' above.
+          (eshell-debug-command (cons 'process eshell-debug-command)))
+      (eshell-command-result command))))
+
+(defun eshell-command-result--equal (_command actual expected)
+  "Compare the ACTUAL result of a COMMAND with its EXPECTED value."
+  (equal actual expected))
+
+(defun eshell-command-result--equal-explainer (command actual expected)
+  "Explain the result of `eshell-command-result--equal'."
+  `(nonequal-result
+    (command ,command)
+    (result ,actual)
+    (expected ,expected)))
+
+(put 'eshell-command-result--equal 'ert-explainer
+     #'eshell-command-result--equal-explainer)
+
+(defun eshell-command-result-equal (command result)
+  "Execute COMMAND non-interactively and compare it to RESULT."
+  (ert-info (#'eshell-get-debug-logs :prefix "Command logs: ")
+    (let ((eshell-module-loading-messages nil))
+      (should (eshell-command-result--equal
+               command
+               (eshell-test-command-result command)
+               result)))))
+
+(defun eshell-command-result--match (_command regexp actual)
+  "Compare the ACTUAL result of a COMMAND with REGEXP."
+  (string-match regexp actual))
+
+(defun eshell-command-result--match-explainer (command regexp actual)
+  "Explain the result of `eshell-command-result--match'."
+  `(mismatched-result
+    (command ,command)
+    (result ,actual)
+    (regexp ,regexp)))
+
+(put 'eshell-command-result--match 'ert-explainer
+     #'eshell-command-result--match-explainer)
+
+(defun eshell-command-result-match (command regexp)
+  "Execute COMMAND non-interactively and compare it to REGEXP."
+  (ert-info (#'eshell-get-debug-logs :prefix "Command logs: ")
+    (let ((eshell-module-loading-messages nil))
+      (should (eshell-command-result--match
+               command regexp
+               (eshell-test-command-result command))))))
+
+(provide 'eshell-tests-helpers)
+
+;;; eshell-tests-helpers.el ends here