Files
cleveragents-core/features/git_worktree_coverage_boost.feature
T
HAL9000 fc50a068a4 test(sandbox): add coverage for TOCTOU error cleanup paths in git_worktree.py
Add BDD scenarios to git_worktree_coverage_boost.feature and corresponding
step definitions to cover the new error-path cleanup branches introduced by
the TOCTOU race condition fix:

- create() cleanup of _parent_temp_dir on TimeoutExpired during worktree add
- create() cleanup of _parent_temp_dir on CalledProcessError during worktree add
- commit() cleanup of _parent_temp_dir on TimeoutExpired
- rollback() cleanup of _parent_temp_dir on TimeoutExpired
- cleanup() OSError handler when removing parent temp directory

These branches were previously uncovered, causing the CI coverage job to
fail below the 97% threshold.

ISSUES CLOSED: #7507
2026-04-28 04:06:57 +00:00

150 lines
6.9 KiB
Gherkin

Feature: Git worktree sandbox coverage boost
As a developer
I want to exercise uncovered edge cases in the git worktree sandbox
So that code coverage is maximised for git_worktree.py
# --- _sanitise_branch_name edge case ---
Scenario: Sanitise branch name with all-special-chars falls back to sandbox
When gwtcb _sanitise_branch_name is called with "!!!"
Then gwtcb the result should be "sandbox"
# --- create fails when path is not repo root ---
Scenario: Create fails when path is not the repository root
Given a gwtcb sandbox pointed at a non-root subdirectory
When gwtcb create is called for plan "plan-001"
Then a gwtcb SandboxCreationError should be raised
And the gwtcb sandbox should be in the "errored" state
# --- create times out ---
Scenario: Create raises SandboxCreationError on timeout
Given a gwtcb sandbox with mocked _run_git that times out
When gwtcb create is called expecting a timeout error
Then a gwtcb SandboxCreationError should be raised with message "timed out"
And the gwtcb sandbox should be in the "errored" state
# --- get_path with None worktree_path ---
Scenario: get_path raises SandboxStateError when worktree_path is None
Given a gwtcb sandbox in CREATED state with None worktree_path
When gwtcb get_path is called with "some/file.py"
Then a gwtcb SandboxStateError should be raised with message "Worktree path not set"
# --- commit with uninitialised worktree ---
Scenario: Commit raises SandboxStateError when worktree not initialised
Given a gwtcb sandbox in ACTIVE state with no worktree or branch
When gwtcb commit is called with message "should fail"
Then a gwtcb SandboxStateError should be raised with message "Worktree not initialised"
# --- commit with modified files in diff output ---
Scenario: Commit parses modified files in diff output
Given a gwtcb sandbox ready to commit with modified-file diff output
When gwtcb commit is called with message "modify files"
Then the gwtcb commit result should include changed file "src/modified.py"
And the gwtcb commit result should include added file "src/new.py"
And the gwtcb commit result should include deleted file "src/old.py"
# --- commit timeout ---
Scenario: Commit raises SandboxCommitError on timeout
Given a gwtcb sandbox in ACTIVE state ready to commit
And gwtcb _run_git is mocked to raise TimeoutExpired on commit
When gwtcb commit is called expecting a timeout error
Then a gwtcb SandboxCommitError should be raised with message "timed out"
And the gwtcb sandbox should be in the "errored" state
# --- commit CalledProcessError ---
Scenario: Commit raises SandboxCommitError on CalledProcessError
Given a gwtcb sandbox in ACTIVE state ready to commit
And gwtcb _run_git is mocked to raise CalledProcessError on commit
When gwtcb commit is called expecting a process error
Then a gwtcb SandboxCommitError should be raised with message "Failed to commit"
And the gwtcb sandbox should be in the "errored" state
# --- rollback with uninitialised worktree ---
Scenario: Rollback raises SandboxStateError when worktree not initialised
Given a gwtcb sandbox in ACTIVE state with no worktree or base commit
When gwtcb rollback is called expecting a state error
Then a gwtcb SandboxStateError should be raised with message "Worktree not initialised"
# --- rollback timeout ---
Scenario: Rollback raises SandboxRollbackError on timeout
Given a gwtcb sandbox in ACTIVE state ready to rollback
And gwtcb _run_git is mocked to raise TimeoutExpired on rollback
When gwtcb rollback is called expecting a timeout error
Then a gwtcb SandboxRollbackError should be raised with message "timed out"
And the gwtcb sandbox should be in the "errored" state
# --- rollback CalledProcessError ---
Scenario: Rollback raises SandboxRollbackError on CalledProcessError
Given a gwtcb sandbox in ACTIVE state ready to rollback
And gwtcb _run_git is mocked to raise CalledProcessError on rollback
When gwtcb rollback is called expecting a process error
Then a gwtcb SandboxRollbackError should be raised with message "Failed to rollback"
And the gwtcb sandbox should be in the "errored" state
# --- cleanup with worktree remove failure ---
Scenario: Cleanup falls back to shutil when git worktree remove fails
Given a gwtcb sandbox with a worktree directory that exists
And gwtcb _run_git is mocked to fail on worktree remove
When gwtcb cleanup is called
Then the gwtcb sandbox should be in the "cleaned_up" state
# --- cleanup with branch delete failure ---
Scenario: Cleanup warns and continues when branch delete fails
Given a gwtcb sandbox with a branch name set but no worktree directory
And gwtcb _run_git is mocked to fail on branch delete
When gwtcb cleanup is called
Then the gwtcb sandbox should be in the "cleaned_up" state
# --- create: timeout after parent dir is created (TOCTOU fix coverage) ---
Scenario: Create cleans up parent dir on timeout during git worktree add
Given a gwtcb sandbox with mocked _run_git that times out on worktree add
When gwtcb create is called expecting a timeout error
Then a gwtcb SandboxCreationError should be raised with message "timed out"
And the gwtcb sandbox should be in the "errored" state
# --- create: CalledProcessError after parent dir is created (TOCTOU fix coverage) ---
Scenario: Create cleans up parent dir on CalledProcessError during git worktree add
Given a gwtcb sandbox with mocked _run_git that fails on worktree add
When gwtcb create is called expecting a process error
Then a gwtcb SandboxCreationError should be raised
And the gwtcb sandbox should be in the "errored" state
# --- commit: timeout with parent dir set (TOCTOU fix coverage) ---
Scenario: Commit cleans up parent dir on timeout
Given a gwtcb sandbox in ACTIVE state ready to commit with parent dir set
And gwtcb _run_git is mocked to raise TimeoutExpired on commit
When gwtcb commit is called expecting a timeout error
Then a gwtcb SandboxCommitError should be raised with message "timed out"
And the gwtcb sandbox should be in the "errored" state
# --- rollback: timeout with parent dir set (TOCTOU fix coverage) ---
Scenario: Rollback cleans up parent dir on timeout
Given a gwtcb sandbox in ACTIVE state ready to rollback with parent dir set
And gwtcb _run_git is mocked to raise TimeoutExpired on rollback
When gwtcb rollback is called expecting a timeout error
Then a gwtcb SandboxRollbackError should be raised with message "timed out"
And the gwtcb sandbox should be in the "errored" state
# --- cleanup: OSError when removing parent dir (TOCTOU fix coverage) ---
Scenario: Cleanup continues when parent dir removal raises OSError
Given a gwtcb sandbox with a parent dir that raises OSError on removal
When gwtcb cleanup is called
Then the gwtcb sandbox should be in the "cleaned_up" state