Skip to content

Fix flaky metadata-sync & consent-status unit tests#6876

Merged
rickvdl merged 2 commits into
mainfrom
rickvdl/fix-flaky-delegate-attr-tests
Jun 2, 2026
Merged

Fix flaky metadata-sync & consent-status unit tests#6876
rickvdl merged 2 commits into
mainfrom
rickvdl/fix-flaky-delegate-attr-tests

Conversation

@rickvdl

@rickvdl rickvdl commented Jun 1, 2026

Copy link
Copy Markdown
Member

Summary

Fixes a few cases of flaky unit tests:

  • PurchasesDelegateTests.testApplicationDidBecomeActiveSyncsCachedTransactionMetadata / …SyncsMultipleCachedTransactions / …DoesNotPostWhenNoCachedMetadata
  • BackendSubscriberAttributesTests.testPostReceiptCachesRequestsWhenOnlyConsentStatus…Timestamps

Fixes

  1. .configure metadata sync data race; on SDK configuration any locally stored transaction metadata (on disk) is synced (using a fire-and-forget Task{}). In the tests we instantly trigger the didBecomeActive notification, which also triggers a sync. At that point isSyncing is still true (sometimes), since the background Task hasn’t finished yet, causing the sync triggered by the foreground notification to get skipped. We’re now observing the isSyncing in the test in order to wait for the initial sync before testing our triggered sync.

  2. Some tests (e.g. testPostReceiptCachesRequestsWhenOnlyConsentStatusTimestampDiffers) concurrently call POST /receipt that use the MockDateProvider to increment the currentIndex. However this was done in a non-atomicway, causing data races. Fixed by making the index useAtomic`

Validation

Failing run (17/20 failed) link

Successful run after fix (20/20 succeeded) link


Note

Low Risk
Changes are limited to test harness timing, mock thread-safety, and internal visibility of a sync flag; no purchase or networking logic changes.

Overview
Stabilizes flaky unit tests around cached transaction metadata sync and concurrent receipt posting without changing product behavior.

Metadata sync tests now wait for the configure-time metadata sync to finish (isSyncing cleared and the local store read at least once) before firing applicationDidBecomeActive, so foreground-triggered sync is not skipped by the in-progress guard. The empty-cache case waits for a second store read instead of a fixed sleep.

MockDateProvider advances its stubbed date index with Atomic so parallel post(receipt:) tests do not race on now().

TransactionMetadataSyncHelper.isSyncing is exposed (no longer private) so tests can observe sync completion; the test base holds a reference to the same helper instance used by Purchases.

Reviewed by Cursor Bugbot for commit ef10830. Bugbot is set up for automated code reviews on this repo. Configure here.

@rickvdl rickvdl force-pushed the rickvdl/fix-flaky-delegate-attr-tests branch from 4075f21 to 5e7132a Compare June 2, 2026 06:07
@rickvdl rickvdl changed the title Fix flaky PurchasesDelegate & BackendSubscriberAttributes unit tests Fix flaky metadata-sync & consent-status unit tests Jun 2, 2026
@rickvdl

rickvdl commented Jun 2, 2026

Copy link
Copy Markdown
Member Author

@RCGitBot please test

@rickvdl rickvdl force-pushed the rickvdl/fix-flaky-delegate-attr-tests branch from 5e7132a to e584d5a Compare June 2, 2026 06:13
@rickvdl

rickvdl commented Jun 2, 2026

Copy link
Copy Markdown
Member Author

@RCGitBot please test

@rickvdl rickvdl force-pushed the rickvdl/fix-flaky-delegate-attr-tests branch from b2cd340 to b628db9 Compare June 2, 2026 09:55
@rickvdl rickvdl force-pushed the rickvdl/fix-flaky-delegate-attr-tests branch from b628db9 to ef10830 Compare June 2, 2026 09:57
@rickvdl

rickvdl commented Jun 2, 2026

Copy link
Copy Markdown
Member Author

@RCGitBot please test

@rickvdl rickvdl marked this pull request as ready for review June 2, 2026 09:58
@rickvdl rickvdl requested a review from a team as a code owner June 2, 2026 09:58

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ef10830. Configure here.

private let transactionPoster: TransactionPosterType

private let isSyncing: Atomic<Bool> = .init(false)
let isSyncing: Atomic<Bool> = .init(false)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Production isSyncing visibility widened solely for tests

Low Severity

The isSyncing property on TransactionMetadataSyncHelper was changed from private to internal access purely so a test can observe it (PurchasesDelegateTests.waitForInitialMetadataSyncToComplete). External access only occurs in tests, meaning this is a test-only visibility change in production code that ships in release builds without a #if DEBUG guard. This violates the rule requiring test-only hooks in production code to be wrapped in #if DEBUG.

Fix in Cursor Fix in Web

Triggered by learned rule: Test-only hooks in production code must be wrapped in #if DEBUG

Reviewed by Cursor Bugbot for commit ef10830. Configure here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Technically true, but I'm not sure if it's worth it. We have a bunch of precedents for this

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Alternatively we could do something like this

private let isSyncing: Atomic<Bool> = .init(false)   // back to private

// in a `// MARK: - Exposed for testing only`-style accessor:
var isCurrentlySyncing: Bool { self.isSyncing.value }   // read-only

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Right. I think this is fine

@ajpallares ajpallares left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the fix!

private let transactionPoster: TransactionPosterType

private let isSyncing: Atomic<Bool> = .init(false)
let isSyncing: Atomic<Bool> = .init(false)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Right. I think this is fine

@rickvdl rickvdl merged commit e3b2b8c into main Jun 2, 2026
43 checks passed
@rickvdl rickvdl deleted the rickvdl/fix-flaky-delegate-attr-tests branch June 2, 2026 12:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants