Skip to content

Commit

Permalink
StoreKitConfigTestCase: improved waitForStoreKitTestIfNeeded
Browse files Browse the repository at this point in the history
I did this in hopes that it would work around `FB11799675`, but alas it didn't. I still think it's a useful refactor.

- Combined `hasWaited` and `waitLock` into a single `Atomic`
- Replaced `Thread.sleep` with `Task.sleep` to avoid blocking the thread. This way if `StoreKitTestSession` needs to do anything on the main thread, it can since it's no longer blocked.
- Moved call to `waitForStoreKitTestIfNeeded` _before_ finishing transactions. I did this in hopes that by the time we call that method, these transactions are gone.
  • Loading branch information
NachoSoto committed Jun 9, 2023
1 parent 4187316 commit fbfe9e9
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 15 deletions.
11 changes: 11 additions & 0 deletions Sources/Misc/Concurrency/Atomic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ import Foundation
* $0.bar = 2
* $0.x = "new X"
* }
*
* // write value and get previous value
* let oldValue = foo.getAndSet(newValue)
* ```
*
* Or for single-line read/writes:
Expand Down Expand Up @@ -65,6 +68,14 @@ internal final class Atomic<T> {
}
}

@discardableResult
func getAndSet(_ newValue: T) -> T {
return self.modify { currentValue in
defer { currentValue = newValue }
return currentValue
}
}

@discardableResult
func withValue<Result>(_ action: (T) throws -> Result) rethrows -> Result {
return try lock.perform {
Expand Down
24 changes: 9 additions & 15 deletions Tests/StoreKitUnitTests/StoreKitConfigTestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,10 @@ class StoreKitConfigTestCase: TestCase {
return .seconds(Int(Self.requestTimeout))
}

private static var hasWaited = false
private static let waitLock = Lock()
private static let waitTimeInSeconds: Double? = {
private static let hasWaited: Atomic<Bool> = false
private static let waitTimeInSeconds: TimeInterval? = {
ProcessInfo.processInfo.environment["CIRCLECI_STOREKIT_TESTS_DELAY_SECONDS"]
.flatMap(Double.init)
.flatMap(TimeInterval.init)
}()

var testSession: SKTestSession!
Expand All @@ -47,12 +46,12 @@ class StoreKitConfigTestCase: TestCase {
self.testSession.disableDialogs = true
self.testSession.clearTransactions()

await self.waitForStoreKitTestIfNeeded()

if #available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *) {
await self.finishAllUnfinishedTransactions()
}

self.waitForStoreKitTestIfNeeded()

let suiteName = "StoreKitConfigTests"
self.userDefaults = UserDefaults(suiteName: suiteName)
self.userDefaults.removePersistentDomain(forName: suiteName)
Expand Down Expand Up @@ -89,21 +88,16 @@ class StoreKitConfigTestCase: TestCase {
@available(iOS 14.0, tvOS 14.0, macOS 11.0, watchOS 7.0, *)
private extension StoreKitConfigTestCase {

func waitForStoreKitTestIfNeeded() {
func waitForStoreKitTestIfNeeded() async {
// StoreKitTest seems to take a few seconds to initialize, and running tests before that
// might result in failure. So we give it a few seconds to load before testing.

guard let waitTime = Self.waitTimeInSeconds else { return }
guard !Self.hasWaited.getAndSet(true) else { return }

Self.waitLock.perform {
if !Self.hasWaited {
Logger.warn("Delaying tests for \(waitTime) seconds for StoreKit initialization...")

Thread.sleep(forTimeInterval: waitTime)
Logger.warn("Delaying tests for \(waitTime) seconds for StoreKit initialization...")

Self.hasWaited = true
}
}
try? await Task.sleep(nanoseconds: DispatchTimeInterval(waitTime).nanoseconds)
}

func clearReceiptIfExists() {
Expand Down
8 changes: 8 additions & 0 deletions Tests/UnitTests/Misc/AtomicTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ class AtomicTests: TestCase {
expect(result) == false
}

func testGetAndSet() {
let atomic = Atomic(false)
let oldValue = atomic.getAndSet(true)

expect(oldValue) == false
expect(atomic.value) == true
}

func testWithValue() {
let atomic = Atomic(10)
let result: Int = atomic.withValue { $0 + 10 }
Expand Down

0 comments on commit fbfe9e9

Please sign in to comment.