mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-22 21:50:45 -08:00
dc4e6b1329; Update copyright years in more files64b3777631; Run set-copyright from admin.el8e1c56ae46; Add 2024 to copyright years # Conflicts: # doc/misc/modus-themes.org # doc/misc/texinfo.tex # etc/NEWS # etc/refcards/ru-refcard.tex # etc/themes/modus-operandi-theme.el # etc/themes/modus-themes.el # etc/themes/modus-vivendi-theme.el # lib/alloca.in.h # lib/binary-io.h # lib/c-ctype.h # lib/c-strcasecmp.c # lib/c-strncasecmp.c # lib/careadlinkat.c # lib/cloexec.c # lib/close-stream.c # lib/diffseq.h # lib/dup2.c # lib/filemode.h # lib/fpending.c # lib/fpending.h # lib/fsusage.c # lib/getgroups.c # lib/getloadavg.c # lib/gettext.h # lib/gettime.c # lib/gettimeofday.c # lib/group-member.c # lib/malloc.c # lib/md5-stream.c # lib/md5.c # lib/md5.h # lib/memmem.c # lib/memrchr.c # lib/nanosleep.c # lib/save-cwd.h # lib/sha1.c # lib/sig2str.c # lib/stdlib.in.h # lib/strtoimax.c # lib/strtol.c # lib/strtoll.c # lib/time_r.c # lib/xalloc-oversized.h # lisp/auth-source-pass.el # lisp/emacs-lisp/lisp-mnt.el # lisp/emacs-lisp/timer.el # lisp/info-look.el # lisp/jit-lock.el # lisp/loadhist.el # lisp/mail/rmail.el # lisp/net/ntlm.el # lisp/net/webjump.el # lisp/progmodes/asm-mode.el # lisp/progmodes/project.el # lisp/progmodes/sh-script.el # lisp/textmodes/flyspell.el # lisp/textmodes/reftex-toc.el # lisp/textmodes/reftex.el # lisp/textmodes/tex-mode.el # lisp/url/url-gw.el # m4/alloca.m4 # m4/clock_time.m4 # m4/d-type.m4 # m4/dirent_h.m4 # m4/dup2.m4 # m4/euidaccess.m4 # m4/fchmodat.m4 # m4/filemode.m4 # m4/fsusage.m4 # m4/getgroups.m4 # m4/getloadavg.m4 # m4/getrandom.m4 # m4/gettime.m4 # m4/gettimeofday.m4 # m4/gnulib-common.m4 # m4/group-member.m4 # m4/inttypes.m4 # m4/malloc.m4 # m4/manywarnings.m4 # m4/mempcpy.m4 # m4/memrchr.m4 # m4/mkostemp.m4 # m4/mktime.m4 # m4/nproc.m4 # m4/nstrftime.m4 # m4/pathmax.m4 # m4/pipe2.m4 # m4/pselect.m4 # m4/pthread_sigmask.m4 # m4/readlink.m4 # m4/realloc.m4 # m4/sig2str.m4 # m4/ssize_t.m4 # m4/stat-time.m4 # m4/stddef_h.m4 # m4/stdint.m4 # m4/stdio_h.m4 # m4/stdlib_h.m4 # m4/stpcpy.m4 # m4/strnlen.m4 # m4/strtoimax.m4 # m4/strtoll.m4 # m4/time_h.m4 # m4/timegm.m4 # m4/timer_time.m4 # m4/timespec.m4 # m4/unistd_h.m4 # m4/warnings.m4 # nt/configure.bat # nt/preprep.c # test/lisp/register-tests.el
384 lines
15 KiB
EmacsLisp
384 lines
15 KiB
EmacsLisp
;;; esh-io-tests.el --- esh-io test suite -*- lexical-binding:t -*-
|
||
|
||
;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
|
||
|
||
;; 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/>.
|
||
|
||
;;; Code:
|
||
|
||
(require 'ert)
|
||
(require 'ert-x)
|
||
(require 'esh-mode)
|
||
(require 'eshell)
|
||
|
||
(require 'eshell-tests-helpers
|
||
(expand-file-name "eshell-tests-helpers"
|
||
(file-name-directory (or load-file-name
|
||
default-directory))))
|
||
|
||
(defvar eshell-test-value nil)
|
||
|
||
(defvar eshell-test-value-with-fun nil)
|
||
(defun eshell-test-value-with-fun ())
|
||
|
||
(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/test-output ()
|
||
"Write some test output separately to stdout and stderr."
|
||
(eshell-printn "stdout")
|
||
(eshell-errorn "stderr"))
|
||
|
||
;;; Tests:
|
||
|
||
|
||
;; Basic redirection
|
||
|
||
(ert-deftest esh-io-test/redirect-file/overwrite ()
|
||
"Check that redirecting to a file in overwrite mode works."
|
||
(ert-with-temp-file temp-file
|
||
:text "old"
|
||
(with-temp-eshell
|
||
(eshell-insert-command (format "echo new > %s" temp-file)))
|
||
(should (equal (eshell-test-file-string temp-file) "new"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-file/append ()
|
||
"Check that redirecting to a file in append mode works."
|
||
(ert-with-temp-file temp-file
|
||
:text "old"
|
||
(with-temp-eshell
|
||
(eshell-insert-command (format "echo new >> %s" temp-file)))
|
||
(should (equal (eshell-test-file-string temp-file) "oldnew"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-file/insert ()
|
||
"Check that redirecting to a file in insert works."
|
||
(ert-with-temp-file temp-file
|
||
:text "old"
|
||
(with-temp-eshell
|
||
(eshell-insert-command (format "echo new >>> %s" temp-file)))
|
||
(should (equal (eshell-test-file-string temp-file) "newold"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-buffer/overwrite ()
|
||
"Check that redirecting to a buffer in overwrite mode works."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-insert-command (format "echo new > #<%s>" bufname)))
|
||
(should (equal (buffer-string) "new"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-buffer/append ()
|
||
"Check that redirecting to a buffer in append mode works."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-insert-command (format "echo new >> #<%s>" bufname)))
|
||
(should (equal (buffer-string) "oldnew"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-buffer/insert ()
|
||
"Check that redirecting to a buffer in insert mode works."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(goto-char (point-min))
|
||
(with-temp-eshell
|
||
(eshell-insert-command (format "echo new >>> #<%s>" bufname)))
|
||
(should (equal (buffer-string) "newold"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-buffer/escaped ()
|
||
"Check that redirecting to a buffer with escaped characters works."
|
||
(with-temp-buffer
|
||
(rename-buffer "eshell\\temp\\buffer" t)
|
||
(let ((bufname (buffer-name)))
|
||
(with-temp-eshell
|
||
(eshell-insert-command (format "echo hi > #<%s>"
|
||
(string-replace "\\" "\\\\" bufname))))
|
||
(should (equal (buffer-string) "hi")))))
|
||
|
||
(ert-deftest esh-io-test/redirect-symbol/overwrite ()
|
||
"Check that redirecting to a symbol in overwrite mode works."
|
||
(let ((eshell-test-value "old"))
|
||
(with-temp-eshell
|
||
(eshell-insert-command "echo new > #'eshell-test-value"))
|
||
(should (equal eshell-test-value "new"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-symbol/append ()
|
||
"Check that redirecting to a symbol in append mode works."
|
||
(let ((eshell-test-value "old"))
|
||
(with-temp-eshell
|
||
(eshell-insert-command "echo new >> #'eshell-test-value"))
|
||
(should (equal eshell-test-value "oldnew"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-symbol/with-function-slot ()
|
||
"Check that redirecting to a symbol with function slot set works."
|
||
(let ((eshell-test-value-with-fun))
|
||
(with-temp-eshell
|
||
(eshell-insert-command "echo hi > #'eshell-test-value-with-fun"))
|
||
(should (equal eshell-test-value-with-fun "hi"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-marker ()
|
||
"Check that redirecting to a marker works."
|
||
(with-temp-buffer
|
||
(let ((eshell-test-value (point-marker)))
|
||
(with-temp-eshell
|
||
(eshell-insert-command "echo hi > $eshell-test-value"))
|
||
(should (equal (buffer-string) "hi")))))
|
||
|
||
(ert-deftest esh-io-test/redirect-multiple ()
|
||
"Check that redirecting to multiple targets works."
|
||
(let ((eshell-test-value "old"))
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-insert-command (format "echo new > #<%s> > #'eshell-test-value"
|
||
bufname)))
|
||
(should (equal (buffer-string) "new"))
|
||
(should (equal eshell-test-value "new")))))
|
||
|
||
(ert-deftest esh-io-test/redirect-multiple/repeat ()
|
||
"Check that redirecting to multiple targets works when repeating a target."
|
||
(let ((eshell-test-value "old"))
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-insert-command
|
||
(format "echo new > #<%s> > #'eshell-test-value > #<%s>"
|
||
bufname bufname)))
|
||
(should (equal (buffer-string) "new"))
|
||
(should (equal eshell-test-value "new")))))
|
||
|
||
(ert-deftest esh-io-test/redirect-subcommands ()
|
||
"Check that redirecting subcommands applies to all subcommands."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-insert-command (format "{echo foo; echo bar} > #<%s>" bufname)))
|
||
(should (equal (buffer-string) "foobar"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-subcommands/override ()
|
||
"Check that redirecting subcommands applies to all subcommands.
|
||
Include a redirect to another location in the subcommand to
|
||
ensure only its statement is redirected."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(eshell-with-temp-buffer bufname-2 "also old"
|
||
(with-temp-eshell
|
||
(eshell-insert-command
|
||
(format "{echo foo; echo bar > #<%s>; echo baz} > #<%s>"
|
||
bufname-2 bufname)))
|
||
(should (equal (buffer-string) "bar")))
|
||
(should (equal (buffer-string) "foobaz"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-subcommands/dev-null ()
|
||
"Check that redirecting subcommands applies to all subcommands.
|
||
Include a redirect to /dev/null to ensure it only applies to its
|
||
statement."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-insert-command
|
||
(format "{echo foo; echo bar > /dev/null; echo baz} > #<%s>"
|
||
bufname)))
|
||
(should (equal (buffer-string) "foobaz"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-subcommands/interpolated ()
|
||
"Check that redirecting interpolated subcommands applies to all subcommands."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-insert-command
|
||
(format "echo ${echo foo; echo bar} > #<%s>" bufname)))
|
||
(should (equal (buffer-string) "foobar"))))
|
||
|
||
|
||
;; Redirecting specific handles
|
||
|
||
(ert-deftest esh-io-test/redirect-stdout ()
|
||
"Check that redirecting to stdout doesn't redirect stderr."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-match-command-output (format "test-output > #<%s>" bufname)
|
||
"stderr\n"))
|
||
(should (equal (buffer-string) "stdout\n")))
|
||
;; Also check explicitly specifying the stdout fd.
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-match-command-output (format "test-output 1> #<%s>" bufname)
|
||
"stderr\n"))
|
||
(should (equal (buffer-string) "stdout\n"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-stderr/overwrite ()
|
||
"Check that redirecting to stderr doesn't redirect stdout."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-match-command-output (format "test-output 2> #<%s>" bufname)
|
||
"stdout\n"))
|
||
(should (equal (buffer-string) "stderr\n"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-stderr/append ()
|
||
"Check that redirecting to stderr doesn't redirect stdout."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-match-command-output (format "test-output 2>> #<%s>" bufname)
|
||
"stdout\n"))
|
||
(should (equal (buffer-string) "oldstderr\n"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-stderr/insert ()
|
||
"Check that redirecting to stderr doesn't redirect stdout."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(goto-char (point-min))
|
||
(with-temp-eshell
|
||
(eshell-match-command-output (format "test-output 2>>> #<%s>" bufname)
|
||
"stdout\n"))
|
||
(should (equal (buffer-string) "stderr\nold"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-stdout-and-stderr ()
|
||
"Check that redirecting to both stdout and stderr works."
|
||
(eshell-with-temp-buffer bufname-1 "old"
|
||
(eshell-with-temp-buffer bufname-2 "old"
|
||
(with-temp-eshell
|
||
(eshell-match-command-output (format "test-output > #<%s> 2> #<%s>"
|
||
bufname-1 bufname-2)
|
||
"\\`\\'"))
|
||
(should (equal (buffer-string) "stderr\n")))
|
||
(should (equal (buffer-string) "stdout\n"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-all/overwrite ()
|
||
"Check that redirecting to stdout and stderr via shorthand works."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-match-command-output (format "test-output &> #<%s>" bufname)
|
||
"\\`\\'"))
|
||
(should (equal (buffer-string) "stdout\nstderr\n")))
|
||
;; Also check the alternate (and less-preferred in Bash) `>&' syntax.
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-match-command-output (format "test-output >& #<%s>" bufname)
|
||
"\\`\\'"))
|
||
(should (equal (buffer-string) "stdout\nstderr\n"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-all/append ()
|
||
"Check that redirecting to stdout and stderr via shorthand works."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-match-command-output (format "test-output &>> #<%s>" bufname)
|
||
"\\`\\'"))
|
||
(should (equal (buffer-string) "oldstdout\nstderr\n")))
|
||
;; Also check the alternate (and less-preferred in Bash) `>>&' syntax.
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-match-command-output (format "test-output >>& #<%s>" bufname)
|
||
"\\`\\'"))
|
||
(should (equal (buffer-string) "oldstdout\nstderr\n"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-all/insert ()
|
||
"Check that redirecting to stdout and stderr via shorthand works."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(goto-char (point-min))
|
||
(with-temp-eshell
|
||
(eshell-match-command-output (format "test-output &>>> #<%s>" bufname)
|
||
"\\`\\'"))
|
||
(should (equal (buffer-string) "stdout\nstderr\nold")))
|
||
;; Also check the alternate `>>>&' syntax.
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(goto-char (point-min))
|
||
(with-temp-eshell
|
||
(eshell-match-command-output (format "test-output >>>& #<%s>" bufname)
|
||
"\\`\\'"))
|
||
(should (equal (buffer-string) "stdout\nstderr\nold"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-copy ()
|
||
"Check that redirecting stdout and then copying stdout to stderr works.
|
||
This should redirect both stdout and stderr to the same place."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-match-command-output (format "test-output > #<%s> 2>&1" bufname)
|
||
"\\`\\'"))
|
||
(should (equal (buffer-string) "stdout\nstderr\n"))))
|
||
|
||
(ert-deftest esh-io-test/redirect-copy-first ()
|
||
"Check that copying stdout to stderr and then redirecting stdout works.
|
||
This should redirect stdout to a buffer, and stderr to where
|
||
stdout originally pointed (the terminal)."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-match-command-output (format "test-output 2>&1 > #<%s>" bufname)
|
||
"stderr\n"))
|
||
(should (equal (buffer-string) "stdout\n"))))
|
||
|
||
|
||
;; Pipelines
|
||
|
||
(ert-deftest esh-io-test/pipeline/default ()
|
||
"Check that `|' only pipes stdout."
|
||
(skip-unless (executable-find "rev"))
|
||
(eshell-command-result-equal "test-output | rev"
|
||
"stderr\ntuodts\n"))
|
||
|
||
|
||
(ert-deftest esh-io-test/pipeline/all ()
|
||
"Check that `|&' only pipes stdout and stderr."
|
||
(skip-unless (executable-find "rev"))
|
||
(eshell-command-result-equal "test-output |& rev"
|
||
"tuodts\nrredts\n"))
|
||
|
||
(ert-deftest esh-io-test/pipeline/subcommands ()
|
||
"Check that all commands in a subcommand are properly piped."
|
||
(skip-unless (executable-find "rev"))
|
||
(with-temp-eshell
|
||
(eshell-match-command-output "{echo foo; echo bar} | rev"
|
||
"\\`raboof\n?")))
|
||
|
||
(ert-deftest esh-io-test/pipeline/stdin-to-head ()
|
||
"Check that standard input is sent to the head process in a pipeline."
|
||
(skip-unless (and (executable-find "tr")
|
||
(executable-find "rev")))
|
||
(with-temp-eshell
|
||
(eshell-insert-command "tr a-z A-Z | rev")
|
||
(eshell-insert-command "hello")
|
||
(eshell-send-eof-to-process)
|
||
(eshell-wait-for-subprocess)
|
||
(should (eshell-match-output "OLLEH\n"))))
|
||
|
||
|
||
;; Virtual targets
|
||
|
||
(ert-deftest esh-io-test/virtual/dev-null ()
|
||
"Check that redirecting to /dev/null works."
|
||
(with-temp-eshell
|
||
(eshell-match-command-output "echo hi > /dev/null" "\\`\\'")))
|
||
|
||
(ert-deftest esh-io-test/virtual/dev-null/multiple ()
|
||
"Check that redirecting to /dev/null works alongside other redirections."
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-match-command-output
|
||
(format "echo new > /dev/null > #<%s>" bufname) "\\`\\'"))
|
||
(should (equal (buffer-string) "new")))
|
||
(eshell-with-temp-buffer bufname "old"
|
||
(with-temp-eshell
|
||
(eshell-match-command-output
|
||
(format "echo new > #<%s> > /dev/null" bufname) "\\`\\'"))
|
||
(should (equal (buffer-string) "new"))))
|
||
|
||
(ert-deftest esh-io-test/virtual/dev-eshell ()
|
||
"Check that redirecting to /dev/eshell works."
|
||
(with-temp-eshell
|
||
(eshell-match-command-output "echo hi > /dev/eshell" "hi")))
|
||
|
||
(ert-deftest esh-io-test/virtual/dev-kill ()
|
||
"Check that redirecting to /dev/kill works."
|
||
(with-temp-eshell
|
||
(eshell-insert-command "echo one > /dev/kill")
|
||
(should (equal (car kill-ring) "one"))
|
||
(eshell-insert-command "echo two > /dev/kill")
|
||
(should (equal (car kill-ring) "two"))
|
||
(eshell-insert-command "echo three >> /dev/kill")
|
||
(should (equal (car kill-ring) "twothree"))))
|
||
|
||
;;; esh-io-tests.el ends here
|