diff options
Diffstat (limited to 'crates/phone-opus/tests')
| -rw-r--r-- | crates/phone-opus/tests/mcp_hardening.rs | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/crates/phone-opus/tests/mcp_hardening.rs b/crates/phone-opus/tests/mcp_hardening.rs index 0d53c33..0b32442 100644 --- a/crates/phone-opus/tests/mcp_hardening.rs +++ b/crates/phone-opus/tests/mcp_hardening.rs @@ -631,6 +631,7 @@ fn consult_reuses_context_per_cwd_by_default_and_fresh_context_opts_out() -> Tes let args = must(fs::read_to_string(&args_file), "read fake args file")?; let lines = args.lines().collect::<Vec<_>>(); assert!(lines.contains(&"-p")); + assert!(lines.contains(&"--verbose")); assert!(lines.contains(&"--output-format")); assert!(lines.contains(&"stream-json")); assert!(lines.contains(&"--strict-mcp-config")); @@ -838,6 +839,56 @@ fn consult_surfaces_downstream_cli_failures() -> TestResult { } #[test] +fn silent_claude_processes_fail_fast_instead_of_wedging() -> TestResult { + let root = temp_root("consult_stall")?; + let state_home = root.join("state-home"); + let fake_claude = root.join("claude"); + let caller_home = root.join("caller-home"); + must(fs::create_dir_all(&state_home), "create state home")?; + must(fs::create_dir_all(&caller_home), "create caller home")?; + seed_caller_claude_home(&caller_home)?; + write_fake_claude_script(&fake_claude)?; + + let claude_bin = fake_claude.display().to_string(); + let caller_home_path = caller_home.display().to_string(); + let env = [ + ("HOME", caller_home_path.as_str()), + ("PHONE_OPUS_CLAUDE_BIN", claude_bin.as_str()), + ("PHONE_OPUS_CLAUDE_INITIAL_OUTPUT_TIMEOUT_MS", "100"), + ("PHONE_OPUS_TEST_SLEEP_MS", "5000"), + ]; + let mut harness = McpHarness::spawn(&state_home, &env)?; + let _ = harness.initialize()?; + harness.notify_initialized()?; + + let started = std::time::Instant::now(); + let consult = harness.call_tool(3, "consult", json!({ "prompt": "hang forever" }))?; + let elapsed = started.elapsed(); + + assert_tool_error(&consult); + assert_eq!( + tool_content(&consult)["fault"]["class"].as_str(), + Some("downstream") + ); + assert!( + tool_content(&consult)["fault"]["detail"] + .as_str() + .is_some_and(|value| value.contains("produced no stream output within 100 ms")) + ); + assert!(elapsed < std::time::Duration::from_secs(3)); + assert_eq!( + tool_content(&consult)["context"]["consult"]["context_mode"].as_str(), + Some("fresh") + ); + assert!( + tool_content(&consult)["context"]["consult"]["planned_session_id"] + .as_str() + .is_some_and(|value| !value.is_empty()) + ); + Ok(()) +} + +#[test] fn quota_failures_surface_resume_context_for_same_cwd() -> TestResult { let root = temp_root("consult_quota_failure")?; let state_home = root.join("state-home"); |