From c25f7af21907d8d55807dab1e0249abca3576ab6 Mon Sep 17 00:00:00 2001 From: Paulo Aboim Pinto Date: Sun, 7 Jun 2026 16:29:40 +0200 Subject: [PATCH] Address acceptance harness review feedback --- crates/tui/tests/tool_lifecycle_acceptance.rs | 58 ++++++++++++++----- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/crates/tui/tests/tool_lifecycle_acceptance.rs b/crates/tui/tests/tool_lifecycle_acceptance.rs index 21ecd28c..33fc997f 100644 --- a/crates/tui/tests/tool_lifecycle_acceptance.rs +++ b/crates/tui/tests/tool_lifecycle_acceptance.rs @@ -45,7 +45,12 @@ fn offline_codewhale_workspace_containing(world: &mut ToolLifecycleWorld, step: let kind = row_value(&row, "kind"); let path = workspace.path().join(relative_path); match kind.as_str() { - "file" => std::fs::write(&path, "").expect("write workspace file"), + "file" => { + if let Some(parent) = path.parent() { + std::fs::create_dir_all(parent).expect("create workspace file parent"); + } + std::fs::write(&path, "").expect("write workspace file"); + } "folder" => std::fs::create_dir_all(&path).expect("create workspace folder"), other => panic!("unsupported workspace entry kind: {other}"), } @@ -328,29 +333,26 @@ fn run_codewhale_exec( fn run_with_timeout(mut command: Command, timeout: Duration) -> std::process::Output { let mut child = command.spawn().expect("spawn codewhale-tui exec"); + let stdout_reader = read_pipe_in_background(child.stdout.take().expect("stdout pipe")); + let stderr_reader = read_pipe_in_background(child.stderr.take().expect("stderr pipe")); + let status = match child.wait_timeout(timeout).expect("wait for codewhale-tui") { Some(status) => status, None => { let _ = child.kill(); let _ = child.wait(); - panic!("codewhale-tui exec timed out after {timeout:?}"); + let stdout = join_pipe_reader(stdout_reader, "stdout"); + let stderr = join_pipe_reader(stderr_reader, "stderr"); + panic!( + "codewhale-tui exec timed out after {timeout:?}\nstdout:\n{}\nstderr:\n{}", + String::from_utf8_lossy(&stdout), + String::from_utf8_lossy(&stderr) + ); } }; - let mut stdout = Vec::new(); - let mut stderr = Vec::new(); - child - .stdout - .take() - .expect("stdout pipe") - .read_to_end(&mut stdout) - .expect("read stdout"); - child - .stderr - .take() - .expect("stderr pipe") - .read_to_end(&mut stderr) - .expect("read stderr"); + let stdout = join_pipe_reader(stdout_reader, "stdout"); + let stderr = join_pipe_reader(stderr_reader, "stderr"); std::process::Output { status, @@ -359,6 +361,26 @@ fn run_with_timeout(mut command: Command, timeout: Duration) -> std::process::Ou } } +fn read_pipe_in_background(mut reader: R) -> std::thread::JoinHandle>> +where + R: Read + Send + 'static, +{ + std::thread::spawn(move || { + let mut output = Vec::new(); + reader.read_to_end(&mut output).map(|_| output) + }) +} + +fn join_pipe_reader( + handle: std::thread::JoinHandle>>, + stream_name: &str, +) -> Vec { + handle + .join() + .unwrap_or_else(|_| panic!("{stream_name} reader thread panicked")) + .unwrap_or_else(|err| panic!("read {stream_name}: {err}")) +} + fn preserve_host_env(command: &mut Command) { command.env_clear(); for key in [ @@ -370,6 +392,10 @@ fn preserve_host_env(command: &mut Command) { "COMSPEC", "TEMP", "TMP", + "TERM", + "COLORTERM", + "LANG", + "LC_ALL", ] { if let Some(value) = std::env::var_os(key) { command.env(key, value);