aboutsummaryrefslogtreecommitdiffstats
path: root/test/src/process-tests.el
diff options
context:
space:
mode:
authorJim Porter2022-07-17 20:25:00 -0700
committerJim Porter2022-08-05 17:58:54 -0700
commitd7b89ea4077d4fe677ba0577245328819ee79cdc (patch)
treed4e499042bdf2f301be7f2d7ec05f0d1bfd8d44b /test/src/process-tests.el
parentb70369c557efed3dcd86dc64a2e73e3480dea6af (diff)
downloademacs-d7b89ea4077d4fe677ba0577245328819ee79cdc.tar.gz
emacs-d7b89ea4077d4fe677ba0577245328819ee79cdc.zip
Allow creating processes where only one of stdin or stdout is a PTY
* src/lisp.h (emacs_spawn): * src/callproc.c (emacs_spawn): Add PTY_IN and PTY_OUT arguments to specify which streams should be set up as a PTY. (call_process): Adjust call to 'emacs_spawn'. * src/process.h (Lisp_Process): Replace 'pty_flag' with 'pty_in' and 'pty_out'. * src/process.c (is_pty_from_symbol): New function. (make-process): Allow :connection-type to be a cons cell, and allow using a stderr process with a PTY for stdin/stdout. (create_process): Handle creating a process where only one of stdin or stdout is a PTY. * lisp/eshell/esh-proc.el (eshell-needs-pipe, eshell-needs-pipe-p): Remove. (eshell-gather-process-output): Use 'make-process' and set ':connection-type' as needed by the value of 'eshell-in-pipeline-p'. * lisp/net/tramp.el (tramp-handle-make-process): * lisp/net/tramp-adb.el (tramp-adb-handle-make-process): * lisp/net/tramp-sh.el (tramp-sh-handle-make-process): Don't signal an error when ':connection-type' is a cons cell. * test/src/process-tests.el (process-test-sentinel-wait-function-working-p): Allow passing PROC in, and rework into... (process-test-wait-for-sentinel): ... this. (process-test-sentinel-accept-process-output) (process-test-sentinel-sit-for, process-test-quoted-batfile) (process-test-stderr-filter): Use 'process-test-wait-for-sentinel'. (make/process/test-connection-type): New function. (make-process/connection-type/pty, make-process/connection-type/pty-2) (make-process/connection-type/pipe) (make-process/connection-type/pipe-2) (make-process/connection-type/in-pty) (make-process/connection-type/out-pty) (make-process/connection-type/pty-with-stderr-buffer) (make-process/connection-type/out-pty-with-stderr-buffer): New tests. * test/lisp/eshell/esh-proc-tests.el (esh-proc-test--detect-pty-cmd): New variable. (esh-proc-test/pipeline-connection-type/no-pipeline) (esh-proc-test/pipeline-connection-type/first) (esh-proc-test/pipeline-connection-type/middle) (esh-proc-test/pipeline-connection-type/last): New tests. * doc/lispref/processes.texi (Asynchronous Processes): Document new ':connection-type' behavior. (Output from Processes): Remove caveat about ':stderr' forcing 'make-process' to use pipes. * etc/NEWS: Announce this change (bug#56025).
Diffstat (limited to 'test/src/process-tests.el')
-rw-r--r--test/src/process-tests.el121
1 files changed, 86 insertions, 35 deletions
diff --git a/test/src/process-tests.el b/test/src/process-tests.el
index aab95b2d733..b801563feb7 100644
--- a/test/src/process-tests.el
+++ b/test/src/process-tests.el
@@ -38,10 +38,11 @@
38;; Timeout in seconds; the test fails if the timeout is reached. 38;; Timeout in seconds; the test fails if the timeout is reached.
39(defvar process-test-sentinel-wait-timeout 2.0) 39(defvar process-test-sentinel-wait-timeout 2.0)
40 40
41;; Start a process that exits immediately. Call WAIT-FUNCTION, 41(defun process-test-wait-for-sentinel (proc exit-status &optional wait-function)
42;; possibly multiple times, to wait for the process to complete. 42 "Set a sentinel on PROC and wait for it to be called with EXIT-STATUS.
43(defun process-test-sentinel-wait-function-working-p (wait-function) 43Call WAIT-FUNCTION, possibly multiple times, to wait for the
44 (let ((proc (start-process "test" nil "bash" "-c" "exit 20")) 44process to complete."
45 (let ((wait-function (or wait-function #'accept-process-output))
45 (sentinel-called nil) 46 (sentinel-called nil)
46 (start-time (float-time))) 47 (start-time (float-time)))
47 (set-process-sentinel proc (lambda (_proc _msg) 48 (set-process-sentinel proc (lambda (_proc _msg)
@@ -50,21 +51,22 @@
50 (> (- (float-time) start-time) 51 (> (- (float-time) start-time)
51 process-test-sentinel-wait-timeout))) 52 process-test-sentinel-wait-timeout)))
52 (funcall wait-function)) 53 (funcall wait-function))
53 (cl-assert (eq (process-status proc) 'exit)) 54 (should sentinel-called)
54 (cl-assert (= (process-exit-status proc) 20)) 55 (should (eq (process-status proc) 'exit))
55 sentinel-called)) 56 (should (= (process-exit-status proc) exit-status))))
56 57
57(ert-deftest process-test-sentinel-accept-process-output () 58(ert-deftest process-test-sentinel-accept-process-output ()
58 (skip-unless (executable-find "bash")) 59 (skip-unless (executable-find "bash"))
59 (with-timeout (60 (ert-fail "Test timed out")) 60 (with-timeout (60 (ert-fail "Test timed out"))
60 (should (process-test-sentinel-wait-function-working-p 61 (let ((proc (start-process "test" nil "bash" "-c" "exit 20")))
61 #'accept-process-output)))) 62 (should (process-test-wait-for-sentinel proc 20)))))
62 63
63(ert-deftest process-test-sentinel-sit-for () 64(ert-deftest process-test-sentinel-sit-for ()
64 (skip-unless (executable-find "bash")) 65 (skip-unless (executable-find "bash"))
65 (with-timeout (60 (ert-fail "Test timed out")) 66 (with-timeout (60 (ert-fail "Test timed out"))
66 (should 67 (let ((proc (start-process "test" nil "bash" "-c" "exit 20")))
67 (process-test-sentinel-wait-function-working-p (lambda () (sit-for 0.01 t)))))) 68 (should (process-test-wait-for-sentinel
69 proc 20 (lambda () (sit-for 0.01 t)))))))
68 70
69(when (eq system-type 'windows-nt) 71(when (eq system-type 'windows-nt)
70 (ert-deftest process-test-quoted-batfile () 72 (ert-deftest process-test-quoted-batfile ()
@@ -97,17 +99,8 @@
97 "echo hello stderr! >&2; " 99 "echo hello stderr! >&2; "
98 "exit 20")) 100 "exit 20"))
99 :buffer stdout-buffer 101 :buffer stdout-buffer
100 :stderr stderr-buffer)) 102 :stderr stderr-buffer)))
101 (sentinel-called nil) 103 (process-test-wait-for-sentinel proc 20)
102 (start-time (float-time)))
103 (set-process-sentinel proc (lambda (_proc _msg)
104 (setq sentinel-called t)))
105 (while (not (or sentinel-called
106 (> (- (float-time) start-time)
107 process-test-sentinel-wait-timeout)))
108 (accept-process-output))
109 (cl-assert (eq (process-status proc) 'exit))
110 (cl-assert (= (process-exit-status proc) 20))
111 (should (with-current-buffer stdout-buffer 104 (should (with-current-buffer stdout-buffer
112 (goto-char (point-min)) 105 (goto-char (point-min))
113 (looking-at "hello stdout!"))) 106 (looking-at "hello stdout!")))
@@ -118,8 +111,7 @@
118(ert-deftest process-test-stderr-filter () 111(ert-deftest process-test-stderr-filter ()
119 (skip-unless (executable-find "bash")) 112 (skip-unless (executable-find "bash"))
120 (with-timeout (60 (ert-fail "Test timed out")) 113 (with-timeout (60 (ert-fail "Test timed out"))
121 (let* ((sentinel-called nil) 114 (let* ((stderr-sentinel-called nil)
122 (stderr-sentinel-called nil)
123 (stdout-output nil) 115 (stdout-output nil)
124 (stderr-output nil) 116 (stderr-output nil)
125 (stdout-buffer (generate-new-buffer "*stdout*")) 117 (stdout-buffer (generate-new-buffer "*stdout*"))
@@ -131,23 +123,14 @@
131 (concat "echo hello stdout!; " 123 (concat "echo hello stdout!; "
132 "echo hello stderr! >&2; " 124 "echo hello stderr! >&2; "
133 "exit 20")) 125 "exit 20"))
134 :stderr stderr-proc)) 126 :stderr stderr-proc)))
135 (start-time (float-time)))
136 (set-process-filter proc (lambda (_proc input) 127 (set-process-filter proc (lambda (_proc input)
137 (push input stdout-output))) 128 (push input stdout-output)))
138 (set-process-sentinel proc (lambda (_proc _msg)
139 (setq sentinel-called t)))
140 (set-process-filter stderr-proc (lambda (_proc input) 129 (set-process-filter stderr-proc (lambda (_proc input)
141 (push input stderr-output))) 130 (push input stderr-output)))
142 (set-process-sentinel stderr-proc (lambda (_proc _input) 131 (set-process-sentinel stderr-proc (lambda (_proc _input)
143 (setq stderr-sentinel-called t))) 132 (setq stderr-sentinel-called t)))
144 (while (not (or sentinel-called 133 (process-test-wait-for-sentinel proc 20)
145 (> (- (float-time) start-time)
146 process-test-sentinel-wait-timeout)))
147 (accept-process-output))
148 (cl-assert (eq (process-status proc) 'exit))
149 (cl-assert (= (process-exit-status proc) 20))
150 (should sentinel-called)
151 (should (equal 1 (with-current-buffer stdout-buffer 134 (should (equal 1 (with-current-buffer stdout-buffer
152 (point-max)))) 135 (point-max))))
153 (should (equal "hello stdout!\n" 136 (should (equal "hello stdout!\n"
@@ -289,6 +272,74 @@
289 (error :got-error)))) 272 (error :got-error))))
290 (should have-called-debugger)))) 273 (should have-called-debugger))))
291 274
275(defun make-process/test-connection-type (ttys &rest args)
276 "Make a process and check whether its standard streams match TTYS.
277This calls `make-process', passing ARGS to adjust how the process
278is created. TTYS should be a list of 3 boolean values,
279indicating whether the subprocess's stdin, stdout, and stderr
280should be a TTY, respectively."
281 (declare (indent 1))
282 (let* (;; MS-Windows doesn't support communicating via pty.
283 (ttys (if (eq system-type 'windows-nt) '(nil nil nil) ttys))
284 (expected-output (concat (and (nth 0 ttys) "stdin\n")
285 (and (nth 1 ttys) "stdout\n")
286 (and (nth 2 ttys) "stderr\n")))
287 (stdout-buffer (generate-new-buffer "*stdout*"))
288 (proc (apply
289 #'make-process
290 :name "test"
291 :command (list "sh" "-c"
292 (concat "if [ -t 0 ]; then echo stdin; fi; "
293 "if [ -t 1 ]; then echo stdout; fi; "
294 "if [ -t 2 ]; then echo stderr; fi"))
295 :buffer stdout-buffer
296 args)))
297 (process-test-wait-for-sentinel proc 0)
298 (should (equal (with-current-buffer stdout-buffer (buffer-string))
299 expected-output))))
300
301(ert-deftest make-process/connection-type/pty ()
302 (skip-unless (executable-find "sh"))
303 (make-process/test-connection-type '(t t t)
304 :connection-type 'pty))
305
306(ert-deftest make-process/connection-type/pty-2 ()
307 (skip-unless (executable-find "sh"))
308 (make-process/test-connection-type '(t t t)
309 :connection-type '(pty . pty)))
310
311(ert-deftest make-process/connection-type/pipe ()
312 (skip-unless (executable-find "sh"))
313 (make-process/test-connection-type '(nil nil nil)
314 :connection-type 'pipe))
315
316(ert-deftest make-process/connection-type/pipe-2 ()
317 (skip-unless (executable-find "sh"))
318 (make-process/test-connection-type '(nil nil nil)
319 :connection-type '(pipe . pipe)))
320
321(ert-deftest make-process/connection-type/in-pty ()
322 (skip-unless (executable-find "sh"))
323 (make-process/test-connection-type '(t nil nil)
324 :connection-type '(pty . pipe)))
325
326(ert-deftest make-process/connection-type/out-pty ()
327 (skip-unless (executable-find "sh"))
328 (make-process/test-connection-type '(nil t t)
329 :connection-type '(pipe . pty)))
330
331(ert-deftest make-process/connection-type/pty-with-stderr-buffer ()
332 (skip-unless (executable-find "sh"))
333 (let ((stderr-buffer (generate-new-buffer "*stderr*")))
334 (make-process/test-connection-type '(t t nil)
335 :connection-type 'pty :stderr stderr-buffer)))
336
337(ert-deftest make-process/connection-type/out-pty-with-stderr-buffer ()
338 (skip-unless (executable-find "sh"))
339 (let ((stderr-buffer (generate-new-buffer "*stderr*")))
340 (make-process/test-connection-type '(nil t nil)
341 :connection-type '(pipe . pty) :stderr stderr-buffer)))
342
292(ert-deftest make-process/file-handler/found () 343(ert-deftest make-process/file-handler/found ()
293 "Check that the `:file-handler’ argument of `make-process’ 344 "Check that the `:file-handler’ argument of `make-process’
294works as expected if a file name handler is found." 345works as expected if a file name handler is found."