Test that SIGINT interrupts non-terminating goals on unix.
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.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,3 +3,5 @@ target/
|
|||||||
.direnv/
|
.direnv/
|
||||||
|
|
||||||
|
|
||||||
|
__pycache__
|
||||||
|
*.pyc
|
||||||
38
tests-pl/issue-interrupt-nontermination.pl
Normal file
38
tests-pl/issue-interrupt-nontermination.pl
Normal file
@@ -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).
|
||||||
14
tests-pl/pty_exec.py
Executable file
14
tests-pl/pty_exec.py
Executable file
@@ -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()
|
||||||
@@ -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());
|
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>(
|
pub(crate) fn load_module_test_with_input<T: Expectable>(
|
||||||
file: &str,
|
file: &str,
|
||||||
input: impl Into<Cow<'static, str>>,
|
input: impl Into<Cow<'static, str>>,
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::helper::load_module_test;
|
use crate::helper::load_module_test;
|
||||||
use crate::helper::load_module_test_with_input;
|
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;
|
use serial_test::serial;
|
||||||
|
|
||||||
// issue #831
|
// issue #831
|
||||||
@@ -163,13 +161,25 @@ fn issue3262_read_from_stdin_no_newline() {
|
|||||||
load_module_test_with_input("tests-pl/issue3262.pl", "hello.", "hello");
|
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(all(feature = "http", not(target_arch = "wasm32")))]
|
||||||
#[cfg_attr(miri, ignore = "it takes too long to run")]
|
#[cfg_attr(miri, ignore = "it takes too long to run")]
|
||||||
fn http_open_hanging() {
|
async fn http_open_hanging() {
|
||||||
load_module_test_with_tokio_runtime_and_input(
|
load_module_test_with_input(
|
||||||
"tests-pl/issue-http_open-hanging.pl",
|
"tests-pl/issue-http_open-hanging.pl",
|
||||||
format!("PROLOG={:?}.", env!("CARGO_BIN_EXE_scryer-prolog")),
|
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"
|
"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",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user