test(tui): isolate user home, config and cache dirs for the TUI tests - #1114
PierrunoYT wants to merge 1 commit into
Conversation
newModel reads <user config>/zero/commands/*.md, and the package has 500+ newModel calls with no isolation, so a developer's own slash commands and state leaked into the TUI tests (and tests could write to real user directories), against the AGENTS.md "Hermetic tests" rule. Add testutil.IsolateUserDirs, which points HOME, USERPROFILE, APPDATA, LOCALAPPDATA and the XDG_* roots at a temp dir (covering Linux, macOS and Windows), and call it from a TestMain in internal/tui. Per-test t.Setenv overrides still win. Refs Twigpine#1103 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedOnly developers with an assigned seat can use this organization's usage-based review budget, and seats here are assigned manually. Ask an admin to assign a seat, or change the review continuation mode in Billing. Next included review available in 32 minutes. View limit detailsLimit details: You’ve used all 4 included reviews currently available. Review configuration: ⚙️ Run configurationConfiguration used: Repository: Twigpine/zero/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (4)
Comment |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Environment and filesystem cleanup failures can be silently ignored, undermining the isolation guarantee.
Review effort: Balanced
Findings: 3
Open (3)
What changed in this PR
Adds package-wide user-directory isolation for TUI tests to prevent access to real user state.
Changes:
- Adds reusable environment isolation and restoration.
- Configures TUI
TestMainwith temporary user directories. - Adds regression tests for directory and command isolation.
| File | Description |
|---|---|
internal/tui/main_test.go |
Establishes package-wide isolation. |
internal/tui/hermetic_test.go |
Verifies TUI isolation behavior. |
internal/testutil/userdirs.go |
Implements the isolation helper. |
internal/testutil/userdirs_test.go |
Tests redirection and restoration. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| for _, name := range userDirEnv { | ||
| value, set := os.LookupEnv(name) | ||
| previous[name] = saved{value: value, set: set} | ||
| _ = os.Setenv(name, root) |
| // helper hands them back (set ones restored, unset ones unset again). | ||
| t.Setenv("HOME", "before-home") | ||
| t.Setenv("XDG_STATE_HOME", "before-state") | ||
| os.Unsetenv("XDG_DATA_HOME") |
| restore := testutil.IsolateUserDirs(root) | ||
| code := m.Run() | ||
| restore() | ||
| _ = os.RemoveAll(root) |

Summary
First, deliberately scoped step of #1103 (test suite is not hermetic).
newModelloads<user config>/zero/commands/*.mdthroughconfig.UserConfigDir(), andinternal/tuihas 500+newModel(calls with no isolation, so a developer's own slash commands and state leak into the TUI tests, and a test could write to the real user directories. That is the "Hermetic tests" rule in AGENTS.md.This PR:
testutil.IsolateUserDirs(root), which pointsHOME,USERPROFILE,APPDATA,LOCALAPPDATAand theXDG_*roots at a temp dir and returns a restore function. All of them are set, sinceos.UserConfigDir/os.UserCacheDirread the XDG variables only on Linux/BSD, derive fromHOMEon macOS, and from%AppData%/%LocalAppData%on Windows;TestMainininternal/tui. Tests that set their own layout witht.Setenvstill win while it is active.Production code is not touched.
Not included, on purpose (AGENTS.md asks that broad changes be discussed first): the
ZERO_CONFIG_DIRoverride inconfig, routing the ~26 non-test callers ofos.User{Config,Home,Cache}Dirthrough it, andTestMainin the other packages. The helper added here is what those follow-ups would call, so this issue should stay open after this PR.Linked issue
Refs #1103 (partial, does not close it).
Note: #1103 does not currently carry the
issue-approvedlabel. Opening this anyway at the author's request; it can be held until the issue is approved.Verification
TestUserDirsAreIsolatedFromTheDeveloperHomechecks that the home, config and cache dirs resolve inside the isolated root. Without theTestMainit fails (home dir "C:\Users\<dev>" is outside the isolated root "", same for config and cache); with it, it passes.TestNewModelLoadsUserCommandsOnlyFromIsolatedConfigchecks a fresh model loads no user commands, and that a command planted in the isolated config dir is the only one it sees.TestIsolateUserDirsRedirectsAndRestores(ininternal/testutil) checks the redirection throughos.UserHomeDir/UserConfigDir/UserCacheDirand that previous values, including unset ones, are restored.go test ./internal/tui/suite passes with the directories redirected (45 s locally on Windows).go build ./...,go vet ./internal/tui/ ./internal/testutil/,gofmt -l,git diff --cached --checkclean.-race, fullgo test ./..., smoke andmaketargets were not run locally.Checklist
issue-approvedlabel. (not yet)go build ./...,go vet ./..., andgo test ./...pass locally. (build passes; vet and tests only for the affected packages)gofmtclean.-racewhere relevant). (tests added;-racenot run locally)🤖 Generated with Claude Code