File: run-program.test.sh

package info (click to toggle)
sbcl 2%3A2.6.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 52,008 kB
  • sloc: lisp: 535,135; ansic: 42,629; sh: 5,737; asm: 2,406; pascal: 717; makefile: 432; python: 56; cpp: 27
file content (154 lines) | stat: -rwxr-xr-x 6,322 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/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