diff options
| author | Daiki Ueno | 2015-04-07 17:42:09 +0900 |
|---|---|---|
| committer | Daiki Ueno | 2015-04-11 07:59:27 +0900 |
| commit | f55ea05bdf60e24c09f9064fc0d2e8a114d6e358 (patch) | |
| tree | ed901f31fffe7afa1d4644dd9980042d7b35895b /test | |
| parent | a2940cd43e7931d16d3a3ce2cf5d4acd148dd00c (diff) | |
| download | emacs-f55ea05bdf60e24c09f9064fc0d2e8a114d6e358.tar.gz emacs-f55ea05bdf60e24c09f9064fc0d2e8a114d6e358.zip | |
Add facility to collect stderr of async subprocess
* src/w32.h (register_aux_fd): New function declaration.
* src/w32.c (register_aux_fd): New function.
* src/process.h (struct Lisp_Process): New member stderrproc.
* src/process.c (PIPECONN_P): New macro.
(PIPECONN1_P): New macro.
(Fdelete_process, Fprocess_status, Fset_process_buffer)
(Fset_process_filter, Fset_process_sentinel, Fstop_process)
(Fcontinue_process): Handle pipe process specially.
(create_process): Respect p->stderrproc.
(Fmake_pipe_process): New function.
(Fmake_process): Add new keyword argument :stderr.
(wait_reading_process_output): Specially handle a pipe process when
it gets an EOF.
(syms_of_process): Register Qpipe and Smake_pipe_process.
* doc/lispref/processes.texi (Asynchronous Processes): Document
`make-pipe-process' and `:stderr' keyword of `make-process'.
* lisp/subr.el (start-process): Suggest to use `make-process' handle
standard error separately.
* test/automated/process-tests.el (process-test-stderr-buffer)
(process-test-stderr-filter): New tests.
* etc/NEWS: Mention new process type `pipe' and its usage with the
`:stderr' keyword of `make-process'.
Diffstat (limited to 'test')
| -rw-r--r-- | test/automated/process-tests.el | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/test/automated/process-tests.el b/test/automated/process-tests.el index dabfbc56b78..1dab615bed0 100644 --- a/test/automated/process-tests.el +++ b/test/automated/process-tests.el | |||
| @@ -72,4 +72,74 @@ | |||
| 72 | (should (string= (buffer-string) "arg1 = \"x &y\", arg2 = \n")))) | 72 | (should (string= (buffer-string) "arg1 = \"x &y\", arg2 = \n")))) |
| 73 | (when batfile (delete-file batfile)))))) | 73 | (when batfile (delete-file batfile)))))) |
| 74 | 74 | ||
| 75 | (ert-deftest process-test-stderr-buffer () | ||
| 76 | (skip-unless (executable-find "bash")) | ||
| 77 | (let* ((stdout-buffer (generate-new-buffer "*stdout*")) | ||
| 78 | (stderr-buffer (generate-new-buffer "*stderr*")) | ||
| 79 | (proc (make-process :name "test" | ||
| 80 | :command (list "bash" "-c" | ||
| 81 | (concat "echo hello stdout!; " | ||
| 82 | "echo hello stderr! >&2; " | ||
| 83 | "exit 20")) | ||
| 84 | :buffer stdout-buffer | ||
| 85 | :stderr stderr-buffer)) | ||
| 86 | (sentinel-called nil) | ||
| 87 | (start-time (float-time))) | ||
| 88 | (set-process-sentinel proc (lambda (proc msg) | ||
| 89 | (setq sentinel-called t))) | ||
| 90 | (while (not (or sentinel-called | ||
| 91 | (> (- (float-time) start-time) | ||
| 92 | process-test-sentinel-wait-timeout))) | ||
| 93 | (accept-process-output)) | ||
| 94 | (cl-assert (eq (process-status proc) 'exit)) | ||
| 95 | (cl-assert (= (process-exit-status proc) 20)) | ||
| 96 | (should (with-current-buffer stdout-buffer | ||
| 97 | (goto-char (point-min)) | ||
| 98 | (looking-at "hello stdout!"))) | ||
| 99 | (should (with-current-buffer stderr-buffer | ||
| 100 | (goto-char (point-min)) | ||
| 101 | (looking-at "hello stderr!"))))) | ||
| 102 | |||
| 103 | (ert-deftest process-test-stderr-filter () | ||
| 104 | (skip-unless (executable-find "bash")) | ||
| 105 | (let* ((sentinel-called nil) | ||
| 106 | (stderr-sentinel-called nil) | ||
| 107 | (stdout-output nil) | ||
| 108 | (stderr-output nil) | ||
| 109 | (stdout-buffer (generate-new-buffer "*stdout*")) | ||
| 110 | (stderr-buffer (generate-new-buffer "*stderr*")) | ||
| 111 | (stderr-proc (make-pipe-process :name "stderr" | ||
| 112 | :buffer stderr-buffer)) | ||
| 113 | (proc (make-process :name "test" :buffer stdout-buffer | ||
| 114 | :command (list "bash" "-c" | ||
| 115 | (concat "echo hello stdout!; " | ||
| 116 | "echo hello stderr! >&2; " | ||
| 117 | "exit 20")) | ||
| 118 | :stderr stderr-proc)) | ||
| 119 | (start-time (float-time))) | ||
| 120 | (set-process-filter proc (lambda (proc input) | ||
| 121 | (push input stdout-output))) | ||
| 122 | (set-process-sentinel proc (lambda (proc msg) | ||
| 123 | (setq sentinel-called t))) | ||
| 124 | (set-process-filter stderr-proc (lambda (proc input) | ||
| 125 | (push input stderr-output))) | ||
| 126 | (set-process-sentinel stderr-proc (lambda (proc input) | ||
| 127 | (setq stderr-sentinel-called t))) | ||
| 128 | (while (not (or sentinel-called | ||
| 129 | (> (- (float-time) start-time) | ||
| 130 | process-test-sentinel-wait-timeout))) | ||
| 131 | (accept-process-output)) | ||
| 132 | (cl-assert (eq (process-status proc) 'exit)) | ||
| 133 | (cl-assert (= (process-exit-status proc) 20)) | ||
| 134 | (should sentinel-called) | ||
| 135 | (should (equal 1 (with-current-buffer stdout-buffer | ||
| 136 | (point-max)))) | ||
| 137 | (should (equal "hello stdout!\n" | ||
| 138 | (mapconcat #'identity (nreverse stdout-output) ""))) | ||
| 139 | (should stderr-sentinel-called) | ||
| 140 | (should (equal 1 (with-current-buffer stderr-buffer | ||
| 141 | (point-max)))) | ||
| 142 | (should (equal "hello stderr!\n" | ||
| 143 | (mapconcat #'identity (nreverse stderr-output) ""))))) | ||
| 144 | |||
| 75 | (provide 'process-tests) | 145 | (provide 'process-tests) |