]> git.eshelyaron.com Git - emacs.git/commitdiff
Move eshell's self-tests to the test/ directory.
authorGlenn Morris <rgm@gnu.org>
Sat, 5 Mar 2011 20:07:27 +0000 (12:07 -0800)
committerGlenn Morris <rgm@gnu.org>
Sat, 5 Mar 2011 20:07:27 +0000 (12:07 -0800)
* lisp/eshell/esh-var.el: Don't require esh-test when compiling.
* lisp/eshell/em-banner.el, lisp/eshell/esh-cmd.el, lisp/eshell/esh-mode.el:
* lisp/eshell/esh-var.el, lisp/eshell/eshell.el: Move tests to esh-test.
* lisp/eshell/esh-test.el: Move to ../../test/eshell.el

* test/eshell.el: Move here from lisp/eshell/esh-test.el.

lisp/ChangeLog
lisp/eshell/em-banner.el
lisp/eshell/esh-cmd.el
lisp/eshell/esh-mode.el
lisp/eshell/esh-test.el [deleted file]
lisp/eshell/esh-util.el
lisp/eshell/esh-var.el
lisp/eshell/eshell.el
test/ChangeLog
test/eshell.el [new file with mode: 0644]

index e0cdeae84af2afb8fde6b1d58792fcae8e7a9729..33aa29ea41bf5556e966a4d1b30b72906cfb9f13 100644 (file)
@@ -1,3 +1,10 @@
+2011-03-05  Glenn Morris  <rgm@gnu.org>
+
+       * eshell/esh-var.el: Don't require esh-test when compiling.
+       * eshell/em-banner.el, eshell/esh-cmd.el, eshell/esh-mode.el:
+       * eshell/esh-var.el, eshell/eshell.el: Move tests to esh-test.
+       * eshell/esh-test.el: Move to ../../test/eshell.el
+
 2011-03-05  David Engster  <deng@randomsample.de>
 
        * files.el (save-some-buffers): Report the names of buffers saved
index c3e5a8b3d5578de12b0cce80801366a522bd64ae..ce987f132e3e3dda104fbc5583992dc86c3acf48 100644 (file)
@@ -82,14 +82,6 @@ This can be any sexp, and should end with at least two newlines."
       (assert msg)
       (eshell-interactive-print msg))))
 
