test(sdcard): direct tests for SdCardParseSource's rewind, lease latch and stream ownership - #654
Conversation
…m ownership SdCardParseSource is the rewind-and-re-read primitive behind every lazy SD card log session, and it had no tests of its own. The parser fixtures reach it only along the happy path, leaving the rewind origin, the single-cursor latch and its release, the stream-ownership rule, and both argument guards unpinned. Adds 13 direct cases in a new test class. Tests only; no production change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
/agentic_review |
PR Summary by QodoAdd direct tests for SdCardParseSource rewind, latch, and stream ownership
AI Description
Diagram
High-Level Assessment
Files changed (1)
|
Code Review by Qodo🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)
Great, no issues found!Qodo reviewed your code and found no material issues that require reviewTip of the day💡 Did you know, you can switch off images and animations for a plain-text comment |
|
Qodo-clean, CI green — ready for review. Independently re-verified on head
Tests only; no production file is touched, so there is no device behaviour to bench. Not merged. |
Produced by the coverage-gap maintenance routine. It adds test cases only — no production file is touched — so it cannot change device behaviour.
What was wrong
SdCardParseSourceis the small class that lets an SD card log session stay lazy. When you parse a downloaded log, the parser reads a short prefix to work out the device configuration and then hands you a session whose samples are produced by re-opening the log from the start every time you enumerate them. That is what keeps a multi-megabyte download at one read buffer of resident memory instead of the whole file, and making "from the start" mean the right thing is entirely this class's job.It had no tests of its own. The existing parser fixtures reach it only along the happy path — a
MemoryStreamsitting at position zero, enumerated exactly once, never re-opened while a read is already in flight. Everything that only matters when something is unusual was therefore unpinned, and each of those could break silently:Position = 0would have looked correct in every existing test;-1) until it is first opened, so a progress bar does not read a not-yet-opened log as an empty one;How it was fixed
A new
SdCardParseSourceTestsclass with 13 direct cases, one per behaviour above plus the two null guards, the forward-only-stream rejection (which returnsnullrather than throwing, because the caller has a fallback), and the failed-rewind path — a stream that claims it can seek and then refuses must leave the latch off, or the source is bricked and every later read reports "already being read" for a read that never started.Every case was verified to be able to fail. Eight mutation rounds were applied to
SdCardParseSource.csfrom a pristine copy, and the union of what they killed is all 13 cases:ArgumentNullException.ThrowIfNullcalls0instead of the stream's positionInterlocked.CompareExchangelatch and the_disposedidempotence guardownsStreamon both lease constructionstry/catchthat unlatches on a failed rewind; accept a non-seekable stream; stop recording the file's lengthLength - Positionas the total instead ofLengthStream.NullThe production file was restored from the pristine copy afterwards and
git statusshows only the new test file.Two things a reviewer may want to push back on:
Open_WhileALeaseOverACallerStreamIsOutstanding_Throwsasserts on a fragment of the exception message ("already being read"), not just the type. That matches existing convention in this suite, and here the type alone is genuinely weak —InvalidOperationExceptionis what a misused stream throws for several unrelated reasons.DisposeAsync_CalledTwice_DoesNotReleaseALeaseTakenInBetweenlooks contrived until you notice that an async iterator can be disposed by both its ownfinallyand an outerawait using. Without the idempotence guard, that stale dispose silently unlatches the live read and the corruption the latch exists to prevent happens anyway.Verification
dotnet buildclean, 0 warnings. Full solution suite green on net9.0 and net10.0. Bench validation does not apply — this is a test-only change with no device interaction.Not merging — for review.