Both cancellation checks in hashWorker in scan.go now each have a test that fails every time the check is removed. scan.go is unchanged.
TestHashWorkerDropsQueuedRuns now passes hashWorker a hash function that records being called before it calls hashSignature. A worker that hashes a queued run after the scan is cancelled is caught whether or not it then sends a result. Before, the test only noticed a result being sent, which a worker without the check did only some of the time.
TestHashWorkerAbandonsBlockedSend is new. Its hash function cancels the scan before calling hashSignature. The result channel is unbuffered and never read, and the job channel stays open, so the worker can only return through the cancellation case beside its send. It mirrors TestSendEventAbandonsBlockedSend for the walk.
What a reader might trip over: the scan-level tests (TestScanHashWriteFailureUnwindsPool and others) cannot guard the send case, because stop() drains results and so frees a parked worker anyway. That is why the new test drives hashWorker directly. The comment on the drop test that described both gaps is removed, since neither gap remains.
Model: opus-5-5
Both cancellation checks in `hashWorker` in `scan.go` now each have a test that fails every time the check is removed. `scan.go` is unchanged.
- `TestHashWorkerDropsQueuedRuns` now passes `hashWorker` a hash function that records being called before it calls `hashSignature`. A worker that hashes a queued run after the scan is cancelled is caught whether or not it then sends a result. Before, the test only noticed a result being sent, which a worker without the check did only some of the time.
- `TestHashWorkerAbandonsBlockedSend` is new. Its hash function cancels the scan before calling `hashSignature`. The result channel is unbuffered and never read, and the job channel stays open, so the worker can only return through the cancellation case beside its send. It mirrors `TestSendEventAbandonsBlockedSend` for the walk.
What a reader might trip over: the scan-level tests (`TestScanHashWriteFailureUnwindsPool` and others) cannot guard the send case, because `stop()` drains results and so frees a parked worker anyway. That is why the new test drives `hashWorker` directly. The comment on the drop test that described both gaps is removed, since neither gap remains.
Model: opus-5-5
TestHashWorkerDropsQueuedRuns now passes hashWorker a hash function
that records being called, so a worker that hashes a run after the
scan is cancelled fails the test every time instead of only when it
then chose to send its result.
TestHashWorkerAbandonsBlockedSend cancels the scan from inside the
hash function and leaves the result channel unread, so the worker can
only return through the cancellation case beside its send. The scan
tests could not show this, because stop drains results and frees a
parked worker anyway.
Model: opus-5-5
TODO.md: both this PR and #55 added an entry at the top of Completed Steps. Kept both, this PR's entry first, then the #55 entry. No other file changed in the rebase.
Model: opus-5-5
Rebased onto current `next`. One file conflicted:
- `TODO.md`: both this PR and https://git.eeqj.de/sneak/sfdupes/issues/55 added an entry at the top of Completed Steps. Kept both, this PR's entry first, then the https://git.eeqj.de/sneak/sfdupes/issues/55 entry. No other file changed in the rebase.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Both cancellation checks in
hashWorkerinscan.gonow each have a test that fails every time the check is removed.scan.gois unchanged.TestHashWorkerDropsQueuedRunsnow passeshashWorkera hash function that records being called before it callshashSignature. A worker that hashes a queued run after the scan is cancelled is caught whether or not it then sends a result. Before, the test only noticed a result being sent, which a worker without the check did only some of the time.TestHashWorkerAbandonsBlockedSendis new. Its hash function cancels the scan before callinghashSignature. The result channel is unbuffered and never read, and the job channel stays open, so the worker can only return through the cancellation case beside its send. It mirrorsTestSendEventAbandonsBlockedSendfor the walk.What a reader might trip over: the scan-level tests (
TestScanHashWriteFailureUnwindsPooland others) cannot guard the send case, becausestop()drains results and so frees a parked worker anyway. That is why the new test driveshashWorkerdirectly. The comment on the drop test that described both gaps is removed, since neither gap remains.Model: opus-5-5
Review passed; needs a rebase onto
nextonly.Model: opus-5-5
1a847037efto712a82e08bRebased onto current
next. One file conflicted:TODO.md: both this PR and #55 added an entry at the top of Completed Steps. Kept both, this PR's entry first, then the #55 entry. No other file changed in the rebase.Model: opus-5-5