mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-08 08:04:25 -10:00
test(tui): seal HOME for the /context baseline tests
`commands::debug_diagnostics_baseline_tests::context_routing_and_report_
branches_match_baseline` failed on any machine whose real home carries global
instructions or installed skills: `/context report` counts both, so the frozen
token totals moved (here ~/.codewhale/instructions.md is 126,359 bytes, past the
102,400-byte cap, and the user's skills load too). The fixture owned its
workspace and skills directory but not the user's home.
Fix: `SealedHome` (debug_diagnostics_test_support)
takes lock_test_env and pins HOME, USERPROFILE and CODEWHALE_HOME to empty
temp dirs for the test's life, the same seal the restore-route tests use
(81d9ec8dc). Applied to the two baseline tests that read the report.
Sibling found by the real-home vs empty-home comparison:
`context_alias_and_bare_action_are_preserved` compares `/ctx report` with
`/context report` byte for byte and failed 6 of 40 real-home runs (the skills
block moved between the two calls: 8103 vs 8589 tokens); 0 failures in 60
real-home and 10 empty-home runs after sealing. Nothing else in the module
differed.
Comparison runs (family filter `commands::debug_diagnostics`, 87 tests; the
real-home loop is read-only for this family, checked by file mtimes):
- before, baseline release binary: real home 86 passed 1 failed (the target);
empty temp HOME+CODEWHALE_HOME 87 passed 0 failed.
- after: real home 60/60 runs 87 passed 0 failed; empty home 10/10 87 passed.
- `commands::debug_diagnostics_baseline_tests` 14 passed 0 failed.
Not run: the full suite, hosted CI, Windows (the seal sets USERPROFILE too).
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Signed-off-by: CodeWhale Bot <[email protected]>
This commit is contained in:
1 parent
bc37c1cbad
commit
1969203080
2 files changed
+48
-1
No files matched your search
@@ -14,7 +14,7 @@
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::commands::debug_diagnostics_test_support::{
|
||||
DiagnosticsHarness, assert_fixture, normalize_cache_ages,
|
||||
DiagnosticsHarness, SealedHome, assert_fixture, normalize_cache_ages,
|
||||
};
|
||||
use crate::commands::{CommandResult, execute};
|
||||
use crate::config::ApiProvider;
|
||||
@@ -237,6 +237,8 @@ fn system_alias_and_truncation_boundary_are_preserved() {
|
||||
/// shared renderer; an unknown subcommand is an exact error with no action.
|
||||
#[test]
|
||||
fn context_routing_and_report_branches_match_baseline() {
|
||||
// The report counts the user's global instructions and installed skills.
|
||||
let _home = SealedHome::new();
|
||||
let mut harness = DiagnosticsHarness::new();
|
||||
assert_fixture(
|
||||
"context_bare.txt",
|
||||
@@ -265,6 +267,10 @@ fn context_routing_and_report_branches_match_baseline() {
|
||||
/// must return the inspector action with no message.
|
||||
#[test]
|
||||
fn context_alias_and_bare_action_are_preserved() {
|
||||
// The alias and canonical reports are compared byte for byte, and both
|
||||
// enumerate the user's installed skills: on a developer machine their
|
||||
// discovery can differ between two calls in one test.
|
||||
let _home = SealedHome::new();
|
||||
let mut harness = DiagnosticsHarness::new();
|
||||
let bare = execute("/context", &mut harness.app);
|
||||
assert!(bare.message.is_none());
|
||||
|
||||
@@ -19,8 +19,49 @@ use regex::Regex;
|
||||
use tempfile::TempDir;
|
||||
|
||||
use crate::config::ApiProvider;
|
||||
use crate::test_support::{EnvVarGuard, TestEnvLock, lock_test_env};
|
||||
use crate::tui::app::{App, TuiOptions};
|
||||
|
||||
/// Seal `HOME`, `USERPROFILE` and `CODEWHALE_HOME` onto empty temporary
|
||||
/// directories for the life of one test.
|
||||
///
|
||||
/// The diagnostics surface reads the *user's* state: global instructions
|
||||
/// (`~/.codewhale/instructions.md`), installed skills, persisted settings. A
|
||||
/// fixture that only owns its workspace and skills directory still lands
|
||||
/// those reads on the developer's real home, so token totals and context
|
||||
/// reports change with whoever runs the suite. Take this first in any test
|
||||
/// whose output depends on them, before building a [`DiagnosticsHarness`]:
|
||||
/// it holds the process-wide environment lock, which the harness's settings
|
||||
/// loader re-enters. Keep one per test; the lock is not reentrant across
|
||||
/// two seals.
|
||||
pub(crate) struct SealedHome {
|
||||
// Drop order matters: restore the environment, then delete the
|
||||
// directories, then release the lock.
|
||||
_codewhale_home: EnvVarGuard,
|
||||
_userprofile: EnvVarGuard,
|
||||
_home: EnvVarGuard,
|
||||
_dir: TempDir,
|
||||
_lock: TestEnvLock,
|
||||
}
|
||||
|
||||
impl SealedHome {
|
||||
pub(crate) fn new() -> Self {
|
||||
let lock = lock_test_env();
|
||||
let dir = TempDir::new().expect("sealed home tempdir");
|
||||
let home = dir.path().join("home");
|
||||
let codewhale_home = dir.path().join("codewhale-home");
|
||||
std::fs::create_dir_all(&home).expect("sealed home dir");
|
||||
std::fs::create_dir_all(&codewhale_home).expect("sealed codewhale home dir");
|
||||
Self {
|
||||
_home: EnvVarGuard::set("HOME", &home),
|
||||
_userprofile: EnvVarGuard::set("USERPROFILE", &home),
|
||||
_codewhale_home: EnvVarGuard::set("CODEWHALE_HOME", &codewhale_home),
|
||||
_dir: dir,
|
||||
_lock: lock,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Host-isolated fixture for the diagnostics command surface.
|
||||
///
|
||||
/// The hermetic test-home wrapper isolates persisted settings. The owned
|
||||
|
||||
Reference in new issue
Block a user