-(eshell-deftest banner banner-displayed
-  "Startup banner is displayed at point-min"
-  (assert eshell-banner-message)
-  (let ((msg (eval eshell-banner-message)))
-    (assert msg)
-    (goto-char (point-min))
-    (looking-at msg)))
-
 (provide 'em-banner)
 
 ;; Local Variables:
index 62c14f38025f052b936651ffa890cf808a9538dd..bdcdc4532721a1d22f062fe448c07e4a7afa55aa 100644 (file)
@@ -320,18 +320,6 @@ otherwise t.")
     (add-hook 'pcomplete-try-first-hook
              'eshell-complete-lisp-symbols nil t)))
 
-(eshell-deftest var last-result-var
-  "\"last result\" variable"
-  (eshell-command-result-p "+ 1 2; + $$ 2" "3\n5\n"))
-
-(eshell-deftest var last-result-var2
-  "\"last result\" variable"
-  (eshell-command-result-p "+ 1 2; + $$ $$" "3\n6\n"))
-
-(eshell-deftest var last-arg-var
-  "\"last arg\" variable"
-  (eshell-command-result-p "+ 1 2; + $_ 4" "3\n6\n"))
-
 (defun eshell-complete-lisp-symbols ()
   "If there is a user reference, complete it."
   (let ((arg (pcomplete-actual-arg)))
@@ -441,32 +429,12 @@ hooks should be run before and after the command."
           (eq (caar terms) 'eshell-command-to-value))
       (car (cdar terms))))
 
-(eshell-deftest cmd lisp-command
-  "Evaluate Lisp command"
-  (eshell-command-result-p "(+ 1 2)" "3"))
-
-(eshell-deftest cmd lisp-command-args
-  "Evaluate Lisp command (ignore args)"
-  (eshell-command-result-p "(+ 1 2) 3" "3"))
-
 (defun eshell-rewrite-initial-subcommand (terms)
   "Rewrite a subcommand in initial position, such as '{+ 1 2}'."
   (if (and (listp (car terms))
           (eq (caar terms) 'eshell-as-subcommand))
       (car terms)))
 
-(eshell-deftest cmd subcommand
-  "Run subcommand"
-  (eshell-command-result-p "{+ 1 2}" "3\n"))
-
-(eshell-deftest cmd subcommand-args
-  "Run subcommand (ignore args)"
-  (eshell-command-result-p "{+ 1 2} 3" "3\n"))
-
-(eshell-deftest cmd subcommand-lisp
-  "Run subcommand + Lisp form"
-  (eshell-command-result-p "{(+ 1 2)}" "3\n"))
-
 (defun eshell-rewrite-named-command (terms)
   "If no other rewriting rule transforms TERMS, assume a named command."
   (let ((sym (if eshell-in-pipeline-p
@@ -478,10 +446,6 @@ hooks should be run before and after the command."
        (list sym cmd (append (list 'list) (cdr terms)))
       (list sym cmd))))
 
-(eshell-deftest cmd named-command
-  "Execute named command"
-  (eshell-command-result-p "+ 1 2" "3\n"))
-
 (defvar eshell-command-body)
 (defvar eshell-test-body)
 
index f7c727aa36fed9c87a0189f14c84d00114264b4e..10623dba8e31d34f5163033ff309cff7aa61c814 100644 (file)
@@ -447,19 +447,6 @@ and the hook `eshell-exit-hook'."
 
 (put 'eshell-mode 'mode-class 'special)
 
-(eshell-deftest mode major-mode
-  "Major mode is correct"
-  (eq major-mode 'eshell-mode))
-
-(eshell-deftest mode eshell-mode-variable
-  "`eshell-mode' is true"
-  (eq eshell-mode t))
-
-(eshell-deftest var window-height
-  "LINES equals window height"
-  (let ((eshell-stringify-t t))
-    (eshell-command-result-p "= $LINES (window-height)" "t\n")))
-
 (defun eshell-command-started ()
   "Indicate in the modeline that a command has started."
   (setq eshell-command-running-string "**")
@@ -470,13 +457,6 @@ and the hook `eshell-exit-hook'."
   (setq eshell-command-running-string "--")
   (force-mode-line-update))
 
-(eshell-deftest mode command-running-p
-  "Modeline shows no command running"
-  (or (featurep 'xemacs)
-      (not eshell-status-in-modeline)
-      (and (memq 'eshell-command-running-string mode-line-format)
-          (equal eshell-command-running-string "--"))))
-
 ;;; Internal Functions:
 
 (defun eshell-toggle-direct-send ()
@@ -546,20 +526,6 @@ and the hook `eshell-exit-hook'."
             (= (1+ pos) limit))
        (forward-char 1))))
 
-(eshell-deftest arg forward-arg
-  "Move across command arguments"
-  (eshell-insert-command "echo $(+ 1 (- 4 3)) \"alpha beta\" file" 'ignore)
-  (let ((here (point)) begin valid)
-    (eshell-bol)
-    (setq begin (point))
-    (eshell-forward-argument 4)
-    (setq valid (= here (point)))
-    (eshell-backward-argument 4)
-    (prog1
-       (and valid (= begin (point)))
-      (eshell-bol)
-      (delete-region (point) (point-max)))))
-
 (defun eshell-forward-argument (&optional arg)
   "Move forward ARG arguments."
   (interactive "p")
@@ -659,17 +625,6 @@ waiting for input."
   (interactive "P")
   (eshell-send-input use-region t))
 
-(eshell-deftest mode queue-input
-  "Queue command input"
-  (eshell-insert-command "sleep 2")
-  (eshell-insert-command "echo alpha" 'eshell-queue-input)
-  (let ((count 10))
-    (while (and eshell-current-command
-               (> count 0))
-      (sit-for 1 0)
-      (setq count (1- count))))
-  (eshell-match-result "alpha\n"))
-
 (defun eshell-send-input (&optional use-region queue-p no-newline)
   "Send the input received to Eshell for parsing and processing.
 After `eshell-last-output-end', sends all text from that marker to
@@ -748,20 +703,6 @@ newline."
               (run-hooks 'eshell-post-command-hook)
               (insert-and-inherit input)))))))))
 
-; (eshell-deftest proc send-to-subprocess
-;   "Send input to a subprocess"
-;   ;; jww (1999-12-06): what about when bc is unavailable?
-;   (if (not (eshell-search-path "bc"))
-;       t
-;     (eshell-insert-command "bc")
-;     (eshell-insert-command "1 + 2")
-;     (sit-for 1 0)
-;     (forward-line -1)
-;     (prog1
-;      (looking-at "3\n")
-;       (eshell-insert-command "quit")
-;       (sit-for 1 0))))
-
 (defsubst eshell-kill-new ()
   "Add the last input text to the kill ring."
   (kill-ring-save eshell-last-input-start eshell-last-input-end))
@@ -907,14 +848,6 @@ Does not delete the prompt."
     (insert "*** output flushed ***\n")
     (delete-region (point) (eshell-end-of-output))))
 
-(eshell-deftest io flush-output
-  "Flush previous output"
-  (eshell-insert-command "echo alpha")
-  (eshell-kill-output)
-  (and (eshell-match-result (regexp-quote "*** output flushed ***\n"))
-       (forward-line)
-       (= (point) eshell-last-output-start)))
-
 (defun eshell-show-output (&optional arg)
   "Display start of this batch of interpreter output at top of window.
 Sets mark to the value of point when this command is run.
@@ -975,12 +908,6 @@ When run interactively, widen the buffer first."
     (goto-char eshell-last-output-end)
     (insert-and-inherit input)))
 
-(eshell-deftest mode run-old-command
-  "Re-run an old command"
-  (eshell-insert-command "echo alpha")
-  (goto-char eshell-last-input-start)
-  (string= (eshell-get-old-input) "echo alpha"))
-
 (defun eshell/exit ()
   "Leave or kill the Eshell buffer, depending on `eshell-kill-on-exit'."
   (throw 'eshell-terminal t))
diff --git a/lisp/eshell/esh-test.el b/lisp/eshell/esh-test.el
deleted file mode 100644 (file)
index 73ba161..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-;;; esh-test.el --- Eshell test suite
-
-;; Copyright (C) 1999-2011  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 <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; The purpose of this module is to verify that Eshell works as
-;; expected.  To run it on your system, use the command
-;; \\[eshell-test].
-
-;;; Code:
-
-(eval-when-compile
-  (require 'eshell)
-  (require 'esh-util))
-(require 'esh-mode)
-
-(defgroup eshell-test nil
-  "This module is meant to ensure that Eshell is working correctly."
-  :tag "Eshell test suite"
-  :group 'eshell)
-
-;;; User Variables:
-
-(defface eshell-test-ok
-  '((((class color) (background light)) (:foreground "Green" :bold t))
-    (((class color) (background dark)) (:foreground "Green" :bold t)))
-  "The face used to highlight OK result strings."
-  :group 'eshell-test)
-(define-obsolete-face-alias 'eshell-test-ok-face 'eshell-test-ok "22.1")
-
-(defface eshell-test-failed
-  '((((class color) (background light)) (:foreground "OrangeRed" :bold t))
-    (((class color) (background dark)) (:foreground "OrangeRed" :bold t))
-    (t (:bold t)))
-  "The face used to highlight FAILED result strings."
-  :group 'eshell-test)
-(define-obsolete-face-alias 'eshell-test-failed-face 'eshell-test-failed "22.1")
-
-(defcustom eshell-show-usage-metrics nil
-  "If non-nil, display different usage metrics for each Eshell command."
-  :set (lambda (symbol value)
-        (if value
-            (add-hook 'eshell-mode-hook 'eshell-show-usage-metrics)
-          (remove-hook 'eshell-mode-hook 'eshell-show-usage-metrics))
-        (set symbol value))
-  :type '(choice (const :tag "No metrics" nil)
-                (const :tag "Cons cells consumed" t)
-                (const :tag "Time elapsed" 0))
-  :group 'eshell-test)
-
-;;; Code:
-
-(defvar test-buffer)
-
-(defun eshell-insert-command (text &optional func)
-  "Insert a command at the end of the buffer."
-  (goto-char eshell-last-output-end)
-  (insert-and-inherit text)
-  (funcall (or func 'eshell-send-input)))
-
-(defun eshell-match-result (regexp)
-  "Insert a command at the end of the buffer."
-  (goto-char eshell-last-input-end)
-  (looking-at regexp))
-
-(defun eshell-command-result-p (text regexp &optional func)
-  "Insert a command at the end of the buffer."
-  (eshell-insert-command text func)
-  (eshell-match-result regexp))
-
-(defvar eshell-test-failures nil)
-
-(defun eshell-run-test (module funcsym label command)
-  "Test whether FORM evaluates to a non-nil value."
-  (when (let ((sym (intern-soft (concat "eshell-" (symbol-name module)))))
-         (or (memq sym (eshell-subgroups 'eshell))
-             (eshell-using-module sym)))
-    (with-current-buffer test-buffer
-      (insert-before-markers
-       (format "%-70s " (substring label 0 (min 70 (length label)))))
-      (insert-before-markers "  ....")
-      (eshell-redisplay))
-    (let ((truth (eval command)))
-      (with-current-buffer test-buffer
-       (delete-char -6)
-       (insert-before-markers
-        "[" (let (str)
-              (if truth
-                  (progn
-                    (setq str "  OK  ")
-                    (put-text-property 0 6 'face 'eshell-test-ok str))
-                (setq str "FAILED")
-                (setq eshell-test-failures (1+ eshell-test-failures))
-                (put-text-property 0 6 'face 'eshell-test-failed str))
-              str) "]")
-       (add-text-properties (line-beginning-position) (point)
-                            (list 'test-func funcsym))
-       (eshell-redisplay)))))
-
-(defun eshell-test-goto-func ()
-  "Jump to the function that defines a particular test."
-  (interactive)
-  (let ((fsym (get-text-property (point) 'test-func)))
-    (when fsym
-      (let* ((def (symbol-function fsym))
-            (library (locate-library (symbol-file fsym 'defun)))
-            (name (substring (symbol-name fsym)
-                             (length "eshell-test--")))
-            (inhibit-redisplay t))
-       (find-file library)
-       (goto-char (point-min))
-       (re-search-forward (concat "^(eshell-deftest\\s-+\\w+\\s-+"
-                                  name))
-       (beginning-of-line)))))
-
-(defun eshell-run-one-test (&optional arg)
-  "Jump to the function that defines a particular test."
-  (interactive "P")
-  (let ((fsym (get-text-property (point) 'test-func)))
-    (when fsym
-      (beginning-of-line)
-      (delete-region (point) (line-end-position))
-      (let ((test-buffer (current-buffer)))
-       (set-buffer (let ((inhibit-redisplay t))
-                     (save-window-excursion (eshell t))))
-       (funcall fsym)
-       (unless arg
-         (kill-buffer (current-buffer)))))))
-
-;;;###autoload
-(defun eshell-test (&optional arg)
-  "Test Eshell to verify that it works as expected."
-  (interactive "P")
-  (let* ((begin (float-time))
-        (test-buffer (get-buffer-create "*eshell test*")))
-    (set-buffer (let ((inhibit-redisplay t))
-                 (save-window-excursion (eshell t))))
-    (with-current-buffer test-buffer
-      (erase-buffer)
-      (setq major-mode 'eshell-test-mode)
-      (setq mode-name "EShell Test")
-      (set (make-local-variable 'eshell-test-failures) 0)
-      (local-set-key [(control ?c) (control ?c)] 'eshell-test-goto-func)
-      (local-set-key [(control ?c) (control ?r)] 'eshell-run-one-test)
-      (local-set-key [(control ?m)] 'eshell-test-goto-func)
-      (local-set-key [return] 'eshell-test-goto-func)
-
-      (insert "Testing Eshell under " (emacs-version))
-      (switch-to-buffer test-buffer)
-      (delete-other-windows))
-    (dolist (funcname (sort (all-completions "eshell-test--"
-                                               obarray 'functionp)
-                              'string-lessp))
-      (with-current-buffer test-buffer
-       (insert "\n"))
-      (funcall (intern-soft funcname)))
-    (with-current-buffer test-buffer
-      (insert (format "\n\n--- %s --- (completed in %d seconds)\n"
-                     (current-time-string)
-                     (- (float-time) begin)))
-      (message "Eshell test suite completed: %s failure%s"
-              (if (> eshell-test-failures 0)
-                  (number-to-string eshell-test-failures)
-                "No")
-              (if (= eshell-test-failures 1) "" "s"))))
-  (goto-char eshell-last-output-end)
-  (unless arg
-    (kill-buffer (current-buffer))))
-
-
-(defvar eshell-metric-before-command 0)
-(defvar eshell-metric-after-command 0)
-
-(defun eshell-show-usage-metrics ()
-  "If run at Eshell mode startup, metrics are shown after each command."
-  (set (make-local-variable 'eshell-metric-before-command)
-       (if (eq eshell-show-usage-metrics t)
-          0
-        (current-time)))
-  (set (make-local-variable 'eshell-metric-after-command)
-       (if (eq eshell-show-usage-metrics t)
-          0
-        (current-time)))
-
-  (add-hook 'eshell-pre-command-hook
-           (function
-            (lambda ()
-              (setq eshell-metric-before-command
-                    (if (eq eshell-show-usage-metrics t)
-                        (car (memory-use-counts))
-                      (current-time))))) nil t)
-
-  (add-hook 'eshell-post-command-hook
-           (function
-            (lambda ()
-              (setq eshell-metric-after-command
-                    (if (eq eshell-show-usage-metrics t)
-                        (car (memory-use-counts))
-                      (current-time)))
-              (eshell-interactive-print
-               (concat
-                (int-to-string
-                 (if (eq eshell-show-usage-metrics t)
-                     (- eshell-metric-after-command
-                        eshell-metric-before-command 7)
-                   (- (float-time
-                       eshell-metric-after-command)
-                      (float-time
-                       eshell-metric-before-command))))
-                "\n"))))
-           nil t))
-
-(provide 'esh-test)
-
-;;; esh-test.el ends here
index 8b62b04a8eae279c4e4b1511f9f308dac0363228..dbe4f824debb035af092c8b50ee5c2f71db6890c 100644 (file)
@@ -147,18 +147,6 @@ function `string-to-number'."
 
 (put 'eshell-condition-case 'lisp-indent-function 2)
 
-(defmacro eshell-deftest (module name label &rest forms)
-  (if (and (fboundp 'cl-compiling-file) (cl-compiling-file))
-      nil
-    (let ((fsym (intern (concat "eshell-test--" (symbol-name name)))))
-      `(eval-when-compile
-        (ignore
-         (defun ,fsym () ,label
-           (eshell-run-test (quote ,module) (quote ,fsym) ,label
-                            (quote (progn ,@forms)))))))))
-
-(put 'eshell-deftest 'lisp-indent-function 2)
-
 (defun eshell-find-delimiter
   (open close &optional bound reverse-p backslash-p)
   "From point, find the CLOSE delimiter corresponding to OPEN.
index ae87215a7671e00275255d5728f5c858e4f7fa84..69004a841f1cd5496e2e2559adc0796b834a0ccd 100644 (file)
 
 (eval-when-compile
   (require 'pcomplete)
-  (require 'esh-test)
   (require 'esh-util)
   (require 'esh-opt)
   (require 'esh-mode))
@@ -477,30 +476,6 @@ Possible options are:
      (t
       (error "Invalid variable reference")))))
 
-(eshell-deftest var interp-cmd
-  "Interpolate command result"
-  (eshell-command-result-p "+ ${+ 1 2} 3" "6\n"))
-
-(eshell-deftest var interp-lisp
-  "Interpolate Lisp form evalution"
-  (eshell-command-result-p "+ $(+ 1 2) 3" "6\n"))
-
-(eshell-deftest var interp-concat
-  "Interpolate and concat command"
-  (eshell-command-result-p "+ ${+ 1 2}3 3" "36\n"))
-
-(eshell-deftest var interp-concat-lisp
-  "Interpolate and concat Lisp form"
-  (eshell-command-result-p "+ $(+ 1 2)3 3" "36\n"))
-
-(eshell-deftest var interp-concat2
-  "Interpolate and concat two commands"
-  (eshell-command-result-p "+ ${+ 1 2}${+ 1 2} 3" "36\n"))
-
-(eshell-deftest var interp-concat-lisp2
-  "Interpolate and concat two Lisp forms"
-  (eshell-command-result-p "+ $(+ 1 2)$(+ 1 2) 3" "36\n"))
-
 (defun eshell-parse-indices ()
   "Parse and return a list of list of indices."
   (let (indices)
index cda1eea2c5522884a18f7553c3834ce5649f86d0..1a9d7c97b83ec8587d10ba025f5e308660320d3b 100644 (file)
@@ -280,26 +280,12 @@ shells such as bash, zsh, rc, 4dos."
   :type 'string
   :group 'eshell)
 
-(eshell-deftest mode same-window-buffer-names
-  "`eshell-buffer-name' is a member of `same-window-buffer-names'"
-  (member eshell-buffer-name same-window-buffer-names))
-
 (defcustom eshell-directory-name
   (locate-user-emacs-file "eshell/" ".eshell/")
   "The directory where Eshell control files should be kept."
   :type 'directory
   :group 'eshell)
 
-(eshell-deftest mode eshell-directory-exists
-  "`eshell-directory-name' exists and is writable"
-  (file-writable-p eshell-directory-name))
-
-(eshell-deftest mode eshell-directory-modes
-  "`eshell-directory-name' has correct access protections"
-  (or (eshell-under-windows-p)
-      (= (file-modes eshell-directory-name)
-        eshell-private-directory-modes)))
-
 ;;;_* Running Eshell
 ;;
 ;; There are only three commands used to invoke Eshell.  The first two
@@ -450,10 +436,6 @@ corresponding to a successful execution."
              (set status-var eshell-last-command-status))
          (cadr result))))))
 
-(eshell-deftest mode simple-command-result
-  "`eshell-command-result' works with a simple command."
-  (= (eshell-command-result "+ 1 2") 3))
-
 ;;;_* Reporting bugs
 ;;
 ;; If you do encounter a bug, on any system, please report
index 8b7feaddf626aecaa5ecb66063e4399309cd5094..b247b88bc947268d2d6fd27aa18aae4d69bdc521 100644 (file)
@@ -1,3 +1,7 @@
+2011-03-05  Glenn Morris  <rgm@gnu.org>
+
+       * eshell.el: Move here from lisp/eshell/esh-test.el.
+
 2011-03-03  Christian Ohler  <ohler@gnu.org>
 
        * automated/ert-tests.el (ert-test-explain-not-equal-keymaps):
diff --git a/test/eshell.el b/test/eshell.el
new file mode 100644 (file)
index 0000000..3b392e8
--- /dev/null
@@ -0,0 +1,421 @@
+;;; esh-test.el --- Eshell test suite
+
+;; Copyright (C) 1999-2011  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 <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The purpose of this module is to verify that Eshell works as
+;; expected.  To run it on your system, use the command
+;; \\[eshell-test].
+
+;;; Code:
+
+(eval-when-compile
+  (require 'cl)                                ; assert
+  (require 'eshell)
+  (require 'esh-util))
+(require 'esh-mode)
+
+(defgroup eshell-test nil
+  "This module is meant to ensure that Eshell is working correctly."
+  :tag "Eshell test suite"
+  :group 'eshell)
+
+;;; User Variables:
+
+(defface eshell-test-ok
+  '((((class color) (background light)) (:foreground "Green" :bold t))
+    (((class color) (background dark)) (:foreground "Green" :bold t)))
+  "The face used to highlight OK result strings."
+  :group 'eshell-test)
+(define-obsolete-face-alias 'eshell-test-ok-face 'eshell-test-ok "22.1")
+
+(defface eshell-test-failed
+  '((((class color) (background light)) (:foreground "OrangeRed" :bold t))
+    (((class color) (background dark)) (:foreground "OrangeRed" :bold t))
+    (t (:bold t)))
+  "The face used to highlight FAILED result strings."
+  :group 'eshell-test)
+(define-obsolete-face-alias 'eshell-test-failed-face 'eshell-test-failed "22.1")
+
+(defcustom eshell-show-usage-metrics nil
+  "If non-nil, display different usage metrics for each Eshell command."
+  :set (lambda (symbol value)
+        (if value
+            (add-hook 'eshell-mode-hook 'eshell-show-usage-metrics)
+          (remove-hook 'eshell-mode-hook 'eshell-show-usage-metrics))
+        (set symbol value))
+  :type '(choice (const :tag "No metrics" nil)
+                (const :tag "Cons cells consumed" t)
+                (const :tag "Time elapsed" 0))
+  :group 'eshell-test)
+
+;;; Code:
+
+(defvar test-buffer)
+
+(defun eshell-insert-command (text &optional func)
+  "Insert a command at the end of the buffer."
+  (goto-char eshell-last-output-end)
+  (insert-and-inherit text)
+  (funcall (or func 'eshell-send-input)))
+
+(defun eshell-match-result (regexp)
+  "Insert a command at the end of the buffer."
+  (goto-char eshell-last-input-end)
+  (looking-at regexp))
+
+(defun eshell-command-result-p (text regexp &optional func)
+  "Insert a command at the end of the buffer."
+  (eshell-insert-command text func)
+  (eshell-match-result regexp))
+
+(defvar eshell-test-failures nil)
+
+(defun eshell-run-test (module funcsym label command)
+  "Test whether FORM evaluates to a non-nil value."
+  (when (let ((sym (intern-soft (concat "eshell-" (symbol-name module)))))
+         (or (memq sym (eshell-subgroups 'eshell))
+             (eshell-using-module sym)))
+    (with-current-buffer test-buffer
+      (insert-before-markers
+       (format "%-70s " (substring label 0 (min 70 (length label)))))
+      (insert-before-markers "  ....")
+      (eshell-redisplay))
+    (let ((truth (eval command)))
+      (with-current-buffer test-buffer
+       (delete-char -6)
+       (insert-before-markers
+        "[" (let (str)
+              (if truth
+                  (progn
+                    (setq str "  OK  ")
+                    (put-text-property 0 6 'face 'eshell-test-ok str))
+                (setq str "FAILED")
+                (setq eshell-test-failures (1+ eshell-test-failures))
+                (put-text-property 0 6 'face 'eshell-test-failed str))
+              str) "]")
+       (add-text-properties (line-beginning-position) (point)
+                            (list 'test-func funcsym))
+       (eshell-redisplay)))))
+
+(defun eshell-test-goto-func ()
+  "Jump to the function that defines a particular test."
+  (interactive)
+  (let ((fsym (get-text-property (point) 'test-func)))
+    (when fsym
+      (let* ((def (symbol-function fsym))
+            (library (locate-library (symbol-file fsym 'defun)))
+            (name (substring (symbol-name fsym)
+                             (length "eshell-test--")))
+            (inhibit-redisplay t))
+       (find-file library)
+       (goto-char (point-min))
+       (re-search-forward (concat "^(eshell-deftest\\s-+\\w+\\s-+"
+                                  name))
+       (beginning-of-line)))))
+
+(defun eshell-run-one-test (&optional arg)
+  "Jump to the function that defines a particular test."
+  (interactive "P")
+  (let ((fsym (get-text-property (point) 'test-func)))
+    (when fsym
+      (beginning-of-line)
+      (delete-region (point) (line-end-position))
+      (let ((test-buffer (current-buffer)))
+       (set-buffer (let ((inhibit-redisplay t))
+                     (save-window-excursion (eshell t))))
+       (funcall fsym)
+       (unless arg
+         (kill-buffer (current-buffer)))))))
+
+;;;###autoload
+(defun eshell-test (&optional arg)
+  "Test Eshell to verify that it works as expected."
+  (interactive "P")
+  (let* ((begin (float-time))
+        (test-buffer (get-buffer-create "*eshell test*")))
+    (set-buffer (let ((inhibit-redisplay t))
+                 (save-window-excursion (eshell t))))
+    (with-current-buffer test-buffer
+      (erase-buffer)
+      (setq major-mode 'eshell-test-mode)
+      (setq mode-name "EShell Test")
+      (set (make-local-variable 'eshell-test-failures) 0)
+      (local-set-key [(control ?c) (control ?c)] 'eshell-test-goto-func)
+      (local-set-key [(control ?c) (control ?r)] 'eshell-run-one-test)
+      (local-set-key [(control ?m)] 'eshell-test-goto-func)
+      (local-set-key [return] 'eshell-test-goto-func)
+
+      (insert "Testing Eshell under " (emacs-version))
+      (switch-to-buffer test-buffer)
+      (delete-other-windows))
+    (dolist (funcname (sort (all-completions "eshell-test--"
+                                               obarray 'functionp)
+                              'string-lessp))
+      (with-current-buffer test-buffer
+       (insert "\n"))
+      (funcall (intern-soft funcname)))
+    (with-current-buffer test-buffer
+      (insert (format "\n\n--- %s --- (completed in %d seconds)\n"
+                     (current-time-string)
+                     (- (float-time) begin)))
+      (message "Eshell test suite completed: %s failure%s"
+              (if (> eshell-test-failures 0)
+                  (number-to-string eshell-test-failures)
+                "No")
+              (if (= eshell-test-failures 1) "" "s"))))
+  (goto-char eshell-last-output-end)
+  (unless arg
+    (kill-buffer (current-buffer))))
+
+
+(defvar eshell-metric-before-command 0)
+(defvar eshell-metric-after-command 0)
+
+(defun eshell-show-usage-metrics ()
+  "If run at Eshell mode startup, metrics are shown after each command."
+  (set (make-local-variable 'eshell-metric-before-command)
+       (if (eq eshell-show-usage-metrics t)
+          0
+        (current-time)))
+  (set (make-local-variable 'eshell-metric-after-command)
+       (if (eq eshell-show-usage-metrics t)
+          0
+        (current-time)))
+
+  (add-hook 'eshell-pre-command-hook
+           (function
+            (lambda ()
+              (setq eshell-metric-before-command
+                    (if (eq eshell-show-usage-metrics t)
+                        (car (memory-use-counts))
+                      (current-time))))) nil t)
+
+  (add-hook 'eshell-post-command-hook
+           (function
+            (lambda ()
+              (setq eshell-metric-after-command
+                    (if (eq eshell-show-usage-metrics t)
+                        (car (memory-use-counts))
+                      (current-time)))
+              (eshell-interactive-print
+               (concat
+                (int-to-string
+                 (if (eq eshell-show-usage-metrics t)
+                     (- eshell-metric-after-command
+                        eshell-metric-before-command 7)
+                   (- (float-time
+                       eshell-metric-after-command)
+                      (float-time
+                       eshell-metric-before-command))))
+                "\n"))))
+           nil t))
+
+
+;;; The tests.
+
+(defmacro eshell-deftest (module name label &rest forms)
+  (declare (indent 2))
+  (if (and (fboundp 'cl-compiling-file) (cl-compiling-file))
+      nil
+    (let ((fsym (intern (concat "eshell-test--" (symbol-name name)))))
+      `(eval-when-compile
+        (ignore
+         (defun ,fsym () ,label
+           (eshell-run-test (quote ,module) (quote ,fsym) ,label
+                            (quote (progn ,@forms)))))))))
+
+
+(eshell-deftest mode same-window-buffer-names
+  "`eshell-buffer-name' is a member of `same-window-buffer-names'"
+  (member eshell-buffer-name same-window-buffer-names))
+
+(eshell-deftest mode eshell-directory-exists
+  "`eshell-directory-name' exists and is writable"
+  (file-writable-p eshell-directory-name))
+
+(eshell-deftest mode eshell-directory-modes
+  "`eshell-directory-name' has correct access protections"
+  (or (eshell-under-windows-p)
+      (= (file-modes eshell-directory-name)
+        eshell-private-directory-modes)))
+
+(eshell-deftest mode simple-command-result
+  "`eshell-command-result' works with a simple command."
+  (= (eshell-command-result "+ 1 2") 3))
+
+
+(require 'em-banner)
+
+(eshell-deftest banner banner-displayed
+  "Startup banner is displayed at point-min"
+  (assert eshell-banner-message)
+  (let ((msg (eval eshell-banner-message)))
+    (assert msg)
+    (goto-char (point-min))
+    (looking-at msg)))
+
+
+(require 'esh-cmd)
+
+(eshell-deftest var last-result-var
+  "\"last result\" variable"
+  (eshell-command-result-p "+ 1 2; + $$ 2" "3\n5\n"))
+
+(eshell-deftest var last-result-var2
+  "\"last result\" variable"
+  (eshell-command-result-p "+ 1 2; + $$ $$" "3\n6\n"))
+
+(eshell-deftest var last-arg-var
+  "\"last arg\" variable"
+  (eshell-command-result-p "+ 1 2; + $_ 4" "3\n6\n"))
+
+(eshell-deftest cmd lisp-command
+  "Evaluate Lisp command"
+  (eshell-command-result-p "(+ 1 2)" "3"))
+
+(eshell-deftest cmd lisp-command-args
+  "Evaluate Lisp command (ignore args)"
+  (eshell-command-result-p "(+ 1 2) 3" "3"))
+
+(eshell-deftest cmd subcommand
+  "Run subcommand"
+  (eshell-command-result-p "{+ 1 2}" "3\n"))
+
+(eshell-deftest cmd subcommand-args
+  "Run subcommand (ignore args)"
+  (eshell-command-result-p "{+ 1 2} 3" "3\n"))
+
+(eshell-deftest cmd subcommand-lisp
+  "Run subcommand + Lisp form"
+  (eshell-command-result-p "{(+ 1 2)}" "3\n"))
+
+(eshell-deftest cmd named-command
+  "Execute named command"
+  (eshell-command-result-p "+ 1 2" "3\n"))
+
+
+(require 'esh-mode)
+
+(eshell-deftest mode major-mode
+  "Major mode is correct"
+  (eq major-mode 'eshell-mode))
+
+(eshell-deftest mode eshell-mode-variable
+  "`eshell-mode' is true"
+  (eq eshell-mode t))
+
+(eshell-deftest var window-height
+  "LINES equals window height"
+  (let ((eshell-stringify-t t))
+    (eshell-command-result-p "= $LINES (window-height)" "t\n")))
+
+(eshell-deftest mode command-running-p
+  "Modeline shows no command running"
+  (or (featurep 'xemacs)
+      (not eshell-status-in-modeline)
+      (and (memq 'eshell-command-running-string mode-line-format)
+          (equal eshell-command-running-string "--"))))
+
+(eshell-deftest arg forward-arg
+  "Move across command arguments"
+  (eshell-insert-command "echo $(+ 1 (- 4 3)) \"alpha beta\" file" 'ignore)
+  (let ((here (point)) begin valid)
+    (eshell-bol)
+    (setq begin (point))
+    (eshell-forward-argument 4)
+    (setq valid (= here (point)))
+    (eshell-backward-argument 4)
+    (prog1
+       (and valid (= begin (point)))
+      (eshell-bol)
+      (delete-region (point) (point-max)))))
+
+(eshell-deftest mode queue-input
+  "Queue command input"
+  (eshell-insert-command "sleep 2")
+  (eshell-insert-command "echo alpha" 'eshell-queue-input)
+  (let ((count 10))
+    (while (and eshell-current-command
+               (> count 0))
+      (sit-for 1 0)
+      (setq count (1- count))))
+  (eshell-match-result "alpha\n"))
+
+; (eshell-deftest proc send-to-subprocess
+;   "Send input to a subprocess"
+;   ;; jww (1999-12-06): what about when bc is unavailable?
+;   (if (not (eshell-search-path "bc"))
+;       t
+;     (eshell-insert-command "bc")
+;     (eshell-insert-command "1 + 2")
+;     (sit-for 1 0)
+;     (forward-line -1)
+;     (prog1
+;      (looking-at "3\n")
+;       (eshell-insert-command "quit")
+;       (sit-for 1 0))))
+
+(eshell-deftest io flush-output
+  "Flush previous output"
+  (eshell-insert-command "echo alpha")
+  (eshell-kill-output)
+  (and (eshell-match-result (regexp-quote "*** output flushed ***\n"))
+       (forward-line)
+       (= (point) eshell-last-output-start)))
+
+(eshell-deftest mode run-old-command
+  "Re-run an old command"
+  (eshell-insert-command "echo alpha")
+  (goto-char eshell-last-input-start)
+  (string= (eshell-get-old-input) "echo alpha"))
+
+
+(require 'esh-var)
+
+(eshell-deftest var interp-cmd
+  "Interpolate command result"
+  (eshell-command-result-p "+ ${+ 1 2} 3" "6\n"))
+
+(eshell-deftest var interp-lisp
+  "Interpolate Lisp form evalution"
+  (eshell-command-result-p "+ $(+ 1 2) 3" "6\n"))
+
+(eshell-deftest var interp-concat
+  "Interpolate and concat command"
+  (eshell-command-result-p "+ ${+ 1 2}3 3" "36\n"))
+
+(eshell-deftest var interp-concat-lisp
+  "Interpolate and concat Lisp form"
+  (eshell-command-result-p "+ $(+ 1 2)3 3" "36\n"))
+
+(eshell-deftest var interp-concat2
+  "Interpolate and concat two commands"
+  (eshell-command-result-p "+ ${+ 1 2}${+ 1 2} 3" "36\n"))
+
+(eshell-deftest var interp-concat-lisp2
+  "Interpolate and concat two Lisp forms"
+  (eshell-command-result-p "+ $(+ 1 2)$(+ 1 2) 3" "36\n"))
+
+
+(provide 'esh-test)
+
+;;; esh-test.el ends here