Repository navigation
refactor(compare,fastq) + test: in-process Command::execute for Phase 3 (#352) - #355
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #355 +/- ##
==========================================
- Coverage 90.93% 90.91% -0.03%
==========================================
Files 78 78
Lines 51046 51074 +28
==========================================
+ Hits 46421 46432 +11
- Misses 4625 4642 +17 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
51d4d49 to
29dec92
Compare
bedf332 to
040eef4
Compare
|
@coderabbitai resume |
|
@coderabbitai review |
📝 WalkthroughWalkthroughThis PR refactors compare subcommands to return errors instead of calling 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
✅ Actions performedReview triggered.
|
✅ Actions performedReviews resumed. |
|
@coderabbitai resume |
|
@coderabbitai review |
✅ Actions performedReviews resumed. |
✅ Actions performedReview triggered.
|
|
@coderabbitai resume |
|
@coderabbitai review |
✅ Actions performedReviews resumed. |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@src/lib/commands/fastq.rs`:
- Around line 200-203: The code currently calls File::create(path) (inside the
match on self.output) which truncates the target before input is opened in
run_with_writer, risking clobbering when --output equals --input; update the
logic to detect and prevent that by checking the output path against the input
path (e.g., compare self.output path to self.input path) before calling
File::create, and return an error if they are the same, or alternatively open
the input first or write to a temporary file and atomically rename into place;
change the branch that uses File::create + BufWriter::with_capacity to perform
this safety check (refer to self.output, self.input, File::create, and
run_with_writer).
🪄 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: CHILL
Plan: Pro
Run ID: 56a9a693-324c-40eb-919d-f2443e61d790
📒 Files selected for processing (9)
src/lib/commands/compare/bams.rssrc/lib/commands/compare/metrics.rssrc/lib/commands/compare/mod.rssrc/lib/commands/fastq.rssrc/main.rstests/integration/test_compare_bams.rstests/integration/test_e2e_regression.rstests/integration/test_fastq_command.rstests/integration/test_zipper_command.rs
test_group_determinism.rs is intentionally kept on the subprocess path so each run picks up a different per-process AHashMap hasher seed; that variance is the property the test was written to exercise.
29dec92 to
bb40c3b
Compare
The compare subcommand previously called std::process::exit(1) on any mismatch or validation failure. This kept in-process callers (e.g. integration tests under cargo llvm-cov nextest) from observing the result. Introduce a CompareMismatch error variant; the CLI maps it back to exit code 1 in main.rs, while in-process callers can downcast. No change to CLI behavior or exit codes.
Convert the 8 test_compare_bams.rs tests that assert only on IDENTICAL/DIFFER and the run_compare_bams_mode / assert_bams_identical helpers in test_e2e_regression.rs to call CompareBams::execute() directly, downcasting on CompareMismatch to distinguish match from mismatch. The remaining 9 test_compare_bams.rs tests stay on the subprocess path because they assert on specific report substrings (EQUIVALENT, Order/name mismatches: N, tags in different order, Missing MI in BAM[12]: N, etc.) that aren't captured in-process.
The fastq command previously wrote unconditionally to stdout, which made in-process tests need an explicit stdout capture. Add an optional --output/-o flag; when present, the FASTQ stream is written to the named file. When omitted, the existing stdout behavior is preserved (stdout remains the default to keep `fgumi fastq -i in.bam | bwa mem` working without flag changes). Extract the conversion loop into a generic Fastq::run_with_writer helper so execute() dispatches the writer type at one place instead of duplicating the loop.
Pass the new --output flag (added in the prior commit) to write FASTQ output directly to a temp file, then parse the file as before. No subprocess stdout capture needed.
… tests Converts the 3 fully-in-process-eligible subprocess invocations to in-process Command::execute() calls. Two tests intentionally stay on the subprocess path: - test_zipper_bam_stdin_input exercises the std::io::stdin() code path inside zipper, which only exists at the process boundary. - test_zipper_bam_mapped_input asserts on a log::warn! "BAM input detected" warning sent to stderr; observing that in-process would require global-logger plumbing in the test harness.
040eef4 to
b964c20
Compare
Summary
Phase 3 of #352, stacked on #354. Contains the two production refactors the issue called out as prerequisite, plus the test conversions they unlock.
Production refactors
compare: replaces 7std::process::exit(1)sites insrc/lib/commands/compare/{bams,metrics}.rswithErr(CompareMismatch(...)).CompareMismatchis a new public, downcastableanyhow-compatible error variant.src/main.rsdowncasts on it and maps toexit(1)so the CLI exit-code contract is preserved byte-for-byte.fastq: adds optional--output/-oflag. When provided, FASTQ writes to the file; when omitted, the priorstdout()behavior is preserved (still the default forfgumi fastq -i in.bam | bwa mem ...). The conversion loop is factored into a genericFastq::run_with_writer<W: Write>helper.Test conversions
test_compare_bams.rs: 8 of 17 tests converted to in-process (those that only check IDENTICAL/DIFFER — fully covered by theResulttype). The other 9 tests stay on the subprocess path because they assert on specific diagnostic substrings (EQUIVALENT,Order/name mismatches: N,tags in different order,Missing MI in BAM[12]: N, etc.) that aren't observable in-process. Both helpers (run_comparefor subprocess,run_compare_in_processfor in-process) coexist; tests pick the one that matches their assertion shape.test_e2e_regression.rs: thecompare_bamsandassert_bams_identicalhelpers move in-process; thetest_different_seeds_produce_different_outputtest now asserts!compare_bams_in_process(...)instead ofoutput.status.code() == Some(1). The file's other subprocess helpers (fgumi,fgumi_ok) stay untouched — they're Phase 4 scope.test_fastq_command.rs: all 7 tests now pass-o <tempfile>to write FASTQ directly to a temp file; thefs::write(&output_fq, &output.stdout)middle step is gone.test_zipper_command.rs: 3 of 5 tests converted to in-process. Two stay subprocess:test_zipper_bam_stdin_input— exercises thestd::io::stdin()pipe path insidezipper, which only exists at the process boundary.test_zipper_bam_mapped_input— asserts on alog::warn!("BAM input detected")warning captured from stderr; capturing that in-process would require global-logger plumbing in the test harness.Phasing
Commits
Test plan
cargo nextest run --features compare,simulate --test integration— 193/193 passed, 23 skippedcargo build(default features) — cleancargo build --features compare— cleancargo ci-fmtcleancargo ci-lintclean (default features)execute()bodiescomparerefactor (now returningErr(CompareMismatch)instead ofprocess::exit(1)in-process) does not affect any caller — onlymain.rsand the integration tests use it, both updated here