diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-24 02:49:33 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-24 02:50:58 +0300 |
| commit | e608a75159fc5cca70485d83ffb8ee681c9da385 (patch) | |
| tree | 5ffdec62d0bee9a798418d6414ecbddae7ff8ae5 /tests | |
| parent | 169a4fd90c20a00aec77d684ecec98b9f0f996cc (diff) | |
fix: make known-agent exit process-owned
refs #1792
refs #1648
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/api_ping.rs | 48 | ||||
| -rw-r--r-- | tests/cli/agent_wait.rs | 4 | ||||
| -rw-r--r-- | tests/cli/sessions.rs | 2 | ||||
| -rw-r--r-- | tests/live_handoff.rs | 89 |
4 files changed, 115 insertions, 28 deletions
diff --git a/tests/api_ping.rs b/tests/api_ping.rs index d05f3f7f..344fe6ec 100644 --- a/tests/api_ping.rs +++ b/tests/api_ping.rs @@ -1699,10 +1699,19 @@ fn pane_report_agent_updates_effective_state() { } let session_path = base.join("pi-session.jsonl"); + let session = send_request( + &socket_path, + &format!( + r#"{{"id":"req_hook_session","method":"pane.report_agent_session","params":{{"pane_id":"{}","source":"herdr:pi","agent":"pi","agent_session_path":"{}","session_start_source":"startup","seq":1}}}}"#, + pane_id, + session_path.display() + ), + ); + assert_eq!(session["result"]["type"], "ok"); let hook = send_request( &socket_path, &format!( - r#"{{"id":"req_hook_5","method":"pane.report_agent","params":{{"pane_id":"{}","source":"herdr:pi","agent":"pi","state":"working","message":"thinking","agent_session_path":"{}"}}}}"#, + r#"{{"id":"req_hook_5","method":"pane.report_agent","params":{{"pane_id":"{}","source":"herdr:pi","agent":"pi","state":"working","message":"thinking","agent_session_path":"{}","seq":2}}}}"#, pane_id, session_path.display() ), @@ -1875,7 +1884,7 @@ fn pane_report_agent_accepts_unknown_agent_labels() { #[cfg(not(target_os = "macos"))] #[test] -fn pane_release_agent_suppresses_reacquire_during_graceful_exit() { +fn official_release_waits_for_confirmed_process_exit() { let _lock = test_lock(); let base = unique_test_dir(); let config_home = base.join("config"); @@ -1960,11 +1969,22 @@ fn pane_release_agent_suppresses_reacquire_during_graceful_exit() { thread::sleep(Duration::from_millis(100)); } + let session_path = base.join("release-session.jsonl"); + let session = send_request( + &socket_path, + &format!( + r#"{{"id":"req_release_session","method":"pane.report_agent_session","params":{{"pane_id":"{}","source":"herdr:pi","agent":"pi","agent_session_path":"{}","session_start_source":"startup","seq":1}}}}"#, + pane_id, + session_path.display() + ), + ); + assert_eq!(session["result"]["type"], "ok"); let hook = send_request( &socket_path, &format!( - r#"{{"id":"req_release_4","method":"pane.report_agent","params":{{"pane_id":"{}","source":"herdr:pi","agent":"pi","state":"working"}}}}"#, - pane_id + r#"{{"id":"req_release_4","method":"pane.report_agent","params":{{"pane_id":"{}","source":"herdr:pi","agent":"pi","state":"working","agent_session_path":"{}","seq":2}}}}"#, + pane_id, + session_path.display() ), ); assert_eq!(hook["result"]["type"], "ok"); @@ -1978,8 +1998,8 @@ fn pane_release_agent_suppresses_reacquire_during_graceful_exit() { ); assert_eq!(released["result"]["type"], "ok"); - let suppression_deadline = Instant::now() + Duration::from_millis(300); - while Instant::now() < suppression_deadline { + let release_observation_deadline = Instant::now() + Duration::from_millis(300); + while Instant::now() < release_observation_deadline { let pane = send_request( &socket_path, &format!( @@ -1987,11 +2007,11 @@ fn pane_release_agent_suppresses_reacquire_during_graceful_exit() { pane_id ), ); - assert!( - pane["result"]["pane"]["agent"].is_null(), - "pane reacquired pi during graceful release: {pane}" + assert_eq!( + pane["result"]["pane"]["agent"], "pi", + "official release hid the live Pi process: {pane}" ); - assert_eq!(pane["result"]["pane"]["agent_status"], "unknown"); + assert_eq!(pane["result"]["pane"]["agent_status"], "working"); thread::sleep(Duration::from_millis(50)); } @@ -2013,7 +2033,7 @@ fn pane_release_agent_suppresses_reacquire_during_graceful_exit() { } assert!( Instant::now() < cleared_deadline, - "pi agent was not cleared promptly after release: {pane}" + "pi agent was not cleared promptly after process exit: {pane}" ); thread::sleep(Duration::from_millis(50)); } @@ -2443,7 +2463,7 @@ fn metadata_status_subscription_filter_and_ttl_expiry_are_observable() { let report_agent = send_request( &socket_path, &format!( - r#"{{"id":"req_meta_sub_2","method":"pane.report_agent","params":{{"pane_id":"{}","source":"herdr:pi","agent":"pi","state":"working"}}}}"#, + r#"{{"id":"req_meta_sub_2","method":"pane.report_agent","params":{{"pane_id":"{}","source":"custom:pi","agent":"pi","state":"working"}}}}"#, pane_id ), ); @@ -2463,7 +2483,7 @@ fn metadata_status_subscription_filter_and_ttl_expiry_are_observable() { let metadata = send_request( &socket_path, &format!( - r#"{{"id":"req_meta_sub_3","method":"pane.report_metadata","params":{{"pane_id":"{}","source":"user:pi-display","agent":"pi","applies_to_source":"herdr:pi","title":"filtered out"}}}}"#, + r#"{{"id":"req_meta_sub_3","method":"pane.report_metadata","params":{{"pane_id":"{}","source":"user:pi-display","agent":"pi","applies_to_source":"custom:pi","title":"filtered out"}}}}"#, pane_id ), ); @@ -2489,7 +2509,7 @@ fn metadata_status_subscription_filter_and_ttl_expiry_are_observable() { let metadata = send_request( &socket_path, &format!( - r#"{{"id":"req_meta_sub_4","method":"pane.report_metadata","params":{{"pane_id":"{}","source":"user:pi-display","agent":"pi","applies_to_source":"herdr:pi","title":"short lived","ttl_ms":100}}}}"#, + r#"{{"id":"req_meta_sub_4","method":"pane.report_metadata","params":{{"pane_id":"{}","source":"user:pi-display","agent":"pi","applies_to_source":"custom:pi","title":"short lived","ttl_ms":100}}}}"#, pane_id ), ); diff --git a/tests/cli/agent_wait.rs b/tests/cli/agent_wait.rs index 11997d00..11da467d 100644 --- a/tests/cli/agent_wait.rs +++ b/tests/cli/agent_wait.rs @@ -26,7 +26,7 @@ fn agent_wait_exits_immediately_when_status_already_matches() { let reported = send_request( &socket_path, &format!( - r#"{{"id":"req_cli_immediate_2","method":"pane.report_agent","params":{{"pane_id":"{}","source":"herdr:pi","agent":"pi","state":"idle"}}}}"#, + r#"{{"id":"req_cli_immediate_2","method":"pane.report_agent","params":{{"pane_id":"{}","source":"custom:test","agent":"pi","state":"idle"}}}}"#, pane_id ), ); @@ -78,7 +78,7 @@ fn agent_wait_times_out_when_status_does_not_match() { let reported = send_request( &socket_path, &format!( - r#"{{"id":"req_cli_timeout_2","method":"pane.report_agent","params":{{"pane_id":"{}","source":"herdr:pi","agent":"pi","state":"working"}}}}"#, + r#"{{"id":"req_cli_timeout_2","method":"pane.report_agent","params":{{"pane_id":"{}","source":"custom:test","agent":"pi","state":"working"}}}}"#, pane_id ), ); diff --git a/tests/cli/sessions.rs b/tests/cli/sessions.rs index 126cb616..b7655542 100644 --- a/tests/cli/sessions.rs +++ b/tests/cli/sessions.rs @@ -230,7 +230,7 @@ fn integration_commands_run_locally_when_server_is_missing() { .unwrap(); assert_eq!(integration_status.status.code(), Some(0)); let status_stdout = String::from_utf8_lossy(&integration_status.stdout); - assert!(status_stdout.contains("pi: current (v6)")); + assert!(status_stdout.contains("pi: current (v7)")); assert!(status_stdout.contains("claude: not installed")); let integration_uninstall = Command::new(env!("CARGO_BIN_EXE_herdr")) diff --git a/tests/live_handoff.rs b/tests/live_handoff.rs index c93898b6..4d81246a 100644 --- a/tests/live_handoff.rs +++ b/tests/live_handoff.rs @@ -1213,6 +1213,8 @@ fn live_handoff_accepts_canonical_pane_id_from_child_env() { #[test] fn live_handoff_keeps_unmanaged_agent_name_bound_to_saved_session() { + use std::os::unix::fs::PermissionsExt; + let _lock = test_lock(); let base = unique_test_dir(); let config_home = base.join("config"); @@ -1220,6 +1222,18 @@ fn live_handoff_keeps_unmanaged_agent_name_bound_to_saved_session() { let api_socket = runtime_dir.join("herdr.sock"); let old_session = base.join("old-session.jsonl"); let new_session = base.join("new-session.jsonl"); + let started_marker = base.join("agent-started"); + let fake_pi = base.join("pi"); + fs::create_dir_all(&base).unwrap(); + fs::write( + &fake_pi, + format!( + "#!/bin/sh\nexport HERDR_AGENT=pi\necho started > {}\nexec /bin/sleep 30\n", + started_marker.display() + ), + ) + .unwrap(); + fs::set_permissions(&fake_pi, fs::Permissions::from_mode(0o755)).unwrap(); let spawned = spawn_server(&config_home, &runtime_dir, &api_socket); wait_for_socket(&api_socket, Duration::from_secs(10)); @@ -1239,6 +1253,30 @@ fn live_handoff_keeps_unmanaged_agent_name_bound_to_saved_session() { assert_ok(request( &api_socket, serde_json::json!({ + "id": "test:pane:start-agent", + "method": "pane.send_input", + "params": {"pane_id": pane_id, "text": fake_pi, "keys": ["Enter"]} + }), + )); + support::wait_for_file(&started_marker, Duration::from_secs(5)); + assert_ok(request( + &api_socket, + serde_json::json!({ + "id": "test:agent:session", + "method": "pane.report_agent_session", + "params": { + "pane_id": pane_id, + "source": "herdr:pi", + "agent": "pi", + "seq": 1, + "agent_session_path": old_session, + "session_start_source": "startup" + } + }), + )); + assert_ok(request( + &api_socket, + serde_json::json!({ "id": "test:agent:report", "method": "pane.report_agent", "params": { @@ -1246,11 +1284,30 @@ fn live_handoff_keeps_unmanaged_agent_name_bound_to_saved_session() { "source": "herdr:pi", "agent": "pi", "state": "idle", - "seq": 1, + "seq": 2, "agent_session_path": old_session } }), )); + let deadline = Instant::now() + Duration::from_secs(5); + loop { + let response = request( + &api_socket, + serde_json::json!({ + "id": "test:agent:wait-for-process", + "method": "agent.get", + "params": {"target": pane_id} + }), + ); + if response.get("result").is_some() { + break; + } + assert!( + Instant::now() < deadline, + "agent process was not detected: {response}" + ); + thread::sleep(Duration::from_millis(25)); + } assert_ok(request( &api_socket, serde_json::json!({ @@ -1276,21 +1333,31 @@ fn live_handoff_keeps_unmanaged_agent_name_bound_to_saved_session() { "pane_id": pane_id, "source": "herdr:pi", "agent": "pi", - "seq": 2, + "seq": 3, "agent_session_path": new_session, "session_start_source": "new" } }), )); - let old_name = request( - &api_socket, - serde_json::json!({ - "id": "test:agent:get-old-name", - "method": "agent.get", - "params": {"target": "reviewer"} - }), - ); - assert_eq!(old_name["error"]["code"], "agent_not_found", "{old_name}"); + let deadline = Instant::now() + Duration::from_secs(5); + loop { + let old_name = request( + &api_socket, + serde_json::json!({ + "id": "test:agent:get-old-name", + "method": "agent.get", + "params": {"target": "reviewer"} + }), + ); + if old_name["error"]["code"] == "agent_not_found" { + break; + } + assert!( + Instant::now() < deadline, + "old session alias was not cleared: {old_name}" + ); + thread::sleep(Duration::from_millis(25)); + } let _ = request( &api_socket, |
