test: unify exec framework - #209
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #209 +/- ##
=======================================
Coverage 89.18% 89.18%
=======================================
Files 3 3
Lines 370 370
=======================================
Hits 330 330
Misses 40 40 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Brought to you by google antigravity. :-) |
8fd5dfa to
ca739c5
Compare
Previously, the `Bash.test` helper did not capture stdout or stderr, causing them to be None. This meant that the assertion `not stdout` was always true (vacuously), and if a test failed, the error message contained no output. Changed the assertion and also the assertion failure message to not hide the "None/None" issue. This commit adds output capturing to `subprocess.Popen`, ensuring that test failures provide useful debugging information -- and it is the prerequisite for reading back what bash actually completes.
201bf5c to
c68685e
Compare
I asked Claude to do it, this is the result. Review carefully! :) |
Every shell now gets the same black-box helper: give it a generated
completion and a command line, get back the candidates that shell
actually offers.
- `bash_candidates` replaces `Bash.compgen`: instead of poking the
generated script's internal arrays, set up `COMP_WORDS`/`COMP_CWORD`
the way readline does (`COMP_WORDBREAKS` splitting included) and call
the registered completion function.
- `zsh_candidates` is new: zsh has no `complete -C`, so drive an
interactive zsh through a pty (like tcsh) with a completion widget
that only ever lists, so even a unique match shows up.
- `fish_candidates`/`tcsh_candidates` keep their mechanism but share the
pty driver and the `(completion, cmdlines, cwd)` signature; tcsh now
lists via `^D` rather than `autolist` (again: unique matches) and the
script is written outside `cwd` so it is not a completion candidate
itself.
- `zsh_specs` stays: it answers a different question (which `_arguments`
spec was generated), which is what the quoting tests need.
`candidates(shell, completion, cmdline)` then dispatches, so the
per-shell `if`/`elif` branches collapse into one assertion and most
`skip("WiP")`s are gone. `Bash` had no users left and is removed.
Running the same expectations on every shell turns up five genuine
differences, marked `xfail` rather than skipped:
- tcsh completes files, not subcommands, after a global option's value
- tcsh offers the options of sibling subcommands
- zsh re-offers earlier positionals' choices at a later slot
- zsh's `_describe` eats a `:` in a subcommand name
- tcsh treats a `/` in a word list as a pathname separator
c68685e to
32480fe
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #209 +/- ##
=======================================
Coverage 85.20% 85.20%
=======================================
Files 3 3
Lines 473 473
Branches 93 93
=======================================
Hits 403 403
Misses 39 39
Partials 31 31 🚀 New features to boost your workflow:
|
yangfan-yf-yf
left a comment
There was a problem hiding this comment.
I found three paths where the new execution harness can report expected test outcomes without having exercised a successful completion. Details inline. The hosted checks are green, but they do not cover these failure paths.
| printf '%s\\n' "${{COMPREPLY[@]}}\"""" | ||
| proc = subprocess.run(['bash', '-o', 'pipefail', '-uc', completion + driver], cwd=cwd, | ||
| capture_output=True, text=True) | ||
| assert not proc.stderr, proc.stderr |
There was a problem hiding this comment.
This checks only stderr and parses stdout even when Bash exits with a non-zero status. For example, bad() { exit 7; }; complete -F bad myprog is reported as an empty candidate list, so a broken completion is indistinguishable from a valid no-match result. The trailing printf also masks a completion function that returns non-zero without exiting. Please propagate the function status, check proc.returncode, and add regression cases for both exit and return.
| nonlocal output | ||
| strip = r"\x1b\[[0-9;?]*[A-Za-z]|\x1b[=>]|[\a\r\b]" | ||
| deadline = time.time() + timeout | ||
| while output.count(PROMPT) < prompts and time.time() < deadline: |
There was a problem hiding this comment.
When the deadline expires, read() returns partial output without verifying that the requested prompt was observed. The caller then parses that output as candidates, so an empty result can satisfy negative assertions even though zsh or tcsh never completed setup or completion. Please raise on a missing prompt and apply a bounded deadline to the drain phase as well.
| assert {"create", "delete", "list"} <= set(candidates) | ||
| completion = complete(test_parser, shell) | ||
| if shell == 'tcsh': | ||
| pytest.xfail("tcsh completes files instead of subcommands after a global option's value") |
There was a problem hiding this comment.
This calls pytest.xfail() before the affected candidate query and assertion. The branch therefore never checks the documented tcsh behavior and can never XPASS after it is fixed. The same pattern occurs in the other four shell-specific xfails on this head. Please mark the affected parameter with pytest.mark.xfail(..., strict=True) so that the query and assertion still run.
Repurposed as requested to fix #243.
Every shell now gets the same black-box helper: give it a generated completion and a
command line, get back the candidates that shell actually offers.
candidates(shell, completion, cmdline)dispatches, so the per-shellif/elifbranches collapse into a single assertion and most
skip("WiP")s are gone.Bash.compgen, poking the generated script's internal arraysbash_candidates: sets upCOMP_WORDS/COMP_CWORDthe way readline does (COMP_WORDBREAKSsplitting included) and calls the registered completion functionzsh_specs(the_argumentsspec array)zsh_candidates: zsh has nocomplete -C, so drive an interactive zsh through a pty with a widget that only ever lists, so even a unique match shows upautolist, script written intocwd^D(list-choices) so unique matches show up, and the script is written outsidecwdso it is not a candidate itselfcomplete -C(completion, cmdlines, cwd)signaturezsh_specsis kept rather than renamed: it answers a different question (which spec wasgenerated), which is what the
#224quoting tests need.The first commit is the original content of this PR (
Bash.testcaptured neither stdoutnor stderr, so
assert not stdoutwas vacuous) — capturing the output is what makesreading back bash's candidates possible.
Bashitself has no users left and is removed.Test counts: 71 passed / 33 skipped → 105 passed / 9 skipped / 5 xfailed (runtime 2.6s → 24s,
the pty-driven shells).
Running the same expectations on every shell surfaces five real differences
Marked
xfail(so they show up under the existing-rxs) rather than skipped — happy tosplit any of these off into their own issues:
_describereads the:in asub:cmdsubcommand as its name/description separator/in a word list as a pathname separator, sosub/cmdlists assubThe last two are exactly what
test_subparser_colons/test_subparser_slasheswere writtento guard against; they were invisible while only bash was exercised.