mirror of
git://git.code.sf.net/p/sbcl/sbcl
synced 2026-09-10 07:26:40 -04:00
155 lines
6.2 KiB
Bash
Executable file
155 lines
6.2 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
# tests related to SB-EXT:RUN-PROGRAM
|
|
|
|
# This software is part of the SBCL system. See the README file for
|
|
# more information.
|
|
#
|
|
# While most of SBCL is derived from the CMU CL system, the test
|
|
# files (like this one) were written from scratch after the fork
|
|
# from CMU CL.
|
|
#
|
|
# This software is in the public domain and is provided with
|
|
# absolutely no warranty. See the COPYING and CREDITS files for
|
|
# more information.
|
|
|
|
. ./subr.sh
|
|
|
|
# Make sure that there's at least something in the environment (for
|
|
# one of the tests below).
|
|
SOMETHING_IN_THE_ENVIRONMENT='yes there is'
|
|
export SOMETHING_IN_THE_ENVIRONMENT
|
|
PATH=/some/path/that/does/not/exist:${PATH}
|
|
export PATH
|
|
|
|
# Increase potential soft ulimit on file descriptors for file
|
|
# descriptor test case below.
|
|
test `ulimit -n` -ge 1050 || ulimit -S -n `ulimit -H -n`
|
|
|
|
# This should probably be broken up into separate pieces.
|
|
run_sbcl --eval "(defvar *exit-ok* $EXIT_LISP_WIN)" <<'EOF'
|
|
(defmacro our-run-program (name &rest rest)
|
|
#+unix `(run-program ,name ,@rest)
|
|
#-unix `(run-program ,(subseq name (1+ (position #\/ name :from-end t)))
|
|
,@rest :search t))
|
|
|
|
;; test that $PATH is searched
|
|
(assert (zerop (sb-ext:process-exit-code
|
|
(sb-ext:run-program "true" () :search t :wait t))))
|
|
(assert (not (zerop (sb-ext:process-exit-code
|
|
(sb-ext:run-program "false" () :search t :wait t)))))
|
|
(let ((string (with-output-to-string (stream)
|
|
(run-program "echo" '("foo" "bar")
|
|
:search t :output stream))))
|
|
(assert (string= string "foo bar
|
|
")))
|
|
(format t ";;; Smoke tests: PASS~%")
|
|
|
|
#+unix
|
|
(defconstant unix-env
|
|
#+haiku
|
|
"/bin/env"
|
|
#-haiku
|
|
"/usr/bin/env")
|
|
|
|
;; Unix environment strings are ordinarily passed with SBCL convention
|
|
;; (instead of CMU CL alist-of-keywords convention).
|
|
#+unix ; env works differently for msys2 apparently
|
|
(let ((string (with-output-to-string (stream)
|
|
(sb-ext:run-program unix-env ()
|
|
:output stream
|
|
:environment '("FEEFIE=foefum")))))
|
|
(assert (equal string "FEEFIE=foefum
|
|
")))
|
|
|
|
;;; Try to obtain file descriptors numerically greater than FD_SETSIZE
|
|
;;; (which is usually 1024) to show that run-program uses poll() rather
|
|
;;; than select(), but if we can't do that, then don't.
|
|
(when (fboundp (find-symbol "UNIX-POLL" "SB-UNIX"))
|
|
(let ((f (open "/dev/null"))
|
|
(got-error)
|
|
(opened))
|
|
(with-alien ((dup (function int int) :extern))
|
|
(dotimes (i 1025)
|
|
(let ((new (alien-funcall dup (sb-impl::fd-stream-fd f))))
|
|
(when (< new 0)
|
|
;; We've no constant for EMFILE, just assume that's the problem
|
|
(return (setq got-error t)))
|
|
(push new opened))))
|
|
(if got-error ; close a bunch
|
|
(dotimes (i 6) (sb-unix:unix-close (pop opened)))
|
|
(assert (> (car opened) 1024)))))
|
|
|
|
;; Unicode strings
|
|
#+unix
|
|
(flet ((try (sb-impl::*default-external-format* x y)
|
|
(let* ((process (run-program
|
|
"/bin/sh" (list "-c" (format nil "echo ~c, $SB_TEST_FOO." x))
|
|
:environment (list (format nil "SB_TEST_FOO=~c" y))
|
|
:output :stream
|
|
:wait t))
|
|
(output (read-line (process-output process)))
|
|
(wanted (format nil "~c, ~c." x y)))
|
|
(unless (equal output wanted)
|
|
(error "wanted ~S, got ~S" wanted output))
|
|
(process-close process))))
|
|
(try :ascii #\s #\b)
|
|
(try :latin-1 (code-char 197) (code-char 229))
|
|
#+sb-unicode
|
|
(try :utf-8 #\GREEK_CAPITAL_LETTER_OMEGA #\GREEK_SMALL_LETTER_OMEGA))
|
|
|
|
;; The default Unix environment for the subprocess is the same as
|
|
;; for the parent process. (I.e., we behave like perl and lots of
|
|
;; other programs, but not like CMU CL.)
|
|
#+unix
|
|
(let* ((sb-impl::*default-external-format* :latin-1)
|
|
(sb-alien::*default-c-string-external-format* :latin-1)
|
|
(string (with-output-to-string (stream)
|
|
(sb-ext:run-program unix-env ()
|
|
:output stream)))
|
|
(expected (apply #'concatenate
|
|
'string
|
|
(mapcar (lambda (environ-string)
|
|
(concatenate 'string
|
|
environ-string
|
|
(string #\newline)))
|
|
(sb-ext:posix-environ)))))
|
|
(assert (string= string expected))
|
|
;; That's not just because POSIX-ENVIRON is having a bad hair
|
|
;; day and returning NIL, is it?
|
|
(assert (plusp (length (sb-ext:posix-environ)))))
|
|
;; make sure that a stream input argument is basically reasonable.
|
|
(let ((string (let ((i (make-string-input-stream "abcdef")))
|
|
(with-output-to-string (stream)
|
|
(run-program "cat" ()
|
|
:search t :input i :output stream)))))
|
|
(assert (= (length string) 6))
|
|
(assert (string= string "abcdef")))
|
|
|
|
;;; Test the bookkeeping involved in decoding the child's output:
|
|
|
|
;; repeated short, properly-encoded reads exposed one bug. (But
|
|
;; note: this test will be inconclusive if the child's stderr is
|
|
;; fully buffered.)
|
|
(let ((str (with-output-to-string (s)
|
|
(our-run-program "/bin/sh"
|
|
'("-c" "(echo Foo; sleep 2; echo Bar)>&2")
|
|
:output s :search t :error :output :wait t))))
|
|
(assert (string= str (format nil "Foo~%Bar~%"))))
|
|
|
|
;; end of file in the middle of a UTF-8 character
|
|
;; (FIXME: asserting failure without knowing why is almost as good as no test at all.)
|
|
(typep (nth-value 1 (ignore-errors
|
|
(let ((sb-impl::*default-external-format* :utf-8))
|
|
(with-output-to-string (s)
|
|
(run-program "printf" '("\\316")
|
|
:output s :search t :wait t)))))
|
|
'error)
|
|
|
|
;; success convention for this Lisp program run as part of a larger script
|
|
(sb-ext:quit :unix-status *exit-ok*)))
|
|
EOF
|
|
check_status_maybe_lose "run program tests" $?
|
|
|
|
exit $EXIT_TEST_WIN
|