diff options
Diffstat (limited to 'crates/phone-opus/tests')
| -rw-r--r-- | crates/phone-opus/tests/mcp_hardening.rs | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/crates/phone-opus/tests/mcp_hardening.rs b/crates/phone-opus/tests/mcp_hardening.rs index b47b365..bc338ca 100644 --- a/crates/phone-opus/tests/mcp_hardening.rs +++ b/crates/phone-opus/tests/mcp_hardening.rs @@ -11,6 +11,7 @@ use libmcp_testkit::read_json_lines; use serde as _; use serde_json::{Value, json}; use thiserror as _; +use uuid as _; type TestResult<T = ()> = Result<T, Box<dyn std::error::Error>>; @@ -223,7 +224,8 @@ fn cold_start_exposes_consult_and_ops_tools() -> TestResult { } #[test] -fn consult_uses_read_only_toolset_and_requested_working_directory() -> TestResult { +fn consult_can_resume_a_prior_session_with_read_only_toolset_and_requested_working_directory() +-> TestResult { let root = temp_root("consult_success")?; let state_home = root.join("state-home"); let sandbox = root.join("sandbox"); @@ -234,6 +236,7 @@ fn consult_uses_read_only_toolset_and_requested_working_directory() -> TestResul let stdout_file = root.join("stdout.json"); let args_file = root.join("args.txt"); let pwd_file = root.join("pwd.txt"); + let resumed_session = "81f218eb-568b-409b-871b-f6e86d8f666f"; write_fake_claude_script(&fake_claude)?; must( fs::write( @@ -247,7 +250,7 @@ fn consult_uses_read_only_toolset_and_requested_working_directory() -> TestResul "num_turns": 2, "result": "oracle", "stop_reason": "end_turn", - "session_id": "session-123", + "session_id": resumed_session, "total_cost_usd": 0.125, "usage": { "input_tokens": 10, @@ -287,16 +290,29 @@ fn consult_uses_read_only_toolset_and_requested_working_directory() -> TestResul json!({ "prompt": "say oracle", "cwd": sandbox.display().to_string(), - "max_turns": 7 + "max_turns": 7, + "session_id": resumed_session }), )?; assert_tool_ok(&consult); assert_eq!(tool_content(&consult)["response"].as_str(), Some("oracle")); assert_eq!( + tool_content(&consult)["session_mode"].as_str(), + Some("resumed") + ); + assert_eq!( + tool_content(&consult)["requested_session_id"].as_str(), + Some(resumed_session) + ); + assert_eq!( tool_content(&consult)["cwd"].as_str(), Some(sandbox.display().to_string().as_str()) ); assert_eq!(tool_content(&consult)["num_turns"].as_u64(), Some(2)); + assert_eq!( + tool_content(&consult)["session_id"].as_str(), + Some(resumed_session) + ); let pwd = must(fs::read_to_string(&pwd_file), "read fake pwd file")?; assert_eq!(pwd.trim(), sandbox.display().to_string()); @@ -315,6 +331,8 @@ fn consult_uses_read_only_toolset_and_requested_working_directory() -> TestResul assert!(lines.contains(&"Bash,Read,Grep,Glob,LS,WebFetch,WebSearch")); assert!(lines.contains(&"--permission-mode")); assert!(lines.contains(&"dontAsk")); + assert!(lines.contains(&"--resume")); + assert!(lines.contains(&resumed_session)); assert!(lines.contains(&"--max-turns")); assert!(lines.contains(&"7")); assert_eq!(lines.last().copied(), Some("say oracle")); @@ -334,6 +352,37 @@ fn consult_uses_read_only_toolset_and_requested_working_directory() -> TestResul } #[test] +fn consult_rejects_invalid_session_handles() -> TestResult { + let root = temp_root("consult_invalid_session")?; + let state_home = root.join("state-home"); + must(fs::create_dir_all(&state_home), "create state home")?; + + let mut harness = McpHarness::spawn(&state_home, &[])?; + let _ = harness.initialize()?; + harness.notify_initialized()?; + + let consult = harness.call_tool( + 3, + "consult", + json!({ + "prompt": "fail", + "session_id": "not-a-uuid" + }), + )?; + assert_tool_error(&consult); + assert_eq!( + tool_content(&consult)["fault"]["class"].as_str(), + Some("protocol") + ); + assert!( + tool_content(&consult)["fault"]["detail"] + .as_str() + .is_some_and(|value| value.contains("session_id must be a valid UUID")) + ); + Ok(()) +} + +#[test] fn consult_surfaces_downstream_cli_failures() -> TestResult { let root = temp_root("consult_failure")?; let state_home = root.join("state-home"); |