summaryrefslogtreecommitdiff
path: root/tests/run.scm
blob: ae12600d213b2398af4788b170dd073f777e5fa6 (plain)
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
#;(include "../scsh-process.scm")
(use scsh-process)

(use test posix srfi-13)

(test-begin "scsh-process")

(test-group "Procedural interface"
  (test "Fork/pipe \"hello world\" example from SCSH reference manual"
        '(0 #t "Hello, world.")
        (receive (exit-status exited-ok? pid)
          (wait (fork/pipe
                 (lambda ()
                   (with-output-to-port (open-output-file* 1)
                     (lambda () (display "Hello, world.\n"))))))
          (list exit-status exited-ok? (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" ,(string-delete #\t message))
              (run/strings (pipe (epf (tr -d t) (<< ,message))
                                 (cat ,tmpfile -)))))
      (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)
                              ("sh" -c "read foo; echo $(($foo))"))
                        (> 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))))))

(test-group "finalization"
  ;; 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-error "No more zombies lying around after we're done" (wait)))

(test-end)

(test-exit)