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
|
(include "../scsh-process.scm")
(import scsh-process)
(use test posix)
(test-begin "scsh-process")
(test-group "Procedural interface"
(test "Fork/pipe \"hello world\" example from SCSH reference manual"
"Hello, world."
(begin (fork/pipe
(lambda ()
(with-output-to-port (open-output-file* 1)
(lambda () (display "Hello, world.\n")))))
(read-line (open-input-file* 0))))
(test "run/string* returns a string output in a subprocess"
"This is a test"
(run/string* (lambda () (display "This is a test"))))
(test-error "run*/string* raises error if subprocess has nonzero exit status"
(run*/string* (lambda () (display "ohai") (exit 1)))))
(test-group "Macro (EPF) interface"
(delete-file* "outfile") ; Leftovers from last run
(test-group "Various run/... forms"
(test "Simple run/string"
"hi, there\n"
(run/string (echo "hi, there")))
(test "Simple run/sexp"
'("hi, there")
(run/sexp (echo "(\"hi, there\") trailing stuff is ignored")))
(test "Simple run/sexps"
'(("hi, there") (a b c))
(run/sexps (echo "(\"hi, there\") (a b c)")))
(test "Simple run/port"
'(a b c)
(read (run/port (echo "(a b c)"))))
(let ((tmpfile (run/file (echo "blah"))))
(test "Simple run/file"
"blah\n"
(with-input-from-file tmpfile read-all))
(test "Appending to a file"
'("blah" "foo")
(begin (run (echo foo) (>> ,tmpfile))
(read-lines tmpfile)))
(let ((message "testing, 1 2 3"))
(test "Redirecting from object"
`("blah" "foo" ,message)
(run/strings (cat ,tmpfile -) (<< ,message))))
(delete-file* tmpfile)))
(test-group "Subprocesses"
(let ((outfile "outfile"))
(test "Subprocess writing to a file"
"hi, there\n"
(begin (run (echo "hi, there") (> ,outfile))
(read-all "outfile"))))
(delete-file* "outfile")
(let ((echo-command 'echo))
(test "Subprocess piped to another process, writing to a file"
"1235\n"
(begin (run (pipe (,echo-command "1234" + 1) ("bc")) (> outfile))
(read-all "outfile"))))
(delete-file* "outfile")
(test "Nested output redirection with pipe+"
"foo\n"
(run/string (pipe+ ((1 0))
(pipe+ ((2 0)) (sh -c "echo foo >&2") (cat))
(cat))))
(test "Collecting FDs"
(list 0 "foo\n" "bar\n")
(receive (status port1 port2)
(run/collecting (2 1) (sh -c "echo foo >&2; echo bar"))
(list status (read-all port1) (read-all port2)))))
(test-group "Conditional process sequencing forms"
(test "&& runs for all true values"
(list #t "bar\n")
(list (&& (epf (echo "foo") (> outfile))
(true)
(epf (echo "bar") (> outfile)))
(read-all "outfile")))
(delete-file* "outfile")
(test "&& stops at first false value and returns false"
(list #f "foo\n")
(list (&& (epf (echo "foo") (> outfile))
(false)
(epf (echo "bar") (> outfile)))
(read-all "outfile")))
(delete-file* "outfile")
(test "|| stops at first true value and returns true"
(list #t "foo\n")
(list (|| (epf (echo "foo") (> outfile))
(true)
(epf (echo "bar") (> outfile)))
(read-all "outfile")))
(delete-file* "outfile")
(test "|| continues after first false value and returns true"
(list #t "bar\n")
(list (|| (false)
(epf (echo "bar") (> outfile)))
(read-all "outfile")))
(delete-file* "outfile")
(test "|| continues beyond all false values and returns false"
#f
(|| (false) (epf (sh -c "echo hi && false") (- 1))))))
;; TODO: Find a way to test that the input port didn't get replaced by
;; one from a subshell. This happened before, but not sure how
;; to detect this except running it manually from the REPL.
(test-end)
(test-exit)
|