Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/liii_subprocess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,11 @@ f_subprocess_run_values (s7_scheme* sc, s7_pointer args) {
}
else if (stdout_mode == redirect_mode::discard) {
attr.outtype = TB_PROCESS_REDIRECT_TYPE_FILEPATH;
#ifdef TB_CONFIG_OS_WINDOWS
attr.out.path = "NUL";
#else
attr.out.path = "/dev/null";
#endif
attr.outmode = TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC;
}
else if (need_stdout_pipe) {
Expand All @@ -201,7 +205,11 @@ f_subprocess_run_values (s7_scheme* sc, s7_pointer args) {
}
else if (stderr_mode == redirect_mode::discard) {
attr.errtype = TB_PROCESS_REDIRECT_TYPE_FILEPATH;
#ifdef TB_CONFIG_OS_WINDOWS
attr.err.path = "NUL";
#else
attr.err.path = "/dev/null";
#endif
attr.errmode = TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC;
}
else if (stderr_to_stdout && out_pipe[1]) {
Expand Down Expand Up @@ -240,8 +248,12 @@ f_subprocess_run_values (s7_scheme* sc, s7_pointer args) {
tb_process_ref_t process = tb_null;
if (s7_is_string (cmd_arg)) {
const char* cmd_c = s7_string (cmd_arg);
#ifdef TB_CONFIG_OS_WINDOWS
process = tb_process_init_cmd (cmd_c, &attr);
#else
tb_char_t const* sh_argv[] = {"sh", "-c", cmd_c, tb_null};
process = tb_process_init ("/bin/sh", sh_argv, &attr);
#endif
}
else if (s7_is_pair (cmd_arg)) {
vector<const char*> argv;
Expand Down
47 changes: 47 additions & 0 deletions tests/liii/subprocess-test.scm
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,51 @@
(check-catch 'value-error (run '(echo-cmd "hello")))
) ;when

(when (os-windows?)
;; run basic tests
(check (zero? (run "python3 -c pass")) => #t)
(check (zero? (run "python3 -c 1/0")) => #f)
(check (run "python3 -c print('hello')") => 0)

(let ((orig-dir (getcwd)))
(run "python3 -c pass" :cwd (os-temp-dir))
(check (getcwd) => orig-dir)
) ;let

(check-catch 'value-error (run "cd /tmp" :cwd (os-temp-dir)))
(check-catch 'value-error (run '(cd "/tmp") :cwd (os-temp-dir)))

;; run-set! / run-get tests
(run-set! 'pytrue "python3")
(check (zero? (run '(pytrue "-c" "pass"))) => #t)

(run-set! 'py-lambda (lambda () (display "ok\n")))
(check (zero? (run '(py-lambda))) => #t)

(check (path? (run-get 'pytrue)) => #t)
(check (run-get 'not-exist) => #f)

(run-set! 'custom-lambda (lambda () (display "ok\n")))
(check (procedure? (run-get 'custom-lambda)) => #t)

;; run-allow! tests
(run-allow! 'pytrue)
(check (zero? (run '(pytrue "-c" "pass"))) => #t)
(check-catch 'value-error (run '(py-lambda)))

(run-allow! '())
(check (zero? (run '(py-lambda))) => #t)

(run-allow! '(pytrue py-lambda))
(check (zero? (run '(pytrue "-c" "pass"))) => #t)
(check (zero? (run '(py-lambda))) => #t)
(check-catch 'value-error (run '(unknown-cmd)))

(run-allow! '())

;; run-ban! tests
(run-ban! 'pytrue)
(check-catch 'value-error (run '(pytrue "-c" "pass")))
) ;when

(check-report)
19 changes: 19 additions & 0 deletions tests/liii/subprocess/run-allow-bang-test.scm
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,23 @@
(run-allow! '())
)

(when (os-windows?)
(run-set! 'pytrue "python3")
(run-set! 'pyfalse "python3")

(run-allow! 'pytrue)
(check (zero? (run '(pytrue "-c" "pass"))) => #t)
(check-catch 'value-error (run '(pyfalse "-c" "1/0")))

(run-allow! '())
(check (zero? (run '(pyfalse "-c" "1/0"))) => #f)

(run-allow! '(pytrue pyfalse))
(check (zero? (run '(pytrue "-c" "pass"))) => #t)
(check (zero? (run '(pyfalse "-c" "1/0"))) => #f)
(check-catch 'value-error (run '(unknown-cmd)))

(run-allow! '())
)

(check-report)
28 changes: 28 additions & 0 deletions tests/liii/subprocess/run-and-test.scm
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,32 @@
(check (to-left (run-and "true" "false" "true")) => '(1 "false"))
) ;when

(when (os-windows?)
(check (either-right? (run-and "python3 -c pass" "python3 -c pass")) => #t)
(check (to-right (run-and "python3 -c pass" "python3 -c pass")) => 0)
(check (either-left? (run-and "python3 -c 1/0" "python3 -c pass")) => #t)
(check (to-left (run-and "python3 -c 1/0" "python3 -c pass")) => '(1 "python3 -c 1/0"))
(check (either-left? (run-and "python3 -c pass" "python3 -c 1/0")) => #t)
(check (to-left (run-and "python3 -c pass" "python3 -c 1/0")) => '(1 "python3 -c 1/0"))
(check (either-right? (run-and "python3 -c pass" "python3 -c pass" :cwd (os-temp-dir))) => #t)
(check (to-right (run-and "python3 -c pass" "python3 -c pass" :cwd (os-temp-dir))) => 0)
(let ((path-env (getenv "PATH")))
(check (either-right? (run-and "python3 -c pass" :env `(("FOO" . "bar") ("PATH" . ,path-env)))) => #t)
(check (to-right (run-and "python3 -c pass" :env `(("FOO" . "bar") ("PATH" . ,path-env)))) => 0))

;; :stdout only on last
(let ((tmpfile (string-append (os-temp-dir) "/gf-run-and-stdout-win.txt")))
(when (file-exists? tmpfile) (delete-file tmpfile))
(check (either-right? (run-and "python3 -c pass" "python3 -c pass" :stdout tmpfile)) => #t)
(check (to-right (run-and "python3 -c pass" "python3 -c pass" :stdout tmpfile)) => 0)
(when (file-exists? tmpfile) (delete-file tmpfile))
) ;let

;; Multiple commands
(check (either-right? (run-and "python3 -c pass" "python3 -c pass" "python3 -c pass")) => #t)
(check (to-right (run-and "python3 -c pass" "python3 -c pass" "python3 -c pass")) => 0)
(check (either-left? (run-and "python3 -c pass" "python3 -c 1/0" "python3 -c pass")) => #t)
(check (to-left (run-and "python3 -c pass" "python3 -c 1/0" "python3 -c pass")) => '(1 "python3 -c 1/0"))
) ;when

(check-report)
17 changes: 17 additions & 0 deletions tests/liii/subprocess/run-ban-bang-test.scm
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,21 @@
(check (zero? (run "true")) => #t)
) ;when

(when (os-windows?)
;; 符号命令禁止与取消
(run-set! 'pytrue "python3")
(run-ban! 'pytrue)
(check-catch 'value-error (run '(pytrue "-c" "pass")))

(run-unban! 'pytrue)
(check (zero? (run '(pytrue "-c" "pass"))) => #t)

;; 'rm 默认被禁止(字符串形式)
(check-catch 'value-error (run "rm -rf /tmp/test"))
(check-catch 'value-error (run "rm"))

;; 其他命令不受影响
(check (zero? (run "python3 -c pass")) => #t)
) ;when

(check-report)
57 changes: 57 additions & 0 deletions tests/liii/subprocess/run-either-test.scm
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,61 @@
(check (to-right (run-either '(printf "%s" "hello world") :stdout 'capture)) => "hello world")
) ;when

(when (os-windows?)
;; basic success
(let ((tmpfile (string-append (os-temp-dir) "/gf-run-either-out-win.txt")))
(when (file-exists? tmpfile) (delete-file tmpfile))
(check (either-right? (run-either "python3 -c pass" :stdout tmpfile :stderr 'discard)) => #t)
(check (to-right (run-either "python3 -c pass" :stdout tmpfile :stderr 'discard)) => "")
(when (file-exists? tmpfile) (delete-file tmpfile))
) ;let

;; basic failure
(let ((tmpfile (string-append (os-temp-dir) "/gf-run-either-out2-win.txt")))
(when (file-exists? tmpfile) (delete-file tmpfile))
(check (either-left? (run-either "python3 -c 1/0" :stdout tmpfile :stderr 'discard)) => #t)
(let ((result (to-left (run-either "python3 -c 1/0" :stdout tmpfile :stderr 'discard))))
(check (number? (car result)) => #t)
(check (string? (cdr result)) => #t))
(when (file-exists? tmpfile) (delete-file tmpfile))
) ;let

;; :cwd
(let ((tmpfile (string-append (os-temp-dir) "/gf-run-either-cwd-win.txt")))
(when (file-exists? tmpfile) (delete-file tmpfile))
(check (either-right? (run-either "python3 -c pass" :cwd (os-temp-dir) :stdout tmpfile :stderr 'discard)) => #t)
(when (file-exists? tmpfile) (delete-file tmpfile))
) ;let

;; :env
(let ((tmpfile (string-append (os-temp-dir) "/gf-run-either-env-win.txt"))
(path-env (getenv "PATH")))
(when (file-exists? tmpfile) (delete-file tmpfile))
(check (either-right? (run-either "python3 -c pass" :env `(("FOO" . "bar") ("PATH" . ,path-env)) :stdout tmpfile :stderr 'discard)) => #t)
(when (file-exists? tmpfile) (delete-file tmpfile))
) ;let

;; :stdout to file
(let ((tmpfile (string-append (os-temp-dir) "/gf-run-either-file-win.txt")))
(when (file-exists? tmpfile) (delete-file tmpfile))
(check (either-right? (run-either "python3 -c print('hello')" :stdout tmpfile :stderr 'discard)) => #t)
(check (to-right (run-either "python3 -c print('hello')" :stdout tmpfile :stderr 'discard)) => "")
(check (path-read-text tmpfile) => "hello\n")
(when (file-exists? tmpfile) (delete-file tmpfile))
) ;let

;; :stdout 'discard
(check (either-right? (run-either "python3 -c pass" :stdout 'discard :stderr 'discard)) => #t)
(check (to-right (run-either "python3 -c pass" :stdout 'discard :stderr 'discard)) => "")

;; list form with symbol head
(run-set! 'pypass "python3")
(let ((tmpfile (string-append (os-temp-dir) "/gf-run-either-list-win.txt")))
(when (file-exists? tmpfile) (delete-file tmpfile))
(check (either-right? (run-either '(pypass "-c" "print('hello world')") :stdout tmpfile :stderr 'discard)) => #t)
(check (to-right (run-either '(pypass "-c" "print('hello world')") :stdout tmpfile :stderr 'discard)) => "")
(when (file-exists? tmpfile) (delete-file tmpfile))
) ;let
) ;when

(check-report)
9 changes: 9 additions & 0 deletions tests/liii/subprocess/run-get-test.scm
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,13 @@
(check (procedure? (run-get 'custom-lambda)) => #t)
)

(when (os-windows?)
(run-set! 'pytrue "python3")
(check (path? (run-get 'pytrue)) => #t)
(check (run-get 'not-exist) => #f)

(run-set! 'custom-lambda (lambda () (display "ok\n")))
(check (procedure? (run-get 'custom-lambda)) => #t)
)

(check-report)
10 changes: 10 additions & 0 deletions tests/liii/subprocess/run-if-test.scm
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,14 @@
(check (to-left (run-if "false" "echo yes" "false")) => '(1 "false"))
) ;when

(when (os-windows?)
(check (either-right? (run-if "python3 -c 1/0" "python3 -c pass" "python3 -c pass")) => #t)
(check (to-right (run-if "python3 -c 1/0" "python3 -c pass" "python3 -c pass")) => 0)

(check (either-left? (run-if "python3 -c pass" "python3 -c 1/0" "python3 -c pass")) => #t)
(check (to-left (run-if "python3 -c pass" "python3 -c 1/0" "python3 -c pass")) => '(1 "python3 -c 1/0"))
(check (either-left? (run-if "python3 -c 1/0" "python3 -c pass" "python3 -c 1/0")) => #t)
(check (to-left (run-if "python3 -c 1/0" "python3 -c pass" "python3 -c 1/0")) => '(1 "python3 -c 1/0"))
) ;when

(check-report)
11 changes: 11 additions & 0 deletions tests/liii/subprocess/run-or-test.scm
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,15 @@
(check (to-right (run-or "true" "false" :cwd "/tmp")) => 0)
) ;when

(when (os-windows?)
(check (either-right? (run-or "python3 -c pass" "python3 -c 1/0")) => #t)
(check (to-right (run-or "python3 -c pass" "python3 -c 1/0")) => 0)
(check (either-left? (run-or "python3 -c 1/0" "python3 -c 1/0")) => #t)
(check (to-left (run-or "python3 -c 1/0" "python3 -c 1/0")) => '(1 "python3 -c 1/0"))
(check (either-right? (run-or "python3 -c 1/0" "python3 -c pass")) => #t)
(check (to-right (run-or "python3 -c 1/0" "python3 -c pass")) => 0)
(check (either-right? (run-or "python3 -c pass" "python3 -c 1/0" :cwd (os-temp-dir))) => #t)
(check (to-right (run-or "python3 -c pass" "python3 -c 1/0" :cwd (os-temp-dir))) => 0)
) ;when

(check-report)
9 changes: 9 additions & 0 deletions tests/liii/subprocess/run-pipe-test.scm
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,13 @@
(check (to-left (run-pipe "echo hello" '(false))) => '(1 (false)))
) ;when

(when (os-windows?)
;; run-pipe relies on :stdout 'capture internally, which doesn't work reliably on Windows
;; multi-command pipe fails because capture returns empty string
(check (either-left? (run-pipe "python3 -c print('hello')" "python3 -c pass")) => #t)

;; single command pipe succeeds because the command exits with 0 (though output is empty)
(check (either-right? (run-pipe "python3 -c pass")) => #t)
) ;when

(check-report)
11 changes: 11 additions & 0 deletions tests/liii/subprocess/run-sequence-test.scm
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,15 @@
(check (to-right (run-sequence "true" "true" :cwd "/tmp")) => 0)
) ;when

(when (os-windows?)
(check (either-right? (run-sequence "python3 -c pass" "python3 -c 1/0" "python3 -c pass")) => #t)
(check (to-right (run-sequence "python3 -c pass" "python3 -c 1/0" "python3 -c pass")) => 0)
(check (either-right? (run-sequence "python3 -c 1/0" "python3 -c pass")) => #t)
(check (to-right (run-sequence "python3 -c 1/0" "python3 -c pass")) => 0)
(check (either-left? (run-sequence "python3 -c pass" "python3 -c 1/0")) => #t)
(check (to-left (run-sequence "python3 -c pass" "python3 -c 1/0")) => 1)
(check (either-right? (run-sequence "python3 -c pass" "python3 -c pass" :cwd (os-temp-dir))) => #t)
(check (to-right (run-sequence "python3 -c pass" "python3 -c pass" :cwd (os-temp-dir))) => 0)
) ;when

(check-report)
11 changes: 11 additions & 0 deletions tests/liii/subprocess/run-set-bang-test.scm
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,15 @@
(check (zero? (run '(my-lambda))) => #t)
)

(when (os-windows?)
(run-set! 'pytrue "python3")
(check (zero? (run '(pytrue "-c" "pass"))) => #t)

(run-set! 'pyfalse "python3")
(check (zero? (run '(pyfalse "-c" "1/0"))) => #f)

(run-set! 'my-lambda (lambda () (display "ok\n")))
(check (zero? (run '(my-lambda))) => #t)
)

(check-report)
22 changes: 22 additions & 0 deletions tests/liii/subprocess/run-test.scm
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,26 @@
(check (run '(printf "%s" "hello world")) => 0)
) ;when

(when (os-windows?)
(check (zero? (run "python3 -c pass")) => #t)
(check (zero? (run "python3 -c 1/0")) => #f)
(check (run "python3 -c print('hello')") => 0)

(let ((orig-dir (getcwd)))
(run "python3 -c pass" :cwd (os-temp-dir))
(check (getcwd) => orig-dir)
) ;let

(check-catch 'value-error (run "cd /tmp" :cwd (os-temp-dir)))
(check-catch 'value-error (run '(cd "/tmp") :cwd (os-temp-dir)))

;; :env (need to preserve PATH on Windows)
(let ((path-env (getenv "PATH")))
(check (run "python3 -c pass" :env `(("FOO" . "bar") ("PATH" . ,path-env))) => 0))

;; list form with symbol head
(run-set! 'pyprint "python3")
(check (run '(pyprint "-c" "print('hello world')")) => 0)
) ;when

(check-report)
Loading
Loading