emacs/test/lisp/eshell/em-extpipe-tests.el

215 lines
8.0 KiB
EmacsLisp

;;; em-extpipe-tests.el --- em-extpipe test suite -*- lexical-binding:t -*-
;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Sean Whitton <spwhitton@spwhitton.name>
;; 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:
;;; Code:
(require 'cl-lib)
(require 'ert)
(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))))
(defmacro em-extpipe-tests--deftest (name input &rest body)
(declare (indent 2))
`(ert-deftest ,name ()
(cl-macrolet
((should-parse (expected)
`(let ((shell-file-name "sh")
(shell-command-switch "-c"))
;; Strip `eshell-do-command'.
(should (equal ,expected
(cadadr (eshell-parse-command input))))))
(with-substitute-for-temp (&rest body)
;; Substitute name of an actual temporary file and/or
;; buffer into `input'. The substitution logic is
;; appropriate for only the use we put it to in this file.
`(ert-with-temp-file temp
(let ((temp-buffer (generate-new-buffer " *tmp*" t)))
(unwind-protect
(let ((input
(replace-regexp-in-string
"temp\\([^>]\\|\\'\\)" temp
(string-replace
"#<buffer temp>"
(format "#<buffer %s>"
(eshell-quote-argument
(buffer-name temp-buffer)))
input))))
,@body)
(when (buffer-name temp-buffer)
(kill-buffer temp-buffer))))))
(temp-should-string= (expected)
`(should (string= ,expected
(string-trim-right
(with-temp-buffer
(insert-file-contents temp)
(buffer-string))))))
(temp-buffer-should-string= (expected)
`(should (string= ,expected
(string-trim-right
(with-current-buffer temp-buffer
(buffer-string)))))))
(skip-unless shell-file-name)
(skip-unless shell-command-switch)
(skip-unless (executable-find shell-file-name))
(let ((input ,input))
(with-temp-eshell ,@body)))))
(em-extpipe-tests--deftest em-extpipe-test-1
"echo \"bar\" *| rev >temp"
(skip-unless (executable-find "rev"))
(should-parse '(eshell-named-command
"sh" (list "-c" "echo \"bar\" | rev >temp")))
(with-substitute-for-temp
(eshell-match-command-output input "^$")
(temp-should-string= "rab")))
(em-extpipe-tests--deftest em-extpipe-test-2
"echo \"bar\" | rev *>temp"
(skip-unless (executable-find "rev"))
(should-parse
'(eshell-execute-pipeline
'((eshell-named-command "echo" (list (eshell-escape-arg "bar")))
(eshell-named-command "sh" (list "-c" "rev >temp")))))
(with-substitute-for-temp
(eshell-match-command-output input "^$")
(temp-should-string= "rab")))
(em-extpipe-tests--deftest em-extpipe-test-3 "foo *| bar | baz -d"
(should-parse
'(eshell-execute-pipeline
'((eshell-named-command "sh" (list "-c" "foo | bar"))
(eshell-named-command "baz" (list "-d"))))))
(em-extpipe-tests--deftest em-extpipe-test-4
"echo \"bar\" *| rev >#<buffer temp>"
(skip-unless (executable-find "rev"))
(should-parse
'(progn
(ignore
(eshell-set-output-handle 1 'overwrite
(eshell-get-buffer "temp")))
(eshell-named-command "sh"
(list "-c" "echo \"bar\" | rev"))))
(with-substitute-for-temp
(eshell-match-command-output input "^$")
(temp-buffer-should-string= "rab")))
(em-extpipe-tests--deftest em-extpipe-test-5
"foo *| bar >#<buffer quux> baz"
(should-parse '(eshell-named-command
"sh" (list "-c" "foo | bar >#<buffer quux> baz"))))
(em-extpipe-tests--deftest em-extpipe-test-6
"foo >#<buffer quux> *| bar baz"
(should-parse '(eshell-named-command
"sh" (list "-c" "foo >#<buffer quux> | bar baz"))))
(em-extpipe-tests--deftest em-extpipe-test-7
"foo *| bar >#<buffer quux> >>#<process other>"
(should-parse
'(progn
(ignore
(eshell-set-output-handle 1 'overwrite
(eshell-get-buffer "quux")))
(ignore
(eshell-set-output-handle 1 'append
(get-process "other")))
(eshell-named-command "sh"
(list "-c" "foo | bar")))))
(em-extpipe-tests--deftest em-extpipe-test-8
"foo *| bar >/dev/kill | baz"
(should-parse
'(eshell-execute-pipeline
'((progn
(ignore
(eshell-set-output-handle 1 'overwrite "/dev/kill"))
(eshell-named-command "sh"
(list "-c" "foo | bar")))
(eshell-named-command "baz")))))
(em-extpipe-tests--deftest em-extpipe-test-9 "foo \\*| bar"
(should-parse
'(eshell-execute-pipeline
'((eshell-named-command "foo"
(list (eshell-escape-arg "*")))
(eshell-named-command "bar")))))
(em-extpipe-tests--deftest em-extpipe-test-10 "foo \"*|\" *>bar"
(should-parse
'(eshell-named-command "sh" (list "-c" "foo \"*|\" >bar"))))
(em-extpipe-tests--deftest em-extpipe-test-11 "foo '*|' bar"
(should-parse '(eshell-named-command
"foo" (list (eshell-escape-arg "*|") "bar"))))
(em-extpipe-tests--deftest em-extpipe-test-12 ">foo bar *| baz"
(should-parse
'(eshell-named-command "sh" (list "-c" ">foo bar | baz"))))
(em-extpipe-tests--deftest em-extpipe-test-13 "foo*|bar"
(should-parse '(eshell-execute-pipeline
'((eshell-named-command (eshell-concat nil "foo" "*"))
(eshell-named-command "bar")))))
(em-extpipe-tests--deftest em-extpipe-test-14 "tac *<temp"
(skip-unless (executable-find "tac"))
(should-parse '(eshell-named-command "sh" (list "-c" "tac <temp")))
(with-substitute-for-temp
(with-temp-buffer
(insert "bar\nbaz\n")
;; Some versions of 'tac' on MS-Windows need Unix EOLs...
(let ((coding-system-for-write 'unix))
(write-file temp)))
(eshell-match-command-output input "baz\nbar")))
(em-extpipe-tests--deftest em-extpipe-test-15 "echo \"bar\" *| cat"
(skip-unless (executable-find "cat"))
(should-parse
'(eshell-named-command "sh" (list "-c" "echo \"bar\" | cat")))
(cl-letf (((symbol-function 'eshell/cat)
(lambda (&rest _args) (eshell-print "nonsense"))))
(eshell-match-command-output input "bar")
(eshell-match-command-output "echo \"bar\" | cat" "nonsense")))
(em-extpipe-tests--deftest em-extpipe-test-16 "echo \"bar\" *| rev"
(skip-unless (executable-find "rev"))
(should-parse
'(eshell-named-command "sh" (list "-c" "echo \"bar\" | rev")))
(let ((eshell-prefer-lisp-functions t))
(cl-letf (((symbol-function 'rev)
(lambda (&rest _args) (eshell-print "nonsense"))))
(eshell-match-command-output input "rab")
(eshell-match-command-output "echo \"bar\" | rev" "nonsense"))))
;; Confirm we don't break input of sharp-quoted symbols (Bug#53518).
(em-extpipe-tests--deftest em-extpipe-test-17 "funcall #'upcase foo"
(eshell-match-command-output input "FOO"))
;;; em-extpipe-tests.el ends here