58 lines
1.7 KiB
Rust
58 lines
1.7 KiB
Rust
//! Loom model for the runtime command capture join pattern.
|
|
|
|
use loom::sync::{Arc, Mutex};
|
|
use loom::thread;
|
|
|
|
fn join_capture(
|
|
handle: loom::thread::JoinHandle<Result<Vec<u8>, &'static str>>,
|
|
stream: &'static str,
|
|
) -> Result<Vec<u8>, String> {
|
|
handle
|
|
.join()
|
|
.map_err(|_| format!("{stream} capture thread panicked"))?
|
|
.map_err(|error| format!("failed to read child {stream}: {error}"))
|
|
}
|
|
|
|
#[test]
|
|
fn capture_threads_publish_before_join_returns() {
|
|
loom::model(|| {
|
|
let events = Arc::new(Mutex::new(Vec::new()));
|
|
let stdout_events = Arc::clone(&events);
|
|
let stderr_events = Arc::clone(&events);
|
|
|
|
let stdout = thread::spawn(move || {
|
|
let mut guard = stdout_events.lock().expect("stdout lock");
|
|
guard.push("stdout");
|
|
});
|
|
let stderr = thread::spawn(move || {
|
|
let mut guard = stderr_events.lock().expect("stderr lock");
|
|
guard.push("stderr");
|
|
});
|
|
|
|
stdout.join().expect("stdout join");
|
|
stderr.join().expect("stderr join");
|
|
|
|
{
|
|
let guard = events.lock().expect("events lock");
|
|
assert_eq!(guard.len(), 2);
|
|
assert!(guard.contains(&"stdout"));
|
|
assert!(guard.contains(&"stderr"));
|
|
drop(guard);
|
|
}
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn capture_join_models_success_and_read_error_paths() {
|
|
loom::model(|| {
|
|
let stdout = thread::spawn(|| Ok(vec![b'o', b'k']));
|
|
let stderr = thread::spawn(|| Err("broken pipe"));
|
|
|
|
assert_eq!(join_capture(stdout, "stdout").expect("stdout"), b"ok");
|
|
assert_eq!(
|
|
join_capture(stderr, "stderr").expect_err("stderr"),
|
|
"failed to read child stderr: broken pipe"
|
|
);
|
|
});
|
|
}
|