use crate::common::TestHooks;
use crate::common::TestInfo;
use crate::{SIGNALS_APP, SLEEPER_APP, assert_no_proc, prepare_debugee_process};
use bugstalker::debugger::DebuggerBuilder;
use nix::sys::signal;
use nix::sys::signal::{SIGINT, SIGUSR1, SIGUSR2};
use serial_test::serial;
use std::thread;
use std::time::Duration;
#[test]
#[serial]
fn test_signal_stop_single_thread() {
let process = prepare_debugee_process(SIGNALS_APP, &["single_thread"]);
let debugee_pid = process.pid();
let info = TestInfo::default();
let builder = DebuggerBuilder::new().with_hooks(TestHooks::new(info.clone()));
let mut debugger = builder.build(process).unwrap();
debugger.set_breakpoint_at_line("signals.rs", 12).unwrap();
thread::spawn(move || {
thread::sleep(Duration::from_secs(4));
signal::kill(debugee_pid, SIGUSR1).unwrap();
});
debugger.start_debugee().unwrap();
std::thread::sleep(Duration::from_secs(1));
debugger.continue_debugee().unwrap();
assert_eq!(info.line.take(), Some(12));
debugger.continue_debugee().unwrap();
assert_no_proc!(debugee_pid);
}
#[test]
#[serial]
fn test_signal_stop_multi_thread() {
let process = prepare_debugee_process(SIGNALS_APP, &["multi_thread"]);
let debugee_pid = process.pid();
let info = TestInfo::default();
let builder = DebuggerBuilder::new().with_hooks(TestHooks::new(info.clone()));
let mut debugger = builder.build(process).unwrap();
debugger.set_breakpoint_at_line("signals.rs", 42).unwrap();
thread::spawn(move || {
thread::sleep(Duration::from_secs(4));
signal::kill(debugee_pid, SIGUSR1).unwrap();
});
debugger.start_debugee().unwrap();
std::thread::sleep(Duration::from_secs(1));
debugger.continue_debugee().unwrap();
assert_eq!(info.line.take(), Some(42));
debugger.continue_debugee().unwrap();
assert_no_proc!(debugee_pid);
}
#[test]
#[serial]
fn test_signal_stop_multi_thread_multiple_signal() {
let process = prepare_debugee_process(SIGNALS_APP, &["multi_thread_multi_signal"]);
let debugee_pid = process.pid();
let info = TestInfo::default();
let builder = DebuggerBuilder::new().with_hooks(TestHooks::new(info.clone()));
let mut debugger = builder.build(process).unwrap();
debugger.set_breakpoint_at_line("signals.rs", 62).unwrap();
thread::spawn(move || {
thread::sleep(Duration::from_secs(4));
signal::kill(debugee_pid, SIGUSR1).unwrap();
signal::kill(debugee_pid, SIGUSR2).unwrap();
});
debugger.start_debugee().unwrap();
std::thread::sleep(Duration::from_secs(1));
debugger.continue_debugee().unwrap();
debugger.continue_debugee().unwrap();
assert_eq!(info.line.take(), Some(62));
debugger.continue_debugee().unwrap();
assert_no_proc!(debugee_pid);
}
#[test]
#[serial]
fn test_transparent_signals() {
let process = prepare_debugee_process(SLEEPER_APP, &["-s", "1"]);
let debugee_pid = process.pid();
let info = TestInfo::default();
let builder = DebuggerBuilder::new().with_hooks(TestHooks::new(info.clone()));
let mut debugger = builder.build(process).unwrap();
thread::spawn(move || {
thread::sleep(Duration::from_secs(2));
signal::kill(debugee_pid, SIGINT).unwrap();
});
debugger.start_debugee().unwrap();
assert!(!debugger.thread_state().unwrap().is_empty());
drop(debugger);
assert_no_proc!(debugee_pid);
}