Skip to content

Fix flaky tests on Windows - #422

Open
bauerpawel wants to merge 1 commit into
Forceu:masterfrom
bauerpawel:fix/windows-flaky-tests
Open

bauerpawel wants to merge 1 commit into
Forceu:masterfrom
bauerpawel:fix/windows-flaky-tests

Conversation

@bauerpawel

Copy link
Copy Markdown
Contributor

Description

Several tests in the suite fail intermittently (and in some cases deterministically) when run on Windows. Root causes:

  • File handles held open across os.Remove: generateHashAndEncrypt (internal/storage/FileServing.go) and getDaysRemaining (internal/webserver/ssl/Ssl.go) didn't close a file handle before removing/rewriting that same file. On Linux this is a no-op; on Windows an open handle blocks the remove/rewrite, so the test either errors out or silently keeps stale data. Aws_test.go had the same pattern.
  • chmod-based permission tests: TestGetFileByChunkId (internal/storage/chunking/Chunking_test.go) used os.Chmod to make a file read-only and assert a failing removal - POSIX permission bits are a no-op on Windows, so the assertion never held. Guarded with runtime.GOOS != "windows".
  • Hardcoded /-separated path assertions: Localstorage_test.go asserted exact path strings using /, which don't match filepath-joined paths on Windows (\). Switched to os.PathSeparator.
  • Wildcard vs. specific address bind conflict: TestIsErrorAddressAlreadyInUse (Setup_test.go) bound a test listener to 127.0.0.1:PORT but the second server to :PORT (wildcard). On Windows, binding to the wildcard address doesn't reliably conflict with an existing listener bound to a specific address on the same port, so the intended "address already in use" error never surfaced. Now both bind to the same specific address.
  • testing/synctest vs. real I/O contention: TestParallelDownloads used testing/synctest's deterministic fake clock around 50 goroutines doing real SQLite writes. The fake clock has no way to gracefully coexist with unpredictable real-world I/O delays (e.g. antivirus briefly locking the database file) - a single external stall can look like a livelock, since retries governed by the fake clock spin far faster than the real delay actually resolves. Replaced with a plain sync.WaitGroup.

None of these are behavior changes to production code paths except the two file-handle fixes, which are strictly more correct (closing a handle before removing/rewriting the same file) on every platform.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Technical Details

  • Database changes: No
  • Storage backend affected: No
  • Usage of AI: Yes — developed with Claude Code as a pair-programming assistant, including root-causing the synctest livelock (confirmed via goroutine dumps that the original, unmodified code also hung, ruling out a regression). I reviewed and tested all changes before submitting.

How Has This Been Tested?

  • Unit Tests: go test ./... --tags=test,awsmock (full suite passes, 15+ repeated runs of the previously-hanging TestParallelDownloads)
  • Environment: Windows 11

Checklist

  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas. (added a comment explaining the synctestWaitGroup rationale, since it's non-obvious)
  • I have made corresponding changes to the documentation. (n/a - no behavior/doc change)
  • My changes generate no new warnings.

🤖 Generated with Claude Code

Several tests failed intermittently on Windows: os.Remove on a file that
still had an open handle, chmod-based permission tests that are no-ops on
Windows, hardcoded "/"-separated path assertions, a wildcard-vs-specific
address bind conflict, and testing/synctest's deterministic fake clock
livelocking against real SQLite I/O contention under TestParallelDownloads
(replaced with a plain sync.WaitGroup).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019woTYJGrS4pfPWC6CCgffQ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant