Add src/poller.rs with FIFO O_NONBLOCK open (read-end + keeper write-end), Stop hook JSON payload parsing, transcript path derivation via cwd slug, and StopInfo resolution. Wire poller into EventLoop via add_fifo_fd() which was already present in event_loop.rs from Phase 3. Update mock-claude to emit proper JSON Stop payloads (with and without transcript_path via MOCK_OMIT_TRANSCRIPT_PATH=1) and update the pty_integration assertion to match. Tests test_stop_hook_fires and test_missing_transcript_path_derived both pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
47 lines
1.7 KiB
Rust
47 lines
1.7 KiB
Rust
use claude_print::hook::HookInstaller;
|
|
use claude_print::pty::PtySpawner;
|
|
use std::ffi::CString;
|
|
use std::io::Read;
|
|
|
|
/// Locate the mock-claude binary compiled alongside the test binary.
|
|
/// Test binaries live at `target/<profile>/deps/`; other bins at `target/<profile>/`.
|
|
fn mock_claude_bin() -> std::path::PathBuf {
|
|
let exe = std::env::current_exe().expect("current_exe");
|
|
let profile_dir = exe
|
|
.parent() // deps/
|
|
.and_then(|p| p.parent()) // target/<profile>/
|
|
.expect("unexpected test binary path");
|
|
profile_dir.join("mock-claude")
|
|
}
|
|
|
|
#[test]
|
|
fn test_pty_spawns_tty() {
|
|
let installer = HookInstaller::new().expect("HookInstaller::new");
|
|
let fifo_path = installer.fifo_path.clone();
|
|
|
|
// Read from the FIFO in a background thread so mock-claude's write doesn't block.
|
|
let reader = std::thread::spawn(move || {
|
|
let mut file = std::fs::File::open(&fifo_path).expect("open stop.fifo");
|
|
let mut buf = String::new();
|
|
file.read_to_string(&mut buf).ok();
|
|
buf
|
|
});
|
|
|
|
let bin = mock_claude_bin();
|
|
let cmd = CString::new(bin.to_str().expect("binary path is utf-8")).expect("CString");
|
|
let fifo_arg =
|
|
CString::new(installer.fifo_path.to_str().expect("fifo path is utf-8")).expect("CString");
|
|
|
|
let spawner = PtySpawner::spawn(&cmd, &[fifo_arg]).expect("PtySpawner::spawn");
|
|
let exit_code = spawner.relay().expect("relay");
|
|
|
|
let fifo_content = reader.join().expect("reader thread");
|
|
assert!(
|
|
fifo_content.contains("session_id"),
|
|
"expected Stop JSON payload in FIFO content, got: {fifo_content:?}",
|
|
);
|
|
assert_eq!(
|
|
exit_code, 0,
|
|
"mock-claude should detect a controlling TTY (isatty(0) returned false)",
|
|
);
|
|
}
|