test(export): add multithread safety tests for system and disk driver#4409
Conversation
Signed-off-by: RUPESHKUMARPALLAI <rkp13@iitbbs.ac.in>
8c36408 to
60c40e3
Compare
Codecov Report✅ All modified and coverable lines are covered by tests.
Additional details and impacted files@@ Coverage Diff @@
## master #4409 +/- ##
===========================================
- Coverage 54.49% 43.96% -10.54%
===========================================
Files 134 282 +148
Lines 12329 20522 +8193
===========================================
+ Hits 6719 9022 +2303
- Misses 5116 10733 +5617
- Partials 494 767 +273
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
JaydipGabani
left a comment
There was a problem hiding this comment.
Thanks for picking this up.
There was a problem hiding this comment.
Add a test that exercises Writer.CloseConnection concurrently with Writer.retryFailedConnections through the actual Writer
There was a problem hiding this comment.
TestCloseConnectionConcurrentWithRetry added
| type concurrentTestDriver struct { | ||
| mu sync.Mutex | ||
| publishCalls int | ||
| createCalls int | ||
| updateCalls int | ||
| closeCalls int | ||
| failPublish bool | ||
| failCreate bool | ||
| failUpdate bool | ||
| failClose bool | ||
| } |
There was a problem hiding this comment.
Unused Counter Fields and Failure Flags
type concurrentTestDriver struct {
mu sync.Mutex
publishCalls int // incremented but NEVER read/asserted
createCalls int // incremented but NEVER read/asserted
updateCalls int // incremented but NEVER read/asserted
closeCalls int // incremented but NEVER read/asserted
failPublish bool // NEVER set to true
failCreate bool // NEVER set to true
failUpdate bool // NEVER set to true
failClose bool // NEVER set to true
}
Either:
- Assert the counters after wg.Wait() (e.g., assert.Greater(t, testDrv.createCalls, 0)) to verify work actually happened
- Enable failure flags in a second subtest to exercise error-path concurrency
- Remove them if they're not needed — dead instrumentation suggests the test is incomplete
There was a problem hiding this comment.
Removed not needed flags
| return nil | ||
| } | ||
|
|
||
| func TestSystem_ConcurrentAccess(t *testing.T) { |
There was a problem hiding this comment.
assert testDrv.publishCalls > 0 after the test to confirm at least some publishers reached the driver. Or track success/failure counts separately
| }() | ||
| } | ||
|
|
||
| wg.Wait() |
There was a problem hiding this comment.
The assertions RetryCount > 0 and NextRetryAt.After(now) pass because goroutine 1 already set them. A single-call test produces identical results. This test doesn't exercise concurrency at all.
What actually happens at runtime:
| Step | What runs | Effect |
|---|---|---|
| Goroutine 1 acquires lock | Retries all 5 connections; all fail. Sets RetryCount=1, NextRetryAt = now + ~30s | Real work done |
| Goroutine 2 acquires lock | Finds now.Before(failedConn.NextRetryAt) → true for all 5 → skips all | No-op |
| Goroutines 3–8 | Same as goroutine 2 | All no-ops |
There was a problem hiding this comment.
updated to simulate through actual writer
… resolve comments Signed-off-by: RUPESHKUMARPALLAI <rkp13@iitbbs.ac.in>
|
Here is the fix - #4422 for data races surfaced by this PR in the CI. |
| } | ||
|
|
||
| wg.Wait() | ||
|
|
There was a problem hiding this comment.
Because closeAndRemoveFilesWithRetry is forced to fail, CloseConnection will start backgroundCleanup() via cleanupOnce.Do(...). The test never stops that goroutine (e.g., by closing cleanupDone / marking cleanupStopped), which can leak goroutines across the package test run and introduce nondeterminism if the ticker fires. Consider explicitly stopping background cleanup during test teardown.
| // Ensure background cleanup goroutine is stopped to avoid leaking | |
| // goroutines across tests when CloseConnection starts backgroundCleanup. | |
| cleanupStopped = true |
| // Ensure at least one publish reached the driver so we know publishers | ||
| // were able to observe a usable connection during concurrent access. | ||
| testDrv.mu.Lock() | ||
| publishCount := testDrv.publishCalls | ||
| testDrv.mu.Unlock() | ||
| if publishCount == 0 { | ||
| t.Fatalf("expected at least one successful Publish call, got %d", publishCount) | ||
| } |
There was a problem hiding this comment.
publishCount == 0 can be a flaky failure because publishers may all run before any UpsertConnection has installed the mapping (or only during windows when CloseConnection has removed it). Consider creating the connection once before starting publishers/closers, or use a start barrier/retry loop with a short timeout so at least one publish is guaranteed to observe an initialized connection.
|
This PR has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
What this PR does / why we need it:
Which issue(s) this PR fixes (optional, using
fixes #<issue number>(, fixes #<issue_number>, ...)format, will close the issue(s) when the PR gets merged):Fixes #4024
Special notes for your reviewer: