aboutsummaryrefslogtreecommitdiff
path: root/tests/client_mode.rs
diff options
context:
space:
mode:
authorEric Yue <jiacheng.yue@foxmail.com>2026-09-15 21:28:59 +0800
committerGitHub <noreply@github.com>2026-09-15 15:28:59 +0200
commit35707684b9de1b2e2b6be5de5a49e69ad57ac36b (patch)
tree0f49470bf333e9d6a8874462a52eaf1961ff34f6 /tests/client_mode.rs
parentf236ba54193d0f474b98849400b0d3a77d2056bd (diff)
test: wait for runtime readiness in integration tests (#4168)
Root cause: The handoff test starts an agent immediately after workspace creation, before the new shell is necessarily ready. The reconnect test assumes a fixed sidebar row and searches raw ANSI output for text that can arrive as separate incremental cell updates. Fix: Wait for a shell builtin to write a readiness marker before sending the single raw agent.start request. Exercise the gap with a delayed shell. Locate the recovered workspace in the rendered sidebar and check the reconstructed screen for selection and input, including overlay borders. Do not extend existing timeouts or add retries that hide failures. Validation: All 25 affected group and helper tests pass. Ten repeated rounds of the two runtime tests and the row helper pass, for 30 test executions without retries. Standalone native just ci passes 3582 Rust tests with six default skips, formatting, all-target Clippy, 106 maintenance tests, six architecture tests and 39 integration-asset tests. Windows cross-lint was not run because its SDK is not installed. Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
Diffstat (limited to 'tests/client_mode.rs')
-rw-r--r--tests/client_mode.rs47
1 files changed, 41 insertions, 6 deletions
diff --git a/tests/client_mode.rs b/tests/client_mode.rs
index a946af7c..71d3ff8d 100644
--- a/tests/client_mode.rs
+++ b/tests/client_mode.rs
@@ -716,6 +716,39 @@ fn output_len(output: &SharedOutput) -> usize {
output.lock().unwrap_or_else(|p| p.into_inner()).text.len()
}
+fn sidebar_row_click(screen: &str, label: &str) -> Vec<u8> {
+ let sidebar_width = screen
+ .lines()
+ .find_map(|line| line.chars().position(|character| character == '│'))
+ .expect("visible sidebar boundary");
+ let row = screen
+ .lines()
+ .position(|line| {
+ line.chars()
+ .take(sidebar_width)
+ .collect::<String>()
+ .contains(label)
+ })
+ .unwrap_or_else(|| panic!("sidebar row {label:?} is not visible: {screen}"))
+ + 1;
+ format!("\x1b[<0;7;{row}M\x1b[<0;7;{row}m").into_bytes()
+}
+
+#[test]
+fn sidebar_row_click_tracks_restored_workspace_count() {
+ for restored in [false, true] {
+ let screen = format!(
+ " machines │\n │\n ▾ Local │local-returned in pane output\n{} · local-returned └─────────────────\n",
+ if restored { " · restored │\n" } else { "" }
+ );
+ let row = if restored { 5 } else { 4 };
+ assert_eq!(
+ sidebar_row_click(&screen, "local-returned"),
+ format!("\x1b[<0;7;{row}M\x1b[<0;7;{row}m").into_bytes()
+ );
+ }
+}
+
/// Spawns a server + real thin client under a PTY and waits until the client
/// has attached and rendered a frame. Returns the pieces plus a shared buffer
/// that keeps accumulating PTY output (including teardown) on a background
@@ -1074,20 +1107,22 @@ fn federated_client_starts_without_local_and_survives_its_restart() {
local_pane,
"printf 'LOCAL_RECOVERED_SURFACE\\n'",
);
- let watermark = output_len(&output);
// Select the fresh workspace below Local's restored workspace.
- input.write_all(b"\x1b[<0;7;5M\x1b[<0;7;5m").unwrap();
+ // A fast shutdown may leave no saved workspace, so locate the actual row.
+ input
+ .write_all(&sidebar_row_click(&screen_text(), "local-returned"))
+ .unwrap();
assert!(
wait_until(Duration::from_secs(10), Duration::from_millis(20), || {
- read_output(&output)[watermark..].contains("LOCAL_RECOVERED_SURFACE")
+ screen_text().contains("LOCAL_RECOVERED_SURFACE")
}),
"recovered Local must be selectable: {}",
- read_output(&output)
+ screen_text()
);
// A coherent frame precedes the final host-effects fence; input stays gated until then.
assert!(
wait_until(Duration::from_secs(8), Duration::from_millis(100), || {
- if read_output(&output)[watermark..].contains("LOCAL_INPUT_RECOVERED") {
+ if screen_text().contains("LOCAL_INPUT_RECOVERED") {
return true;
}
input
@@ -1096,7 +1131,7 @@ fn federated_client_starts_without_local_and_survives_its_restart() {
false
}),
"recovered Local must accept input: {}",
- read_output(&output)
+ screen_text()
);
drop(input);
drop(client);