aboutsummaryrefslogtreecommitdiff
path: root/tests/api_ping.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-07-16 23:13:06 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-07-16 23:13:41 +0300
commit550e9f8cc085f428429f5cf2da0bb2dba897e8b8 (patch)
tree996e9cbbf905b89df8bd512fa9b0e68d07e25943 /tests/api_ping.rs
parent8dcb75a5c08b4dd1f225ea531a27824a9f41ae4a (diff)
fix: follow foreground process group leader cwd
refs #1472
Diffstat (limited to 'tests/api_ping.rs')
-rw-r--r--tests/api_ping.rs138
1 files changed, 138 insertions, 0 deletions
diff --git a/tests/api_ping.rs b/tests/api_ping.rs
index d2033814..a52e71c3 100644
--- a/tests/api_ping.rs
+++ b/tests/api_ping.rs
@@ -895,6 +895,144 @@ fn pane_info_reports_foreground_cwd_without_changing_pane_cwd() {
cleanup_spawned_herdr(child, base);
}
+#[cfg(target_os = "linux")]
+#[test]
+fn new_terminal_cwd_follow_ignores_nonleader_group_member_cwd() {
+ let _lock = test_lock();
+ let base = unique_test_dir();
+ let helper_cwd = base.join("plugin-cache");
+ let helper_marker = base.join("helper-cwd-ready");
+ let marker = base.join("helper-ready");
+ let leader_pid_file = base.join("leader.pid");
+ let helper_pid_file = base.join("helper.pid");
+ fs::create_dir_all(&helper_cwd).unwrap();
+ let config_home = base.join("config");
+ let runtime_dir = base.join("runtime");
+ let socket_path = runtime_dir.join("herdr.sock");
+
+ let child = spawn_herdr_with_shell(&config_home, &runtime_dir, &socket_path, "/bin/bash");
+ wait_for_socket(&socket_path, Duration::from_secs(5));
+
+ let created = send_request(
+ &socket_path,
+ &format!(
+ r#"{{"id":"member_ws","method":"workspace.create","params":{{"cwd":"{}","focus":true}}}}"#,
+ base.display()
+ ),
+ );
+ let pane_id = created["result"]["root_pane"]["pane_id"]
+ .as_str()
+ .unwrap()
+ .to_string();
+ let workspace_id = created["result"]["workspace"]["workspace_id"]
+ .as_str()
+ .unwrap()
+ .to_string();
+ let command = format!(
+ "/bin/sh -c 'printf %s $$ > {}; (cd {} && touch {} && sleep 30) & printf %s $! > {}; while [ ! -e {} ]; do sleep 0.01; done; touch {}; wait'",
+ leader_pid_file.display(),
+ helper_cwd.display(),
+ helper_marker.display(),
+ helper_pid_file.display(),
+ helper_marker.display(),
+ marker.display()
+ );
+ let send_text = send_request(
+ &socket_path,
+ &serde_json::json!({
+ "id": "member_send",
+ "method": "pane.send_text",
+ "params": {
+ "pane_id": pane_id,
+ "text": command,
+ },
+ })
+ .to_string(),
+ );
+ assert_eq!(send_text["result"]["type"], "ok");
+ let send_enter = send_request(
+ &socket_path,
+ &format!(
+ r#"{{"id":"member_enter","method":"pane.send_keys","params":{{"pane_id":"{}","keys":["Enter"]}}}}"#,
+ pane_id
+ ),
+ );
+ assert_eq!(send_enter["result"]["type"], "ok");
+ wait_for_path(&marker, Duration::from_secs(5));
+
+ let leader_pid: u32 = fs::read_to_string(&leader_pid_file)
+ .unwrap()
+ .parse()
+ .unwrap();
+ let helper_pid: u32 = fs::read_to_string(&helper_pid_file)
+ .unwrap()
+ .parse()
+ .unwrap();
+ assert_eq!(
+ unsafe { libc::getpgid(leader_pid as libc::pid_t) },
+ leader_pid as libc::pid_t
+ );
+ assert_eq!(
+ unsafe { libc::getpgid(helper_pid as libc::pid_t) },
+ leader_pid as libc::pid_t
+ );
+ assert_eq!(
+ fs::read_link(format!("/proc/{leader_pid}/cwd")).unwrap(),
+ base
+ );
+ assert_eq!(
+ fs::read_link(format!("/proc/{helper_pid}/cwd")).unwrap(),
+ helper_cwd
+ );
+
+ let pane = send_request(
+ &socket_path,
+ &format!(
+ r#"{{"id":"member_pane","method":"pane.get","params":{{"pane_id":"{}"}}}}"#,
+ pane_id
+ ),
+ );
+ assert_eq!(pane["result"]["pane"]["cwd"], base.display().to_string());
+ assert_eq!(
+ pane["result"]["pane"]["foreground_cwd"],
+ helper_cwd.display().to_string()
+ );
+
+ let split = send_request(
+ &socket_path,
+ &serde_json::json!({
+ "id": "member_split",
+ "method": "pane.split",
+ "params": {
+ "target_pane_id": pane_id,
+ "direction": "right",
+ "focus": false,
+ },
+ })
+ .to_string(),
+ );
+ assert_eq!(split["result"]["pane"]["cwd"], base.display().to_string());
+
+ let tab = send_request(
+ &socket_path,
+ &serde_json::json!({
+ "id": "member_tab",
+ "method": "tab.create",
+ "params": {
+ "workspace_id": workspace_id,
+ "focus": false,
+ },
+ })
+ .to_string(),
+ );
+ assert_eq!(
+ tab["result"]["root_pane"]["cwd"],
+ base.display().to_string()
+ );
+
+ cleanup_spawned_herdr(child, base);
+}
+
#[cfg(not(target_os = "macos"))]
#[test]
fn agent_start_creates_named_terminal_over_socket() {