From 8636fa0caa6c25ec271cfa1ba0512c07f59e3566 Mon Sep 17 00:00:00 2001 From: Val Alexander <68980965+BunsDev@users.noreply.github.com> Date: Sun, 18 Oct 2026 08:27:26 -0500 Subject: [PATCH] test(commands): share bounded goal fixture runner Port manifest position 111 with the current goal fixture assertions intact. Share child deadlines, cleanup, stderr capture, and completion checks while keeping every home path inside the fixture scratch directory. Coven-Harness: Codex / GPT-6 --- src-rust/crates/commands/tests/common/goal.rs | 50 +++++++++++++ src-rust/crates/commands/tests/goal_budget.rs | 74 +++++-------------- src-rust/crates/commands/tests/goal_clear.rs | 58 ++------------- src-rust/crates/commands/tests/goal_reads.rs | 58 ++------------- 4 files changed, 81 insertions(+), 159 deletions(-) create mode 100644 src-rust/crates/commands/tests/common/goal.rs diff --git a/src-rust/crates/commands/tests/common/goal.rs b/src-rust/crates/commands/tests/common/goal.rs new file mode 100644 index 00000000..5b811e16 --- /dev/null +++ b/src-rust/crates/commands/tests/common/goal.rs @@ -0,0 +1,50 @@ +use std::process::{Command, Stdio}; +use std::time::{Duration, Instant}; + +pub fn run_cases(worker: &str, cases: &[&str]) { + let mut failures = Vec::new(); + for case in cases { + let temp = tempfile::tempdir().unwrap(); + let home = temp.path().join("home"); + let project = temp.path().join("project"); + std::fs::create_dir(&home).unwrap(); + std::fs::create_dir(&project).unwrap(); + let log = temp.path().join("stderr"); + let mut child = Command::new(std::env::current_exe().unwrap()) + .args(["--exact", worker, "--ignored", "--nocapture"]) + .env_clear() + .env("HOME", &home) + .env("USERPROFILE", &home) + .env("COVEN_CODE_HOME", &home) + .env("COVEN_HOME", temp.path().join("coven")) + .env("COVEN_CAVE_HOME", temp.path().join("cave")) + .env("GOAL_FIXTURE_PROJECT", &project) + .env("GOAL_FIXTURE_CASE", case) + .env("GOAL_FIXTURE_DONE", temp.path().join("done")) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(std::fs::File::create(&log).unwrap()) + .spawn() + .unwrap(); + let deadline = Instant::now() + Duration::from_secs(10); + let outcome = loop { + match child.try_wait() { + Ok(Some(status)) => break status, + Ok(None) if Instant::now() < deadline => { + std::thread::sleep(Duration::from_millis(10)) + } + result => { + let _ = child.kill(); + let _ = child.wait(); + panic!("{case}: child wait failed: {result:?}"); + } + } + }; + if outcome.success() { + assert_eq!(std::fs::read(temp.path().join("done")).unwrap(), b"checked"); + } else { + failures.push(format!("{case}: {}", std::fs::read_to_string(log).unwrap())); + } + } + assert!(failures.is_empty(), "{}", failures.join("\n")); +} diff --git a/src-rust/crates/commands/tests/goal_budget.rs b/src-rust/crates/commands/tests/goal_budget.rs index b5dc94c0..5e9f118d 100644 --- a/src-rust/crates/commands/tests/goal_budget.rs +++ b/src-rust/crates/commands/tests/goal_budget.rs @@ -1,66 +1,30 @@ +#[path = "common/goal.rs"] +mod goal_fixture; + use claurst_commands::{CommandContext, CommandResult, GoalCommand, SlashCommand}; use claurst_core::{config::Config, cost::CostTracker, GoalStore}; -use std::process::{Command, Stdio}; -use std::time::{Duration, Instant}; +use goal_fixture::run_cases; #[test] fn invalid_explicit_goal_budgets_preserve_existing_goal() { - run_cases(&[ - "overflow_k", - "overflow_m", - "overflow_integer", - "invalid", - "negative", - "over_storage", - ]); + run_cases( + "goal_budget_worker", + &[ + "overflow_k", + "overflow_m", + "overflow_integer", + "invalid", + "negative", + "over_storage", + ], + ); } #[test] fn valid_goal_budgets_preserve_existing_semantics() { - run_cases(&["zero", "plain", "k", "m", "none", "max_storage"]); -} - -fn run_cases(cases: &[&str]) { - let mut failures = Vec::new(); - for case in cases { - let temp = tempfile::tempdir().unwrap(); - let home = temp.path().join("home"); - let project = temp.path().join("project"); - std::fs::create_dir(&home).unwrap(); - std::fs::create_dir(&project).unwrap(); - let log = temp.path().join("stderr"); - let mut child = Command::new(std::env::current_exe().unwrap()) - .args(["--exact", "goal_budget_worker", "--ignored", "--nocapture"]) - .env_clear() - .env("COVEN_CODE_HOME", &home) - .env("GOAL_FIXTURE_PROJECT", &project) - .env("GOAL_FIXTURE_CASE", case) - .env("GOAL_FIXTURE_DONE", temp.path().join("done")) - .stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(std::fs::File::create(&log).unwrap()) - .spawn() - .unwrap(); - let deadline = Instant::now() + Duration::from_secs(10); - let outcome = loop { - match child.try_wait() { - Ok(Some(status)) => break status, - Ok(None) if Instant::now() < deadline => { - std::thread::sleep(Duration::from_millis(10)) - } - result => { - let _ = child.kill(); - let _ = child.wait(); - panic!("{case}: child wait failed: {result:?}"); - } - } - }; - if outcome.success() { - assert_eq!(std::fs::read(temp.path().join("done")).unwrap(), b"checked"); - } else { - failures.push(format!("{case}: {}", std::fs::read_to_string(log).unwrap())); - } - } - assert!(failures.is_empty(), "{}", failures.join("\n")); + run_cases( + "goal_budget_worker", + &["zero", "plain", "k", "m", "none", "max_storage"], + ); } #[test] diff --git a/src-rust/crates/commands/tests/goal_clear.rs b/src-rust/crates/commands/tests/goal_clear.rs index 96a46cdd..a58d34ee 100644 --- a/src-rust/crates/commands/tests/goal_clear.rs +++ b/src-rust/crates/commands/tests/goal_clear.rs @@ -1,64 +1,18 @@ +#[path = "common/goal.rs"] +mod goal_fixture; + use claurst_commands::{CommandContext, CommandResult, CovenCommand, GoalCommand, SlashCommand}; use claurst_core::{config::Config, cost::CostTracker, Goal, GoalStore}; -use std::process::{Command, Stdio}; -use std::time::{Duration, Instant}; +use goal_fixture::run_cases; #[test] fn failed_goal_deletion_is_reported_without_mutating_goals() { - run_cases(&["direct_failure", "coven_failure"]); + run_cases("goal_clear_worker", &["direct_failure", "coven_failure"]); } #[test] fn successful_and_absent_goal_deletion_keep_existing_behavior() { - run_cases(&["direct_success", "coven_success"]); -} - -fn run_cases(cases: &[&str]) { - let mut failures = Vec::new(); - for case in cases { - let temp = tempfile::tempdir().unwrap(); - let home = temp.path().join("home"); - let project = temp.path().join("project"); - std::fs::create_dir(&home).unwrap(); - std::fs::create_dir(&project).unwrap(); - let log = temp.path().join("stderr"); - let mut child = Command::new(std::env::current_exe().unwrap()) - .args(["--exact", "goal_clear_worker", "--ignored", "--nocapture"]) - .env_clear() - .env("HOME", &home) - .env("USERPROFILE", &home) - .env("COVEN_CODE_HOME", &home) - .env("COVEN_HOME", temp.path().join("coven")) - .env("COVEN_CAVE_HOME", temp.path().join("cave")) - .env("GOAL_FIXTURE_PROJECT", &project) - .env("GOAL_FIXTURE_CASE", case) - .env("GOAL_FIXTURE_DONE", temp.path().join("done")) - .stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(std::fs::File::create(&log).unwrap()) - .spawn() - .unwrap(); - let deadline = Instant::now() + Duration::from_secs(10); - let outcome = loop { - match child.try_wait() { - Ok(Some(status)) => break status, - Ok(None) if Instant::now() < deadline => { - std::thread::sleep(Duration::from_millis(10)) - } - result => { - let _ = child.kill(); - let _ = child.wait(); - panic!("{case}: child wait failed: {result:?}"); - } - } - }; - if outcome.success() { - assert_eq!(std::fs::read(temp.path().join("done")).unwrap(), b"checked"); - } else { - failures.push(format!("{case}: {}", std::fs::read_to_string(log).unwrap())); - } - } - assert!(failures.is_empty(), "{}", failures.join("\n")); + run_cases("goal_clear_worker", &["direct_success", "coven_success"]); } fn assert_goal_unchanged(before: &Goal, after: &Goal) { diff --git a/src-rust/crates/commands/tests/goal_reads.rs b/src-rust/crates/commands/tests/goal_reads.rs index a90e0e50..94766687 100644 --- a/src-rust/crates/commands/tests/goal_reads.rs +++ b/src-rust/crates/commands/tests/goal_reads.rs @@ -1,64 +1,18 @@ +#[path = "common/goal.rs"] +mod goal_fixture; + use claurst_commands::{CommandContext, CommandResult, CovenCommand, GoalCommand, SlashCommand}; use claurst_core::{config::Config, cost::CostTracker, GoalError, GoalStatus, GoalStore}; -use std::process::{Command, Stdio}; -use std::time::{Duration, Instant}; +use goal_fixture::run_cases; #[test] fn corrupt_goal_reads_are_errors_without_mutation() { - run_cases(&["status", "counter"]); + run_cases("goal_read_worker", &["status", "counter"]); } #[test] fn missing_and_valid_goal_reads_keep_existing_behavior() { - run_cases(&["missing", "valid"]); -} - -fn run_cases(cases: &[&str]) { - let mut failures = Vec::new(); - for case in cases { - let temp = tempfile::tempdir().unwrap(); - let home = temp.path().join("home"); - let project = temp.path().join("project"); - std::fs::create_dir(&home).unwrap(); - std::fs::create_dir(&project).unwrap(); - let log = temp.path().join("stderr"); - let mut child = Command::new(std::env::current_exe().unwrap()) - .args(["--exact", "goal_read_worker", "--ignored", "--nocapture"]) - .env_clear() - .env("HOME", &home) - .env("USERPROFILE", &home) - .env("COVEN_CODE_HOME", &home) - .env("COVEN_HOME", temp.path().join("coven")) - .env("COVEN_CAVE_HOME", temp.path().join("cave")) - .env("GOAL_FIXTURE_PROJECT", &project) - .env("GOAL_FIXTURE_CASE", case) - .env("GOAL_FIXTURE_DONE", temp.path().join("done")) - .stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(std::fs::File::create(&log).unwrap()) - .spawn() - .unwrap(); - let deadline = Instant::now() + Duration::from_secs(10); - let outcome = loop { - match child.try_wait() { - Ok(Some(status)) => break status, - Ok(None) if Instant::now() < deadline => { - std::thread::sleep(Duration::from_millis(10)) - } - result => { - let _ = child.kill(); - let _ = child.wait(); - panic!("{case}: child wait failed: {result:?}"); - } - } - }; - if outcome.success() { - assert_eq!(std::fs::read(temp.path().join("done")).unwrap(), b"checked"); - } else { - failures.push(format!("{case}: {}", std::fs::read_to_string(log).unwrap())); - } - } - assert!(failures.is_empty(), "{}", failures.join("\n")); + run_cases("goal_read_worker", &["missing", "valid"]); } #[derive(Debug, Clone, PartialEq, Eq)]