X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=tests%2Frun-program.impure.lisp;h=46238b9c5ceae0ff642589be8acbb037b2a3ca14;hb=a7e90050c1617168d162b7219c4aeede3e90205a;hp=a9d36326e57fc922e4e73fa439883a276d6e50cf;hpb=0a477f244a6bf9a751603042d2b66f7e9c13e309;p=sbcl.git diff --git a/tests/run-program.impure.lisp b/tests/run-program.impure.lisp index a9d3632..46238b9 100644 --- a/tests/run-program.impure.lisp +++ b/tests/run-program.impure.lisp @@ -54,10 +54,10 @@ (defparameter *cat-out* (make-synonym-stream '*cat-out-pipe*)) (with-test (:name :run-program-cat-2) - (let ((cat (run-program "/bin/cat" nil :input *cat-in* :output *cat-out* + (let ((cat (run-program "/bin/cat" nil :input *cat-in* :output *cat-out* :wait nil))) - (dolist (test '("This is a test!" - "This is another test!" + (dolist (test '("This is a test!" + "This is another test!" "This is the last test....")) (write-line test *cat-in*) (assert (equal test (read-line *cat-out*)))) @@ -65,7 +65,7 @@ ;;; The above test used to use ed, but there were buffering issues: on some platforms ;;; buffering of stdin and stdout depends on their TTYness, and ed isn't sufficiently -;;; agressive about flushing them. So, here's another test using :PTY. +;;; agressive about flushing them. So, here's another test using :PTY. (defparameter *tmpfile* "run-program-ed-test.tmp") @@ -84,25 +84,92 @@ (defun read-linish (stream) (with-output-to-string (s) (loop for c = (read-char stream) - while (and c (not (eq #\newline c)) (not (eq #\return c))) - do (write-char c s)))) + while (and c (not (eq #\newline c))) + ;; Some eds like to send \r\n + do (unless (eq #\return c) + (write-char c s))))) (defun assert-ed (command response) (when command (write-line command *ed-in*) (force-output *ed-in*)) - (let ((got (read-linish *ed-out*))) - (unless (equal response got) - (error "wanted ~S from ed, got ~S" response got))) + (when response + (let ((got (read-linish *ed-out*))) + (unless (equal response got) + (error "wanted '~A' from ed, got '~A'" response got)))) *ed*) (unwind-protect - (with-test (:name :run-program-ed) + (with-test (:name :run-program-ed) (assert-ed nil "4") - (assert-ed ".s/bar/baz/g" "") + (assert-ed ".s/bar/baz/g" nil) (assert-ed "w" "4") - (assert-ed "q" "") + (assert-ed "q" nil) (process-wait *ed*) (with-open-file (f *tmpfile*) (assert (equal "baz" (read-line f))))) (delete-file *tmpfile*)) + +;; Around 1.0.12 there was a regression when :INPUT or :OUTPUT was a +;; pathname designator. Since these use the same code, it should +;; suffice to test just :INPUT. +(let ((file)) + (unwind-protect + (progn (with-open-file (f "run-program-test.tmp" :direction :output) + (setf file (truename f)) + (write-line "Foo" f)) + (assert (run-program "cat" () + :input file :output t + :search t :wait t))) + (when file + (delete-file file)))) + +;;; This used to crash on Darwin and trigger recursive lock errors on +;;; every platform. +(with-test (:name (:run-program :stress)) + ;; Do it a hundred times in batches of 10 so that with a low limit + ;; of the number of processes the test can have a chance to pass. + (loop + repeat 10 do + (map nil + #'sb-ext:process-wait + (loop repeat 10 + collect + (sb-ext:run-program "/bin/echo" ' + ("It would be nice if this didn't crash.") + :wait nil :output nil))))) + +(with-test (:name (:run-program :pty-stream)) + (assert (equal "OK" + (subseq + (with-output-to-string (s) + (assert (= 42 (process-exit-code + (run-program "/bin/sh" '("-c" "echo OK; exit 42") :wait t + :pty s)))) + s) + 0 + 2)))) + +;; Check whether RUN-PROGRAM puts its child process into the foreground +;; when stdin is inherited. If it fails to do so we will receive a SIGTTIN. +;; +;; We can't check for the signal itself since run-program.c resets the +;; forked process' signal mask to defaults. But the default is `stop' +;; of which we can be notified asynchronously by providing a status hook. +(with-test (:name (:run-program :inherit-stdin)) + (let (stopped) + (flet ((status-hook (proc) + (case (sb-ext:process-status proc) + (:stopped (setf stopped t))))) + (let ((proc (sb-ext:run-program "/bin/ed" nil :search nil :wait nil + :input t :output t + :status-hook #'status-hook))) + ;; Give the program a generous time to generate the SIGTTIN. + ;; If it hasn't done so after that time we can consider it + ;; to be working (i.e. waiting for input without generating SIGTTIN). + (sleep 0.5) + ;; either way we have to signal it to terminate + (process-kill proc sb-posix:sigterm) + (process-close proc) + (assert (not stopped)))))) +