use super::{GuardFailure, run_guarded};
use crate::test_support::{ActionSink, SharedSink};
use crate::wait_progress::Cadence;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::channel;
use std::sync::Arc;
use std::time::Duration;
const DEADLINE: Duration = Duration::from_millis(100);
const LONG_DEADLINE: Duration = Duration::from_secs(60);
const FAST: Cadence = Cadence {
grace: Duration::from_millis(5),
interval: Duration::from_millis(5),
};
#[test]
fn a_finished_job_returns_its_value_from_another_thread() {
let caller = std::thread::current().id();
let outcome: Result<bool, GuardFailure> = run_guarded(
move || {
return std::thread::current().id() != caller;
},
DEADLINE,
FAST,
"a job",
&mut std::io::sink(),
);
assert_eq!(outcome, Ok(true));
}
#[test]
fn a_panic_comes_back_as_text() {
const MESSAGE: &str = "planted panic";
let outcome: Result<(), GuardFailure> = run_guarded(
|| {
panic!("{MESSAGE}");
},
DEADLINE,
FAST,
"a job",
&mut std::io::sink(),
);
assert_eq!(outcome, Err(GuardFailure::Panicked(String::from(MESSAGE))));
}
#[test]
fn a_job_that_outlives_its_deadline_is_abandoned() {
let (release, blocked) = channel::<()>();
let finished: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
let marker: Arc<AtomicBool> = Arc::clone(&finished);
let outcome: Result<(), GuardFailure> = run_guarded(
move || {
let _ = blocked.recv();
marker.store(true, Ordering::SeqCst);
},
DEADLINE,
FAST,
"a job",
&mut std::io::sink(),
);
assert_eq!(outcome, Err(GuardFailure::TimedOut(DEADLINE)));
assert!(!finished.load(Ordering::SeqCst), "the guard answered while the job was blocked");
drop(release);
}
#[test]
fn a_long_wait_prints_notices_naming_the_file() {
let (release, blocked) = channel::<()>();
let sink: SharedSink = SharedSink::default();
let mut counted: ActionSink = ActionSink::new(&sink, 3, move || {
let _ = release.send(());
});
let waiting_for: &str = "monochromatic-lint to check docs/a.md";
let outcome: Result<(), GuardFailure> = run_guarded(
move || {
let _ = blocked.recv();
},
LONG_DEADLINE,
FAST,
waiting_for,
&mut counted,
);
assert_eq!(outcome, Ok(()));
let text: String = sink.text();
assert!(text.lines().count() >= 3, "{text}");
for line in text.lines() {
assert!(line.starts_with(format!("cli-git: still waiting for {waiting_for} after ").as_str()), "{text}");
assert!(
line.contains(format!("giving up on it after {} seconds", LONG_DEADLINE.as_secs()).as_str()),
"{text}"
);
}
}