From a4ccdd978acfce10103e1495541dd398234fbe45 Mon Sep 17 00:00:00 2001 From: Fabrizio Demaria Date: Fri, 26 Apr 2024 19:04:11 +0200 Subject: [PATCH] remove sleep from tests --- .../ConfidenceFeatureProviderTest.swift | 64 +++++++++++++------ 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/Tests/ConfidenceProviderTests/ConfidenceFeatureProviderTest.swift b/Tests/ConfidenceProviderTests/ConfidenceFeatureProviderTest.swift index 7fdf0a58..67a53064 100644 --- a/Tests/ConfidenceProviderTests/ConfidenceFeatureProviderTest.swift +++ b/Tests/ConfidenceProviderTests/ConfidenceFeatureProviderTest.swift @@ -26,40 +26,66 @@ class ConfidenceFeatureProviderTest: XCTestCase { } func testSlowFirstResolveWillbeCancelledOnSecondResolve() async throws { - class FakeClient: ConfidenceResolveClient { + let expectation1 = expectation(description: "First resolve completed") + let expectation2 = expectation(description: "Unlock second resolve") + let expectation3 = expectation(description: "Third resolve completed") + + class FakeClient: XCTestCase, ConfidenceResolveClient { var callCount = 0 - var returnCount = 0 var resolveContexts: [ConfidenceStruct] = [] + let expectation1: XCTestExpectation + let expectation2: XCTestExpectation + let expectation3: XCTestExpectation + + init(expectation1: XCTestExpectation, expectation2: XCTestExpectation, expectation3: XCTestExpectation) { + self.expectation1 = expectation1 + self.expectation2 = expectation2 + self.expectation3 = expectation3 + super.init(invocation: nil) // Workaround to use expectations in FakeClient + } func resolve(ctx: ConfidenceStruct) async throws -> ResolvesResult { callCount += 1 - if callCount == 1 { - try await Task.sleep(nanoseconds: UInt64(1 * Double(NSEC_PER_MSEC))) - returnCount += 1 - } else { - returnCount += 1 + switch callCount { + case 1: + expectation1.fulfill() + if Task.isCancelled { + return .init(resolvedValues: [], resolveToken: "") + } + case 2: + await fulfillment(of: [expectation2], timeout: 5.0) + if Task.isCancelled { + return .init(resolvedValues: [], resolveToken: "") + } + XCTFail("This task should be cancelled and never reach here") + case 3: + expectation3.fulfill() + if Task.isCancelled { + return .init(resolvedValues: [], resolveToken: "") + } + default: XCTFail("We expect only 3 resolve calls") } - resolveContexts.append(ctx) return .init(resolvedValues: [], resolveToken: "") } } let confidence = Confidence.Builder.init(clientSecret: "").build() - let client = FakeClient() + let client = FakeClient( + expectation1: expectation1, + expectation2: expectation2, + expectation3: expectation3 + ) let provider = ConfidenceFeatureProvider(confidence: confidence, session: nil, client: client) - let initialContext = MutableContext(targetingKey: "user1") - .add(key: "hello", value: Value.string("world")) - provider.initialize(initialContext: initialContext) - try await Task.sleep(nanoseconds: UInt64(2 * Double(NSEC_PER_MSEC))) - client.callCount = 0 - client.returnCount = 0 + // Initialize allows to start listening for context changes in "confidence" + provider.initialize(initialContext: MutableContext(targetingKey: "user1")) + // Let the internal "resolve" finish + await fulfillment(of: [expectation1], timeout: 5.0) confidence.putContext(key: "new", value: ConfidenceValue(string: "value")) confidence.putContext(key: "new2", value: ConfidenceValue(string: "value2")) - try await Task.sleep(nanoseconds: UInt64(2 * Double(NSEC_PER_MSEC))) - XCTAssertEqual(2, client.callCount) - XCTAssertEqual(1, client.returnCount) - XCTAssertEqual(confidence.getContext()["new2"], ConfidenceValue.init(string: "value2")) + await fulfillment(of: [expectation3], timeout: 5.0) + expectation2.fulfill() // Allow second resolve to continue, regardless if cancelled or not + XCTAssertEqual(3, client.callCount) XCTAssertEqual(2, client.resolveContexts.count) XCTAssertEqual(confidence.getContext(), client.resolveContexts[1]) }