Skip to content

test(export): add multithread safety tests for system and disk driver#4409

Open
RUPESHKUMARPALLAI wants to merge 3 commits into
open-policy-agent:masterfrom
RUPESHKUMARPALLAI:add-multithread-export-tests-4024
Open

test(export): add multithread safety tests for system and disk driver#4409
RUPESHKUMARPALLAI wants to merge 3 commits into
open-policy-agent:masterfrom
RUPESHKUMARPALLAI:add-multithread-export-tests-4024

Conversation

@RUPESHKUMARPALLAI

@RUPESHKUMARPALLAI RUPESHKUMARPALLAI commented Feb 26, 2026

Copy link
Copy Markdown

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:

@RUPESHKUMARPALLAI RUPESHKUMARPALLAI requested a review from a team as a code owner February 26, 2026 14:35
Copilot AI review requested due to automatic review settings February 26, 2026 14:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Signed-off-by: RUPESHKUMARPALLAI <rkp13@iitbbs.ac.in>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 43.96%. Comparing base (3350319) to head (60c40e3).
⚠️ Report is 610 commits behind head on master.

❗ There is a different number of reports uploaded between BASE (3350319) and HEAD (60c40e3). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (3350319) HEAD (60c40e3)
unittests 2 1
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     
Flag Coverage Δ
unittests 43.96% <ø> (-10.54%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JaydipGabani JaydipGabani left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for picking this up.

Comment thread pkg/export/system_test.go

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test that exercises Writer.CloseConnection concurrently with Writer.retryFailedConnections through the actual Writer

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TestCloseConnectionConcurrentWithRetry added

Comment thread pkg/export/system_test.go
Comment on lines +310 to +320
type concurrentTestDriver struct {
mu sync.Mutex
publishCalls int
createCalls int
updateCalls int
closeCalls int
failPublish bool
failCreate bool
failUpdate bool
failClose bool
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed not needed flags

Comment thread pkg/export/system_test.go
return nil
}

func TestSystem_ConcurrentAccess(t *testing.T) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert testDrv.publishCalls > 0 after the test to confirm at least some publishers reached the driver. Or track success/failure counts separately

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}()
}

wg.Wait()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated to simulate through actual writer

… resolve comments

Signed-off-by: RUPESHKUMARPALLAI <rkp13@iitbbs.ac.in>
@JaydipGabani

Copy link
Copy Markdown
Contributor

Here is the fix - #4422 for data races surfaced by this PR in the CI.

Copilot AI review requested due to automatic review settings March 4, 2026 19:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

Comment thread pkg/export/disk/disk_test.go
}

wg.Wait()

Copilot AI Mar 4, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
// Ensure background cleanup goroutine is stopped to avoid leaking
// goroutines across tests when CloseConnection starts backgroundCleanup.
cleanupStopped = true

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RUPESHKUMARPALLAI can you address this?

Comment thread pkg/export/system_test.go
Comment on lines +407 to +414
// 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)
}

Copilot AI Mar 4, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RUPESHKUMARPALLAI can you address this?

@github-actions

Copy link
Copy Markdown
Contributor

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.

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.

Add tests for multi thread safety

4 participants