0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-10-29 08:58:01 -04:00

fix(test): add process sigint handler for --watch (#18678)

Fixes #18676.
This commit is contained in:
Nayeem Rahman 2023-04-12 23:51:04 +01:00 committed by GitHub
parent 17e4782140
commit d97f9d22b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 0 deletions

View file

@ -1122,6 +1122,35 @@ fn test_watch_unload_handler_error_on_drop() {
check_alive_then_kill(child); check_alive_then_kill(child);
} }
#[cfg(unix)]
#[test]
fn test_watch_sigint() {
use nix::sys::signal;
use nix::sys::signal::Signal;
use nix::unistd::Pid;
let t = TempDir::new();
let file_to_watch = t.path().join("file_to_watch.js");
write(&file_to_watch, r#"Deno.test("foo", () => {});"#).unwrap();
let mut child = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("test")
.arg("--watch")
.arg(&file_to_watch)
.env("NO_COLOR", "1")
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap();
let (mut stdout_lines, mut stderr_lines) = child_lines(&mut child);
wait_contains("Test started", &mut stderr_lines);
wait_contains("ok | 1 passed | 0 failed", &mut stdout_lines);
wait_contains("Test finished", &mut stderr_lines);
signal::kill(Pid::from_raw(child.id() as i32), Signal::SIGINT).unwrap();
let exit_status = child.wait().unwrap();
assert_eq!(exit_status.code(), Some(130));
}
// Regression test for https://github.com/denoland/deno/issues/15465. // Regression test for https://github.com/denoland/deno/issues/15465.
#[test] #[test]
fn run_watch_reload_once() { fn run_watch_reload_once() {

View file

@ -57,7 +57,9 @@ use std::io::Write;
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
use std::path::Path; use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::AtomicUsize; use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use std::time::Instant; use std::time::Instant;
@ -1174,6 +1176,8 @@ pub async fn check_specifiers(
Ok(()) Ok(())
} }
static HAS_TEST_RUN_SIGINT_HANDLER: AtomicBool = AtomicBool::new(false);
/// Test a collection of specifiers with test modes concurrently. /// Test a collection of specifiers with test modes concurrently.
async fn test_specifiers( async fn test_specifiers(
ps: &ProcState, ps: &ProcState,
@ -1201,6 +1205,7 @@ async fn test_specifiers(
signal::ctrl_c().await.unwrap(); signal::ctrl_c().await.unwrap();
sender_.upgrade().map(|s| s.send(TestEvent::Sigint).ok()); sender_.upgrade().map(|s| s.send(TestEvent::Sigint).ok());
}); });
HAS_TEST_RUN_SIGINT_HANDLER.store(true, Ordering::Relaxed);
let join_handles = let join_handles =
specifiers_with_mode specifiers_with_mode
@ -1388,6 +1393,7 @@ async fn test_specifiers(
} }
sigint_handler_handle.abort(); sigint_handler_handle.abort();
HAS_TEST_RUN_SIGINT_HANDLER.store(false, Ordering::Relaxed);
let elapsed = Instant::now().duration_since(earlier); let elapsed = Instant::now().duration_since(earlier);
reporter.report_summary(&summary, &elapsed); reporter.report_summary(&summary, &elapsed);
@ -1736,6 +1742,19 @@ pub async fn run_tests_with_watch(
} }
}; };
// On top of the sigint handlers which are added and unbound for each test
// run, a process-scoped basic exit handler is required due to a tokio
// limitation where it doesn't unbind its own handler for the entire process
// once a user adds one.
tokio::task::spawn(async move {
loop {
signal::ctrl_c().await.unwrap();
if !HAS_TEST_RUN_SIGINT_HANDLER.load(Ordering::Relaxed) {
std::process::exit(130);
}
}
});
let clear_screen = !ps.borrow().options.no_clear_screen(); let clear_screen = !ps.borrow().options.no_clear_screen();
file_watcher::watch_func( file_watcher::watch_func(
resolver, resolver,