Rust: snapshot tests for consume_stream UTF-8 replacement output (#105) - #241
Rust: snapshot tests for consume_stream UTF-8 replacement output (#105)#241leynos wants to merge 2 commits into
Conversation
consume_stream_files' read-and-decode loop had no Rust-level test pinning its observable UTF-8 output; only the incremental decoder in utf8.rs was property-tested, and the PyO3 boundary is covered on the Python side (test_rust_streams.py::TestRustConsumeStream). Add src/consume_snapshot_tests.rs with insta inline-snapshot tests that drive the full loop through a real pipe for the four categories the Python oracle suite also covers: - pure ASCII decodes verbatim - multi-byte sequences split across buffer boundaries (buffer_size 1) decode identically to a whole-payload buffer - invalid bytes become U+FFFD - an incomplete trailing sequence resolves to U+FFFD at EOF The boundary-independence assertions pin that the output does not depend on where reads split a multi-byte sequence. insta is added as a default-features-off dev-dependency. Closes #105 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reviewer's GuideAdds Unix-only Rust snapshot tests using Sequence diagram for consume_stream_files UTF-8 snapshot testssequenceDiagram
participant TestRunner
participant consume_snapshot_tests
participant consume_stream_files
participant insta
TestRunner->>consume_snapshot_tests: pure_ascii_decodes_verbatim
consume_snapshot_tests->>consume_stream_files: consume_stream_files(read_fd, write_fd, buffer_size)
consume_stream_files-->>consume_snapshot_tests: decoded_text
consume_snapshot_tests->>insta: assert_snapshot(decoded_text)
TestRunner->>consume_snapshot_tests: invalid_bytes_become_replacement_characters
consume_snapshot_tests->>consume_stream_files: consume_stream_files(read_fd, write_fd, buffer_size)
consume_stream_files-->>consume_snapshot_tests: decoded_text
consume_snapshot_tests->>insta: assert_snapshot(decoded_text)
TestRunner->>consume_snapshot_tests: incomplete_trailing_sequence_is_replaced_at_eof
consume_snapshot_tests->>consume_stream_files: consume_stream_files(read_fd, write_fd, buffer_size)
consume_stream_files-->>consume_snapshot_tests: decoded_text
consume_snapshot_tests->>insta: assert_snapshot(decoded_text)
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdd Unix-only integration-style snapshot tests for ChangesUTF-8 stream snapshot tests
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 19 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (19 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@rust/cuprum-rust/src/consume_snapshot_tests.rs`:
- Around line 7-10: Add end-to-end PyO3 integration cases in
TestRustConsumeStream for multibyte UTF-8 sequences split across buffer
boundaries and incomplete trailing bytes at EOF, matching the documented Python
oracle categories. Keep the existing invalid-byte coverage and ensure these
scenarios cross the Python/Rust boundary before retaining the module’s
full-coverage claim.
- Around line 73-77: Extend the equality assertions in the invalid-byte and
incomplete-tail tests around consume_snapshot_tests.rs to include
consume(payload, 3) alongside the existing buffer sizes 1 and 64. Ensure both
replacement-case tests verify identical output across one-byte, three-byte, and
whole-payload reads.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: f93ffd86-9684-4256-a4b7-7d86c0dab710
⛔ Files ignored due to path filters (1)
rust/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (3)
rust/cuprum-rust/Cargo.tomlrust/cuprum-rust/src/consume_snapshot_tests.rsrust/cuprum-rust/src/lib.rs
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/shared-actions(auto-detected)leynos/pylint-pypy-shim(auto-detected)leynos/whitaker(auto-detected)
| //! four categories the Python oracle suite also covers — pure ASCII, multi-byte | ||
| //! sequences split across buffer boundaries, invalid bytes, and an incomplete | ||
| //! trailing sequence at EOF — so a regression in the loop, the bounds-checked | ||
| //! slicing, or the `final_chunk` handling shows up as a concrete text diff. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Add the missing Python boundary cases.
The module claims that the Python oracle covers all four categories, but the existing TestRustConsumeStream coverage only exercises invalid UTF-8; split multibyte input and incomplete trailing bytes do not cross the PyO3 boundary. Add those end-to-end scenarios before claiming full coverage, or narrow this documentation; Issue #105 remains only partially covered otherwise.
As per coding guidelines, externally observable behavioural changes require end-to-end tests at the integration boundary.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@rust/cuprum-rust/src/consume_snapshot_tests.rs` around lines 7 - 10, Add
end-to-end PyO3 integration cases in TestRustConsumeStream for multibyte UTF-8
sequences split across buffer boundaries and incomplete trailing bytes at EOF,
matching the documented Python oracle categories. Keep the existing invalid-byte
coverage and ensure these scenarios cross the Python/Rust boundary before
retaining the module’s full-coverage claim.
Sources: Coding guidelines, MCP tools
| assert_eq!( | ||
| byte_at_a_time, | ||
| consume(payload, 64), | ||
| "invalid-byte replacement must not depend on the buffer size", | ||
| ); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Exercise the three-byte boundary in both replacement cases.
The invalid-byte and incomplete-tail tests compare only buffer sizes 1 and 64. Add consume(payload, 3) to each equality chain so these required cases verify output independence across one-byte, three-byte, and whole-payload reads; otherwise a three-byte boundary regression passes unnoticed.
As per coding guidelines, unit tests must cover meaningful edge cases and invariants.
Also applies to: 90-94
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@rust/cuprum-rust/src/consume_snapshot_tests.rs` around lines 73 - 77, Extend
the equality assertions in the invalid-byte and incomplete-tail tests around
consume_snapshot_tests.rs to include consume(payload, 3) alongside the existing
buffer sizes 1 and 64. Ensure both replacement-case tests verify identical
output across one-byte, three-byte, and whole-payload reads.
Source: Coding guidelines
Both replacement tests now assert identical output across one-byte,
three-byte, and whole-payload reads, matching the multibyte test. The
three-byte case is the interesting middle ground for the incomplete tail,
since it splits the truncated euro sign differently again.
The module docstring claimed these snapshots covered "the four categories
the Python oracle suite also covers", which overstated what is verified.
TestRustConsumeStream does declare all four against rust_consume_stream —
ASCII, a boundary-split snowman at buffer_size 2, invalid bytes, and a
truncated trailing sequence — each checked against
payload.decode("utf-8", errors="replace"). But those cases are gated on
the compiled extension being importable, and nothing on the test path
builds it: make build only runs uv sync, and the CI typecheck-test job
runs make typecheck and make test without maturin develop, which appears
only in the benchmark-ratchet job. They therefore skip, locally and in CI.
Adding the two further Python cases the review asked for would have added
no coverage for the same reason, so the docstring now states the position
accurately instead: the Python suite declares the categories, these
snapshots are what actually executes for them.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Both addressed in 4f6693d — one applied as asked, one that turned out to be right for a different and more serious reason than stated. 2. Three-byte buffer in the replacement tests ✅Applied. Both the invalid-byte and incomplete-tail tests now assert identical output across one-byte, three-byte, and whole-payload reads, matching the multibyte test. The three-byte case is genuinely the interesting middle ground for the incomplete tail, since it splits the truncated euro sign differently again. 1. The Python integration cases — investigated, and the docstring corrected insteadThe literal request was to add multibyte-split and incomplete-trailing cases to
Each calls But your underlying instinct was right, and the reason is worse than a missing test. Chasing "ensure these scenarios cross the Python/Rust boundary", I ran them — and all seven The
I verified this locally: after So adding the two requested cases would have added no coverage at all — they would have skipped alongside the existing four, while making the suite look better than it is. That seemed strictly worse than the honest alternative, so I corrected the overstated claim instead. The docstring no longer says these snapshots mirror what the Python oracle "covers"; it records that the Python suite declares the categories, that they are gated on an extension the test path never builds, and that these Rust-side snapshots are consequently the coverage that actually executes. Happy to add the Python cases anyway if you would rather have them staged for whenever the extension does get built — say the word. Worth raising separatelyThat the Rust-backend Python tests never execute in CI is a real gap well beyond this PR: it silently disables every Validation
|
Summary
consume_stream_files(the read-and-decode loop behind the PyO3rust_consume_stream) had no Rust-level test pinning its observable UTF-8 output. Only the incremental decoder inutf8.rswas property-tested (againstString::from_utf8_lossy), and the compile-time UI tests only check PyO3 macro patterns. This addsinstasnapshot tests exercising the full loop.What's added
rust/cuprum-rust/src/consume_snapshot_tests.rsdrives real pipe descriptors throughconsume_stream_filesand pins the exact output for the four categories from #105:pure_ascii_decodes_verbatimcuprum reads pipesmultibyte_sequences_split_across_buffer_boundarieshéllo, 世界! ☕invalid_bytes_become_replacement_charactersx\xffy\x80zincomplete_trailing_sequence_is_replaced_at_eofeuro sign: \xe2\x82The multi-byte, invalid, and incomplete cases additionally assert boundary-independence — a one-byte buffer, a three-byte buffer, and a whole-payload buffer all decode to the same text — so a regression in the bounds-checked slicing or
final_chunkhandling surfaces as a concrete diff.instais added as adefault-features = falsedev-dependency (v1.48.0); the snapshots are inline, so there are no separate.snapfiles to manage.Boundary already covered on the Python side
The issue's second bullet (integration through the Python/Rust boundary) is already satisfied by
cuprum/unittests/test_rust_streams.py::TestRustConsumeStream, which feeds ASCII, a boundary-split multi-byte scalar (buffer_size=2), invalid bytes, and an incomplete trailing sequence throughrust_consume_streamand asserts againstpayload.decode("utf-8", errors="replace"). These Rust snapshots complement that by pinning the exact decoded text one layer down, at the read loop itself.Validation
Full gates green:
make check-fmt,make lint(clippy-D warnings,cargo doc -D warnings, interrogate 100%, pylint 10.00/10),make test(pytest 755 passed / 47 skipped; Rust nextest 61/61 including the four new cases).Closes #105
🤖 Generated with Claude Code
Summary by Sourcery
Add Rust snapshot tests to pin the UTF-8 replacement behavior of the consume_stream_files read loop using real pipe descriptors.
Build:
Tests: