Skip to content

Commit 8b8bdbc

Browse files
committed
Simplify listener attachment syncronisation
1 parent a963b69 commit 8b8bdbc

File tree

1 file changed

+25
-9
lines changed

1 file changed

+25
-9
lines changed

FirebaseRemoteConfig/Tests/Swift/SwiftAPI/AsyncStreamTests.swift

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ class MockRealtime: RCNConfigRealtime, @unchecked Sendable {
3636
/// The listener closure captured from the `updates` async stream.
3737
var listener: ((RemoteConfigUpdate?, Error?) -> Void)?
3838
let mockRegistration = MockListenerRegistration()
39+
var listenerAttachedExpectation: XCTestExpectation?
3940

4041
override func addConfigUpdateListener(_ listener: @escaping (RemoteConfigUpdate?, Error?)
4142
-> Void) -> ConfigUpdateListenerRegistration {
4243
self.listener = listener
44+
listenerAttachedExpectation?.fulfill()
4345
return mockRegistration
4446
}
4547

@@ -101,6 +103,9 @@ class AsyncStreamTests: XCTestCase {
101103
let expectation = self.expectation(description: "Stream should yield an update.")
102104
let keysToUpdate = ["foo", "bar"]
103105

106+
let listenerAttachedExpectation = self.expectation(description: "Listener should be attached.")
107+
mockRealtime.listenerAttachedExpectation = listenerAttachedExpectation
108+
104109
let listeningTask = Task {
105110
for try await update in config.updates {
106111
XCTAssertEqual(update.updatedKeys, Set(keysToUpdate))
@@ -109,8 +114,8 @@ class AsyncStreamTests: XCTestCase {
109114
}
110115
}
111116

112-
// Ensure the listener is attached before sending the update.
113-
try await Task.sleep(nanoseconds: 100_000_000) // 0.1 seconds
117+
// Wait for the listener to be attached before sending the update.
118+
await fulfillment(of: [listenerAttachedExpectation], timeout: 1.0)
114119

115120
mockRealtime.sendUpdate(keys: keysToUpdate)
116121

@@ -122,6 +127,9 @@ class AsyncStreamTests: XCTestCase {
122127
let expectation = self.expectation(description: "Stream should throw an error.")
123128
let testError = TestError()
124129

130+
let listenerAttachedExpectation = self.expectation(description: "Listener should be attached.")
131+
mockRealtime.listenerAttachedExpectation = listenerAttachedExpectation
132+
125133
let listeningTask = Task {
126134
do {
127135
for try await _ in config.updates {
@@ -133,8 +141,8 @@ class AsyncStreamTests: XCTestCase {
133141
}
134142
}
135143

136-
// Ensure the listener is attached before sending the error.
137-
try await Task.sleep(nanoseconds: 100_000_000) // 0.1 seconds
144+
// Wait for the listener to be attached before sending the error.
145+
await fulfillment(of: [listenerAttachedExpectation], timeout: 1.0)
138146

139147
mockRealtime.sendError(testError)
140148

@@ -143,14 +151,17 @@ class AsyncStreamTests: XCTestCase {
143151
}
144152

145153
func testStreamCancellation_callsRemoveOnListener() async throws {
154+
let listenerAttachedExpectation = self.expectation(description: "Listener should be attached.")
155+
mockRealtime.listenerAttachedExpectation = listenerAttachedExpectation
156+
146157
let listeningTask = Task {
147158
for try await _ in config.updates {
148159
// We will cancel the task, so it should not reach here.
149160
}
150161
}
151162

152-
// Ensure the listener has time to be established.
153-
try await Task.sleep(nanoseconds: 100_000_000) // 0.1 seconds
163+
// Wait for the listener to be attached.
164+
await fulfillment(of: [listenerAttachedExpectation], timeout: 1.0)
154165

155166
// Verify the listener has not been removed yet.
156167
XCTAssertFalse(mockRealtime.mockRegistration.wasRemoveCalled)
@@ -168,6 +179,9 @@ class AsyncStreamTests: XCTestCase {
168179
func testStreamFinishesGracefully_whenListenerSendsNil() async throws {
169180
let expectation = self.expectation(description: "Stream should finish without error.")
170181

182+
let listenerAttachedExpectation = self.expectation(description: "Listener should be attached.")
183+
mockRealtime.listenerAttachedExpectation = listenerAttachedExpectation
184+
171185
let listeningTask = Task {
172186
var updateCount = 0
173187
do {
@@ -182,7 +196,7 @@ class AsyncStreamTests: XCTestCase {
182196
}
183197
}
184198

185-
try await Task.sleep(nanoseconds: 100_000_000)
199+
await fulfillment(of: [listenerAttachedExpectation], timeout: 1.0)
186200
mockRealtime.sendCompletion()
187201

188202
await fulfillment(of: [expectation], timeout: 1.0)
@@ -199,6 +213,9 @@ class AsyncStreamTests: XCTestCase {
199213
]
200214
var receivedUpdates: [Set<String>] = []
201215

216+
let listenerAttachedExpectation = self.expectation(description: "Listener should be attached.")
217+
mockRealtime.listenerAttachedExpectation = listenerAttachedExpectation
218+
202219
let listeningTask = Task {
203220
for try await update in config.updates {
204221
receivedUpdates.append(update.updatedKeys)
@@ -210,10 +227,9 @@ class AsyncStreamTests: XCTestCase {
210227
return receivedUpdates
211228
}
212229

213-
try await Task.sleep(nanoseconds: 100_000_000)
230+
await fulfillment(of: [listenerAttachedExpectation], timeout: 1.0)
214231

215232
mockRealtime.sendUpdate(keys: Array(updatesToSend[0]))
216-
try await Task.sleep(nanoseconds: 100_000_000) // Brief pause between sends
217233
mockRealtime.sendUpdate(keys: Array(updatesToSend[1]))
218234

219235
await fulfillment(of: [expectation], timeout: 2.0)

0 commit comments

Comments
 (0)