test(xtask): gate --append-verify phase-2 redo in the validate matrix - #7232
Open
oferchen wants to merge 2 commits into
Open
test(xtask): gate --append-verify phase-2 redo in the validate matrix#7232oferchen wants to merge 2 commits into
oferchen wants to merge 2 commits into
Conversation
This was referenced Aug 6, 2026
oferchen
force-pushed
the
test/xtask-verify-redo-check
branch
from
August 7, 2026 01:34
f771a68 to
cee0cda
Compare
The fidelity matrix never forced a verification redo: append-inplace seeds a matching prefix, so its --append-verify re-checksum succeeds and the phase-2 redo path is never entered. Add a verify-redo check that seeds a destination which is both shorter than the source and wrong (100 KiB of zeros against a 200 KiB deterministic payload), so the re-checksum fails and the receiver retains the update and requests MSG_REDO. Every (transport, direction, verbosity) cell asserts exit code parity, byte-identical destinations, the exact upstream 'failed verification' stderr lines, and the --stats literal/matched split. Upstream gates the warning behind INFO_GTE(NAME, 1) (receiver.c:1072), so the oracle is silence by default and one bare-relative-name line under -v; both are asserted. Non-vacuous guards: the seed must be shorter than and differ from the source, and upstream must report the file transferred twice.
The verify-redo check read only stderr, so a cell where oc emits the failed-verification line on stdout compared [] against upstream's [] and passed. Measured against rsync 3.4.4: on daemon pull oc writes the line to stdout at every verbosity while upstream is silent by default and writes to stderr under -v, so that cell passed assertion 3 vacuously and only failed later on the delta split. Capture the lines per stream and compare stdout and stderr separately. Upstream gates the line behind INFO_GTE(NAME, 1) (receiver.c:1072) and rwrite() routes FWARNING to stderr (log.c:314), so the oracle is: absent from both streams by default, present on stderr alone under -v. The failure message now names the stream the line landed on - the text is identical either way, so a bare "not found" points at a missing emit when the fault is a misrouted one.
oferchen
force-pushed
the
test/xtask-verify-redo-check
branch
from
August 8, 2026 19:51
cee0cda to
de4da20
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
cargo xtask validatenever forced a phase-2 verification redo.checks/append_inplace.rsdoes run--append-verify, but it seeds a matching prefix, so the re-checksum succeeds and the redo path is never entered. Three real divergences live behind that gap and the matrix could not see any of them.This PR adds the gate. It does not fix the divergences - it makes them visible and keeps them fixed once they are.
What
New
xtask/src/commands/validate/checks/verify_redo.rs, registered next toappend-inplacein the "Transfer decisions and deletion" group. CategoryValidationonly, so a barecargo xtask validateruns it.Fixture - source
payload.binis 200 KiB of deterministic index-hashed bytes; the destination is pre-seeded with 100 KiB of zeros, so it is both shorter than the source and wrong.--append-verifyappends the tail, the re-checksum fails, the receiver retains the update and asks the generator to redo it (receiver.c:1070,send_msg_int(MSG_REDO, ndx)). Flags:-a --append-verify --ignore-times --numeric-ids --stats.Cells - one per
(transport, direction, verbosity). Push is skipped onlocal(a local push is the same local-copy code path as the pull, so it would be a duplicate cell, not coverage); ssh cells skip when no sshd answers on localhost:22.Assertions, all four per cell:
comparison::exit_code_difffacet, so a non-zero oc exit is reported as a divergence rather than swallowed as an unrunnable cell).failed verificationlines are exactly upstream's, at each verbosity, per stream - stdout and stderr are checked separately so a line emitted on the wrong stream is a failure, not a vacuous match.--statsliteral/matched split matches upstream's.Non-vacuous guards - the seeded destination must really be shorter than and differ from the source before the transfer, and upstream must report
Number of regular files transferred: 2(the one file counted twice is the redo). Either guard failing is aFAIL, not a silent pass.Correction to the assumed oracle
The premise this check was scoped from said the warning prints at default verbosity. It does not. Upstream prints the line only when
The first failure is a
FWARNINGand the redo then succeeds, so nothing ever reaches the ungatedFERROR_XFERform. Measured on rsync 3.4.4 across local, daemon pull and daemon push: stderr is empty without-v, and under-vit is exactlySo the check encodes the measured oracle at both verbosities: upstream's exact silence by default, and upstream's exact bare-relative-name line under
-v. That is strictly stronger than asserting the line at one verbosity - it catches a warning that is missing and one that is emitted where upstream is silent.Currently failing cells (expected, not papered over)
Measured with upstream rsync 3.4.4 as ground truth,
--transport local --transport daemon(ssh cells skipped - no sshd on the measuring host). Each cell reports its first failing assertion.local pull defaultlocal pull verboseWARNING:line on stderrdaemon pull defaultdaemon pull verboseWARNING:line on stderr, stdout emptydaemon push defaultdaemon push verboseThree distinct open divergences, all already tracked separately:
-v) but its redo delta is off by 400 bytes in each direction (205,700 / 101,500 against 205,300 / 101,900) - a block-boundary difference, not a whole-file resend.Note on reading the table: each cell reports only its first failing assertion, so
daemon pull's literal/matched divergence is now masked behind the earlier assertion-3 failure and will resurface once the emit site is fixed. That ordering is deliberate - reporting the misrouted warning first points at the nearer cause.None of the assertions were relaxed to get a green run. A red cell here is the correct result until the underlying behaviour is fixed.
Correction: the receiver-side warning is on stdout, not missing
An earlier revision of this description said daemon pull "never prints the warning, even under
-v". That is wrong, and the assertion as first written could not tell the difference. Re-measured on the same fixture against/opt/homebrew/bin/rsync3.4.4, counting thefailed verificationline per stream:-vpayload.bin<dst>/payload.bin-v<dst>/payload.binSo oc emits the line on the wrong stream, with the wrong name form, at a verbosity where upstream is silent - three divergences at once. Because assertion 3 originally filtered
stderronly, the default-verbosity cells compared[] == []and passed that assertion vacuously; the-vcells failed with a message that read as "oc printed nothing".Assertion 3 is therefore stream-aware, in the second commit on this branch: the oracle is an
ExpectedWarnings { stdout, stderr }pair,stdoutis empty at every verbosity (upstreamrwrite()mapsFWARNINGtof = stderr,log.c:314- verified in the C source, not assumed), and the failure message names the stream and calls out a misrouted line explicitly. Detection still uses the barecontains("failed verification")substring on both streams, so the absolute-path form is caught rather than filtered out as absent; the name shape is then judged by the exact-string comparison against upstream's captured line. Fixed on this branch rather than in a stacked follow-up, since the PR is still open and a vacuous assertion should not be merged and then patched.Deviations from the sibling check's pattern
append-inplacestamps a fixed mtime withtouch -d @epochbecause its reuse decision depends on mtime equality. Here the transfer is forced by the differing size plus--ignore-times, and every assertion (bytes, exit code, warning lines, delta split) is mtime-independent - so the stamp buys nothing, while depending on it makes the whole check skip on any host whosetouchis the BSD one. Dropping it is what let the check actually run and produce the table above.output()and is killed on return.Validationonly, notWire. The redo is a protocol round-trip, but every assertion here is client-observable behaviour (exit code, bytes, stderr, stats) rather than captured wire frames, which is whatcapability-string- the soleWiremember - actually inspects. Keeping it inValidationalso means a barecargo xtask validategates it, which is the point.Verification
cargo fmt --all -- --checkcleancargo clippy -p xtask --all-targets --all-features --no-deps -- -D warningsclean (noallowwaivers)cargo clippy --locked --workspace --all-targets --all-features --no-deps -- -D warningsclean (the full CI invocation, re-run on the head commit)cargo nextest run -p xtask --all-features -E 'test(verify_redo)'- 10 passed. The full-p xtaskrun is 433/434; the one failure is the pre-existing macOS-onlyvalidate::support::tests::backdated_tree_populates_and_backdates_the_root, which needs a GNUtouch -d @epochand is untouched by this changecargo xtask validate --listshowsverify-redo [validation];--helpunchanged