aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorEric Yue <jiacheng.yue@foxmail.com>2026-09-23 22:44:56 +0800
committerGitHub <noreply@github.com>2026-09-23 16:44:56 +0200
commitc958833fa81333bf07a255f7d1325e6892daca1e (patch)
tree6d1f073d936f4a4c3d3fdc20b6b9857716e8967c /tests
parent9903007e5c4407ded451cac0b8164e3d69deb891 (diff)
test: wait for complete handoff pid markers (#4538)
* test: wait for complete handoff pid markers * test: wait for complete handoff pid markers
Diffstat (limited to 'tests')
-rw-r--r--tests/live_handoff.rs65
1 files changed, 48 insertions, 17 deletions
diff --git a/tests/live_handoff.rs b/tests/live_handoff.rs
index ea4b84df..3420940c 100644
--- a/tests/live_handoff.rs
+++ b/tests/live_handoff.rs
@@ -410,6 +410,50 @@ fn wait_for_file_contains(path: &Path, needle: &str, timeout: Duration) -> Strin
);
}
+fn wait_for_pid_marker(path: &Path, timeout: Duration) -> u32 {
+ // Shell redirection creates the file before echo writes the PID. Wait for
+ // the newline too, so a partially written PID cannot be accepted.
+ let text = wait_for_file_contains(path, "\n", timeout);
+ text.lines()
+ .next()
+ .and_then(|line| line.split_whitespace().last())
+ .and_then(|pid| pid.parse().ok())
+ .filter(|pid| *pid > 0)
+ .unwrap_or_else(|| panic!("invalid PID marker at {}: {text:?}", path.display()))
+}
+
+#[test]
+fn pid_marker_waits_for_complete_line() {
+ let base = unique_test_dir();
+ fs::create_dir_all(&base).unwrap();
+ let marker = base.join("child.pid");
+ // Keep each incomplete marker unchanged throughout the wait. In particular,
+ // READY 12 must time out rather than return a truncated but parseable PID.
+ for partial in ["", "READY ", "READY 12"] {
+ fs::write(&marker, partial).unwrap();
+ let timeout = Duration::from_millis(100);
+ let started = Instant::now();
+ let panic = std::panic::catch_unwind(|| wait_for_pid_marker(&marker, timeout))
+ .expect_err("incomplete marker should time out");
+ assert!(
+ started.elapsed() >= timeout,
+ "marker {partial:?} failed early"
+ );
+ let message = panic.downcast_ref::<String>().expect("timeout diagnostic");
+ assert_eq!(
+ message,
+ &format!(
+ "{} did not contain {:?}; last text was {partial:?}",
+ marker.display(),
+ "\n"
+ )
+ );
+ }
+ fs::write(&marker, "READY 1234\n").unwrap();
+ assert_eq!(wait_for_pid_marker(&marker, Duration::from_secs(1)), 1234);
+ fs::remove_dir_all(base).unwrap();
+}
+
#[cfg(target_os = "linux")]
fn server_ptmx_fd_count(pid: u32) -> usize {
let Ok(entries) = fs::read_dir(format!("/proc/{pid}/fd")) else {
@@ -1014,17 +1058,8 @@ fn live_handoff_preserves_pane_process_io() {
"params": {"pane_id": second_pane_id, "text": second_command, "keys": ["Enter"]}
}),
));
- support::wait_for_file(&marker, Duration::from_secs(5));
- support::wait_for_file(&second_marker, Duration::from_secs(5));
- let pid_text = fs::read_to_string(&marker).unwrap();
- let child_pid: u32 = pid_text.split_whitespace().last().unwrap().parse().unwrap();
- let second_pid_text = fs::read_to_string(&second_marker).unwrap();
- let second_child_pid: u32 = second_pid_text
- .split_whitespace()
- .last()
- .unwrap()
- .parse()
- .unwrap();
+ let child_pid = wait_for_pid_marker(&marker, Duration::from_secs(5));
+ let second_child_pid = wait_for_pid_marker(&second_marker, Duration::from_secs(5));
assert_eq!(unsafe { libc::kill(child_pid as libc::pid_t, 0) }, 0);
assert_eq!(unsafe { libc::kill(second_child_pid as libc::pid_t, 0) }, 0);
@@ -1955,9 +1990,7 @@ fn live_handoff_bad_expected_protocol_rolls_back_old_server() {
"params": {"pane_id": pane_id, "text": command, "keys": ["Enter"]}
}),
));
- support::wait_for_file(&marker, Duration::from_secs(5));
- let pid_text = fs::read_to_string(&marker).unwrap();
- let child_pid: u32 = pid_text.split_whitespace().last().unwrap().parse().unwrap();
+ let child_pid = wait_for_pid_marker(&marker, Duration::from_secs(5));
let failed = request(
&api_socket,
@@ -2041,9 +2074,7 @@ fn live_handoff_import_failure_rolls_back_old_server_at(failure_point: &str) {
"params": {"pane_id": pane_id, "text": command, "keys": ["Enter"]}
}),
));
- support::wait_for_file(&marker, Duration::from_secs(5));
- let pid_text = fs::read_to_string(&marker).unwrap();
- let child_pid: u32 = pid_text.split_whitespace().last().unwrap().parse().unwrap();
+ let child_pid = wait_for_pid_marker(&marker, Duration::from_secs(5));
let failed = request(
&api_socket,