]> Repositorios git - scryer-prolog.git/commitdiff
Test that SIGINT interrupts non-terminating goals on unix.
authorDanil Platonov <[email protected]>
Sat, 30 May 2026 18:45:57 +0000 (11:45 -0700)
committerDanil Platonov <[email protected]>
Sat, 30 May 2026 18:45:57 +0000 (11:45 -0700)
Cleanup: use tokio::test instead of special test helpers

Added pty_exec.py helper script to run binaries with a pseudoterminal attached (bug won't trigger otherwise).

Tested CI to fail on all unixes (ubuntu+macos) with older rustyline, and pass with new one.

.gitignore
tests-pl/issue-interrupt-nontermination.pl [new file with mode: 0644]
tests-pl/pty_exec.py [new file with mode: 0755]
tests/scryer/helper.rs
tests/scryer/issues.rs

index c2e60e69b1d7da15f346429e4a732c2ebaaaff4f..359be019388f7b224b05ac56f69a7ed77c4a3c46 100644 (file)
@@ -3,3 +3,5 @@ target/
 .direnv/
 
 
+__pycache__
+*.pyc
\ No newline at end of file
diff --git a/tests-pl/issue-interrupt-nontermination.pl b/tests-pl/issue-interrupt-nontermination.pl
new file mode 100644 (file)
index 0000000..75b9b7d
--- /dev/null
@@ -0,0 +1,38 @@
+% Server
+:- use_module(library(process)).
+:- use_module(library(charsio)).
+:- use_module(library(lists)).
+:- use_module(library(time)).
+
+prolog_path(Prolog) :-
+    read(Body),
+    term_variables(Body, [Prolog]),
+    Body.
+
+main :-
+    prolog_path(Prolog),
+    CMD = "\
+use_module(library(os)), \
+pid(PID), \
+write(PID), nl, \
+asserta((f :- f)), \
+catch(f, Err, (write(Err),nl)), \
+write(done), nl, \
+halt.",
+    process_create("tests-pl/pty_exec.py", [Prolog, "-g", CMD], [stdout(pipe(O))]),
+    get_line_to_chars(O, PID0, ""),
+    append(PID, "\r\n", PID0),
+    process_create("kill", ["-s", "INT", PID], []),
+    sleep(5),
+    % second kill should fail because process should exit after one kill
+    process_create("kill", ["-s", "INT", PID], [stderr(null), process(PK)]),
+    process_wait(PK, Status),
+    status_report(Status, PID), nl.
+
+status_report(exit(1), _PID) :- write(ok).
+status_report(exit(0), PID) :-
+    write(not_dead),
+    % kill by force to exit cleanly
+    process_create("kill", ["-9", PID], []).
+
+:- initialization(main).
\ No newline at end of file
diff --git a/tests-pl/pty_exec.py b/tests-pl/pty_exec.py
new file mode 100755 (executable)
index 0000000..336f99f
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/env python3
+# Pseudoterminal wrapper script
+
+import pty
+from sys import argv
+
+def main():
+    if len(argv) < 2:
+        print(f"Usage: {argv[0]} [command]")
+        return
+    pty.spawn(argv[1:])
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file
index 91fe988051fb5d8fbdcb2d5d920ecf38d8537090..4f3168aae0e2e29e0957f7a3a3fb82919c57dffb 100644 (file)
@@ -38,41 +38,6 @@ pub(crate) fn load_module_test<T: Expectable>(file: &str, expected: T) {
     expected.assert_eq(wam.test_load_file(file).as_slice());
 }
 
-/// Same as `load_module_test` with tokio runtime
-#[cfg(not(target_arch = "wasm32"))]
-pub(crate) fn load_module_test_with_tokio_runtime<T: Expectable>(file: &str, expected: T) {
-    let runtime = tokio::runtime::Builder::new_multi_thread()
-        .enable_all()
-        .build()
-        .unwrap();
-
-    runtime.block_on(async move {
-        let mut wam = MachineBuilder::default().build();
-        expected.assert_eq(wam.test_load_file(file).as_slice())
-    });
-}
-
-#[cfg(not(target_arch = "wasm32"))]
-pub(crate) fn load_module_test_with_tokio_runtime_and_input<T: Expectable>(
-    file: &str,
-    input: impl Into<Cow<'static, str>>,
-    expected: T,
-) {
-    let runtime = tokio::runtime::Builder::new_multi_thread()
-        .enable_all()
-        .build()
-        .unwrap();
-
-    runtime.block_on(async move {
-        let mut wam = MachineBuilder::default()
-            .with_streams(
-                StreamConfig::in_memory().with_user_input(InputStreamConfig::string(input)),
-            )
-            .build();
-        expected.assert_eq(wam.test_load_file(file).as_slice())
-    });
-}
-
 pub(crate) fn load_module_test_with_input<T: Expectable>(
     file: &str,
     input: impl Into<Cow<'static, str>>,
index 1cc9a260b502e5f4b429be1064a2527f8be37511..95208a4c68a3b4678f99ff7b312a36f153c2f928 100644 (file)
@@ -1,7 +1,5 @@
 use crate::helper::load_module_test;
 use crate::helper::load_module_test_with_input;
-#[cfg(all(feature = "http", not(target_arch = "wasm32")))]
-use crate::helper::load_module_test_with_tokio_runtime_and_input;
 use serial_test::serial;
 
 // issue #831
@@ -163,13 +161,25 @@ fn issue3262_read_from_stdin_no_newline() {
     load_module_test_with_input("tests-pl/issue3262.pl", "hello.", "hello");
 }
 
-#[test]
+#[tokio::test(flavor = "multi_thread")]
 #[cfg(all(feature = "http", not(target_arch = "wasm32")))]
 #[cfg_attr(miri, ignore = "it takes too long to run")]
-fn http_open_hanging() {
-    load_module_test_with_tokio_runtime_and_input(
+async fn http_open_hanging() {
+    load_module_test_with_input(
         "tests-pl/issue-http_open-hanging.pl",
         format!("PROLOG={:?}.", env!("CARGO_BIN_EXE_scryer-prolog")),
             "received response with status code:200\nreceived response with status code:200\nreceived response with status code:200\nreceived response with status code:200\nreceived response with status code:200\n"
     );
 }
+
+#[tokio::test(flavor = "multi_thread")]
+#[cfg(feature = "repl")]
+#[cfg(unix)]
+#[cfg_attr(miri, ignore = "it takes too long to run")]
+async fn sigint_interrupts_nonterminating_goals() {
+    load_module_test_with_input(
+        "tests-pl/issue-interrupt-nontermination.pl",
+        format!("PROLOG={:?}.", env!("CARGO_BIN_EXE_scryer-prolog")),
+        "ok\n",
+    );
+}