test(context_engine): skip the chmod attachment case when the runner is root - #313
Conversation
…is root The case chmods a file to 000 and expects `build_user_content` to report an unreadable attachment as a note. Root ignores the mode bits, so the read succeeds, the picture is inlined, and the assertion sees content blocks where it wanted a string. Our runner is root; GitHub's is not, which is why the case arrived green from upstream and failed here on its first run. Guarded rather than rewritten: the behaviour under test is worth pinning where permissions actually apply. Same spelling as the existing guard in tests/test_importer_hermes_skills.py. `os` moves to module scope because the decorator is evaluated there. Co-authored-by: Claude (claude-opus-5) <noreply@anthropic.com>
|
@claude review |
|
Claude finished @0xKT's task in 2m 19s —— View job Review:
|
gloryfromca
left a comment
There was a problem hiding this comment.
No blockers; this can merge as far as I am concerned.
What I checked
The diff itself, the surrounding test, the repo's own conventions (AGENTS.md sections 1/2/3/5), whether the skip weakens coverage, CI configuration, and prior art in the tree.
The skip is honest, not a green-wash. The concern with skipif is always that a case stops asserting anything. Here the guard is keyed to os.geteuid() == 0 only, so every non-root run still executes the full body. Verified locally at euid 501:
uv run pytest tests/test_read_file_image.py -q -rs
106 passed in 16.44s # 0 skipped, the case ran its assertions
uv run ruff check tests/test_read_file_image.py
All checks passed!
That matches the description's root-side figure (105 passed, 1 skipped) as the complement. The unit matrix in .github/workflows/ci.yml is ubuntu-latest and does not run as root, so CI keeps exercising the case exactly as before; the skip only fires on a root developer box.
The alternative would have been worse. The behaviour under test is what build_user_content does when the read raises. As root, DAC is bypassed, so the only ways to reach that path are patching the read or forcing a delete between resolution and read -- both of which assert against a mock rather than against the renderer. Guarding the case is the right trade, and the reason string names the cause so nobody has to rediscover it.
It matches prior art. tests/test_importer_hermes_skills.py already carries the identical decorator and reason string at two sites, so this is the established spelling in this repo rather than a new local invention. Moving import os to module scope is required, since the decorator is evaluated at collection time.
Conventions. Branch test/skip_chmod_case_as_root fits the <type>/<snake_desc> form; the commit header is 74 chars, lowercase, no trailing period, scope is a real subpackage; commit message and PR description are both ASCII-clean (grepped with [^\x00-\x7F], zero matches); the Co-authored-by trailer is present in the commit and absent from the PR description, which is what squash-merge wants. No source file is touched, so there is no backward-compatibility surface.
One pre-existing note, not a finding against this diff: os.geteuid does not exist on Windows, so a module-scope call would be an AttributeError at collection there. This is already the situation in test_importer_hermes_skills.py, the unit matrix never runs on Windows, and the one windows-latest job runs a single unrelated integration file -- so nothing this PR does makes any run fail. Worth a sys.platform guard someday if the suite ever needs to collect on Windows; out of scope here.
Summary
test_an_attachment_that_cannot_be_read_costs_a_note_not_the_turnmakes a fileunreadable with
chmod 000and asserts the renderer notes the failed attachmentinstead of failing the whole turn.
chmod 000does not block a root user, sothe file stays readable, the error path is never entered, and the case fails for
anyone running the suite as root. It passes in CI, which does not run as root,
so the failure is invisible there and shows up only on a developer's machine.
Skipped for root rather than reworked: the behaviour under test is what happens
when a read raises, and making that happen without permissions means faking the
error, which would test the mock. The case is worth keeping for the runs that
can exercise it honestly.
The commit is
0xKT's, cherry-picked from the GitLab trunk where it alreadylanded. Authorship is preserved.
Type
Test-only.
Verification
Before this, the same command as root gave
1 failed, 105 passed, with thefailure on this case. The skip reason names the cause, so a reader is not left
guessing why it is absent.
Risk
None to the product: no source file is touched. Non-root runs, CI included,
execute the case exactly as before.
Related Issues
N/A