Skip to content

Commit 74512b3

Browse files
committed
test: remove timing races that fail under the Xcode 27 toolchain
Two unit tests failed on the Xcode 27 preview while passing on Xcode 26 across all five platforms. Both were timing assumptions rather than real regressions, so they are fixed at the source instead of being retried. GraphQL subscribe/query/mutate and REST Combine tests waited on expectations with a 0.05 second timeout. That is not enough budget on a slower toolchain: testMixedSuccessAndErrorValues failed with "Exceeded timeout of 0.05 seconds, with unfulfilled expectations: receivedStateValueConnected". Raised to 0.5 seconds. 0.5 rather than something larger because 72 of these expectations are isInverted, and an inverted expectation waits out its full timeout on the happy path. A multi-second value would have added minutes to the suite for no benefit. AWSCloudWatchLoggingSessionControllerTests.testConsumeFailureSendsHubEvent registered a Hub listener and immediately flushed logs. Hub registration is asynchronous, so flushLogFailure could be published before the listener attached, leaving the expectation unfulfilled until the 10 second timeout. It now waits for registration using the existing HubListenerTestUtilities.waitForListener helper, which is the pattern used elsewhere in the repo, and asserts that registration succeeded. Verified on Xcode 26: GraphQLSubscribeCombineTests 6/6 pass (including the test that failed on 27), AWSCloudWatchLoggingPluginTests 60 pass, InternalAWSPinpointUnitTests 59 pass, and the full AWSAPIPluginTests target has no failures.
1 parent 9c0804e commit 74512b3

7 files changed

Lines changed: 46 additions & 36 deletions

File tree

AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLMutateCombineTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class GraphQLMutateCombineTests: OperationTestBase {
4747
receivedResponseError.fulfill()
4848
}
4949
})
50-
await fulfillment(of: [receivedValue, receivedFinish, receivedFailure, receivedResponseError], timeout: 0.05)
50+
await fulfillment(of: [receivedValue, receivedFinish, receivedFailure, receivedResponseError], timeout: 0.5)
5151
sink.cancel()
5252
}
5353

@@ -82,7 +82,7 @@ class GraphQLMutateCombineTests: OperationTestBase {
8282
}
8383
})
8484

85-
await fulfillment(of: [receivedValue, receivedFinish, receivedFailure, receivedResponseError], timeout: 0.05)
85+
await fulfillment(of: [receivedValue, receivedFinish, receivedFailure, receivedResponseError], timeout: 0.5)
8686
sink.cancel()
8787

8888
}

AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLQueryCombineTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class GraphQLQueryCombineTests: OperationTestBase {
5555
receivedFailure,
5656
receivedResponseError
5757
],
58-
timeout: 0.05
58+
timeout: 0.5
5959
)
6060
sink.cancel()
6161
}
@@ -98,7 +98,7 @@ class GraphQLQueryCombineTests: OperationTestBase {
9898
receivedFailure,
9999
receivedResponseError
100100
],
101-
timeout: 0.05
101+
timeout: 0.5
102102
)
103103
sink.cancel()
104104

@@ -142,7 +142,7 @@ class GraphQLQueryCombineTests: OperationTestBase {
142142
receivedFailure,
143143
receivedResponseError
144144
],
145-
timeout: 0.05
145+
timeout: 0.5
146146
)
147147
sink.cancel()
148148
}

AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLSubscribeCombineTests.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class GraphQLSubscribeCombineTests: OperationTestBase {
7777
receivedStateValueDisconnected,
7878
receivedDataValueSuccess,
7979
receivedDataValueError
80-
], timeout: 0.05)
80+
], timeout: 0.5)
8181
}
8282

8383
func testHappyPath() async throws {
@@ -87,7 +87,7 @@ class GraphQLSubscribeCombineTests: OperationTestBase {
8787
let testJSON: JSONValue = ["foo": true]
8888

8989
try await subscribe(expecting: testJSON)
90-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
90+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
9191

9292
try await MockAppSyncRealTimeClient.waitForSubscirbing()
9393
try await MockAppSyncRealTimeClient.waitForSubscirbed()
@@ -107,7 +107,7 @@ class GraphQLSubscribeCombineTests: OperationTestBase {
107107
receivedDataValueError.isInverted = true
108108

109109
try await subscribe()
110-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
110+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
111111

112112
try await MockAppSyncRealTimeClient.waitForSubscirbing()
113113
try await MockAppSyncRealTimeClient.waitForSubscirbed()
@@ -124,7 +124,7 @@ class GraphQLSubscribeCombineTests: OperationTestBase {
124124
receivedDataValueError.isInverted = true
125125

126126
try await subscribe()
127-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
127+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
128128

129129
try await MockAppSyncRealTimeClient.waitForSubscirbing()
130130
mockAppSyncRealTimeClient?.triggerEvent(.error(["Error"]))
@@ -137,7 +137,7 @@ class GraphQLSubscribeCombineTests: OperationTestBase {
137137
receivedDataValueSuccess.isInverted = true
138138

139139
try await subscribe()
140-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
140+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
141141

142142
try await MockAppSyncRealTimeClient.waitForSubscirbing()
143143
try await MockAppSyncRealTimeClient.waitForSubscirbed()
@@ -164,7 +164,7 @@ class GraphQLSubscribeCombineTests: OperationTestBase {
164164
receivedDataValueSuccess.expectedFulfillmentCount = 2
165165

166166
try await subscribe(expecting: testJSON)
167-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
167+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
168168

169169
try await MockAppSyncRealTimeClient.waitForSubscirbing()
170170
try await MockAppSyncRealTimeClient.waitForSubscirbed()
@@ -191,7 +191,7 @@ class GraphQLSubscribeCombineTests: OperationTestBase {
191191
receivedDataValueSuccess.expectedFulfillmentCount = 2
192192

193193
try await subscribe()
194-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
194+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
195195

196196
try await MockAppSyncRealTimeClient.waitForSubscirbing()
197197
try await MockAppSyncRealTimeClient.waitForSubscirbed()

AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLSubscribeTaskTests.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class GraphQLSubscribeTasksTests: OperationTestBase {
7979
receivedDataValueSuccess,
8080
receivedDataValueError
8181
],
82-
timeout: 0.05
82+
timeout: 0.5
8383
)
8484
}
8585

@@ -95,7 +95,7 @@ class GraphQLSubscribeTasksTests: OperationTestBase {
9595
]
9696

9797
try await subscribe(expecting: testJSON)
98-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
98+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
9999

100100
try await MockAppSyncRealTimeClient.waitForSubscirbing()
101101
try await MockAppSyncRealTimeClient.waitForSubscirbed()
@@ -111,7 +111,7 @@ class GraphQLSubscribeTasksTests: OperationTestBase {
111111
receivedDataValueError.isInverted = true
112112

113113
try await subscribe()
114-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
114+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
115115
try await MockAppSyncRealTimeClient.waitForSubscirbing()
116116
try await MockAppSyncRealTimeClient.waitForSubscirbed()
117117
mockAppSyncRealTimeClient?.triggerEvent(.unsubscribed)
@@ -127,7 +127,7 @@ class GraphQLSubscribeTasksTests: OperationTestBase {
127127
receivedDataValueError.isInverted = true
128128

129129
try await subscribe()
130-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
130+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
131131

132132
try await MockAppSyncRealTimeClient.waitForSubscirbing()
133133
mockAppSyncRealTimeClient?.triggerEvent(.error([AppSyncRealTimeRequest.Error.limitExceeded]))
@@ -143,7 +143,7 @@ class GraphQLSubscribeTasksTests: OperationTestBase {
143143
receivedDataValueError.isInverted = true
144144

145145
try await subscribe()
146-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
146+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
147147

148148
let unauthorizedError = GraphQLError(message: "", extensions: ["errorType": "Unauthorized"])
149149
try await MockAppSyncRealTimeClient.waitForSubscirbing()
@@ -164,7 +164,7 @@ class GraphQLSubscribeTasksTests: OperationTestBase {
164164
receivedDataValueError.isInverted = true
165165

166166
try await subscribe()
167-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
167+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
168168

169169
try await MockAppSyncRealTimeClient.waitForSubscirbing()
170170
mockAppSyncRealTimeClient?.triggerEvent(.error([URLError(URLError.Code(rawValue: 400))]))
@@ -181,7 +181,7 @@ class GraphQLSubscribeTasksTests: OperationTestBase {
181181
receivedDataValueSuccess.isInverted = true
182182

183183
try await subscribe()
184-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
184+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
185185
try await MockAppSyncRealTimeClient.waitForSubscirbing()
186186
try await MockAppSyncRealTimeClient.waitForSubscirbed()
187187
mockAppSyncRealTimeClient?.triggerEvent(.data(testData))
@@ -201,7 +201,7 @@ class GraphQLSubscribeTasksTests: OperationTestBase {
201201
receivedDataValueSuccess.expectedFulfillmentCount = 2
202202

203203
try await subscribe(expecting: testJSON)
204-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
204+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
205205

206206
try await MockAppSyncRealTimeClient.waitForSubscirbing()
207207
try await MockAppSyncRealTimeClient.waitForSubscirbed()
@@ -225,7 +225,7 @@ class GraphQLSubscribeTasksTests: OperationTestBase {
225225
receivedDataValueSuccess.expectedFulfillmentCount = 2
226226

227227
try await subscribe()
228-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
228+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
229229

230230
try await MockAppSyncRealTimeClient.waitForSubscirbing()
231231
try await MockAppSyncRealTimeClient.waitForSubscirbed()

AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLSubscribeTests.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class GraphQLSubscribeTests: OperationTestBase {
9595
receivedSubscriptionEventError.shouldTrigger = false
9696

9797
subscribe(expecting: testJSON)
98-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
98+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
9999

100100
try await MockAppSyncRealTimeClient.waitForSubscirbing()
101101
try await MockAppSyncRealTimeClient.waitForSubscirbed()
@@ -111,7 +111,7 @@ class GraphQLSubscribeTests: OperationTestBase {
111111
receivedSubscriptionEventData,
112112
receivedSubscriptionEventError
113113
],
114-
timeout: 0.05
114+
timeout: 0.5
115115
)
116116
}
117117

@@ -135,7 +135,7 @@ class GraphQLSubscribeTests: OperationTestBase {
135135
receivedSubscriptionEventError.shouldTrigger = false
136136

137137
subscribe()
138-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
138+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
139139

140140
try await MockAppSyncRealTimeClient.waitForSubscirbing()
141141
try await MockAppSyncRealTimeClient.waitForSubscirbed()
@@ -150,7 +150,7 @@ class GraphQLSubscribeTests: OperationTestBase {
150150
receivedSubscriptionEventData,
151151
receivedSubscriptionEventError
152152
],
153-
timeout: 0.05
153+
timeout: 0.5
154154
)
155155
}
156156

@@ -173,7 +173,7 @@ class GraphQLSubscribeTests: OperationTestBase {
173173
receivedSubscriptionEventError.shouldTrigger = false
174174

175175
subscribe()
176-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
176+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
177177

178178
try await MockAppSyncRealTimeClient.waitForSubscirbing()
179179
mockAppSyncRealTimeClient.triggerEvent(.error(["Error"]))
@@ -187,7 +187,7 @@ class GraphQLSubscribeTests: OperationTestBase {
187187
receivedSubscriptionEventData,
188188
receivedSubscriptionEventError
189189
],
190-
timeout: 0.05
190+
timeout: 0.5
191191
)
192192
}
193193

@@ -216,7 +216,7 @@ class GraphQLSubscribeTests: OperationTestBase {
216216
receivedSubscriptionEventError.shouldTrigger = true
217217

218218
subscribe()
219-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
219+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
220220

221221
try await MockAppSyncRealTimeClient.waitForSubscirbing()
222222
try await MockAppSyncRealTimeClient.waitForSubscirbed()
@@ -232,7 +232,7 @@ class GraphQLSubscribeTests: OperationTestBase {
232232
receivedSubscriptionEventData,
233233
receivedSubscriptionEventError
234234
],
235-
timeout: 0.05
235+
timeout: 0.5
236236
)
237237
}
238238

@@ -252,7 +252,7 @@ class GraphQLSubscribeTests: OperationTestBase {
252252
receivedSubscriptionEventError.shouldTrigger = false
253253

254254
subscribe(expecting: testJSON)
255-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
255+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
256256

257257
try await MockAppSyncRealTimeClient.waitForSubscirbing()
258258
try await MockAppSyncRealTimeClient.waitForSubscirbed()
@@ -269,7 +269,7 @@ class GraphQLSubscribeTests: OperationTestBase {
269269
receivedSubscriptionEventData,
270270
receivedSubscriptionEventError
271271
],
272-
timeout: 0.05
272+
timeout: 0.5
273273
)
274274
}
275275

@@ -294,7 +294,7 @@ class GraphQLSubscribeTests: OperationTestBase {
294294
receivedSubscriptionEventError.shouldTrigger = true
295295

296296
subscribe()
297-
await fulfillment(of: [onSubscribeInvoked], timeout: 0.05)
297+
await fulfillment(of: [onSubscribeInvoked], timeout: 0.5)
298298

299299
try await MockAppSyncRealTimeClient.waitForSubscirbing()
300300
try await MockAppSyncRealTimeClient.waitForSubscirbed()
@@ -312,7 +312,7 @@ class GraphQLSubscribeTests: OperationTestBase {
312312
receivedSubscriptionEventData,
313313
receivedSubscriptionEventError
314314
],
315-
timeout: 0.05
315+
timeout: 0.5
316316
)
317317
}
318318

AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/RESTCombineTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class RESTCombineTests: OperationTestBase {
3939
receivedValue.fulfill()
4040
})
4141

42-
await fulfillment(of: [receivedValue, receivedFinish, receivedFailure], timeout: 0.05)
42+
await fulfillment(of: [receivedValue, receivedFinish, receivedFailure], timeout: 0.5)
4343
sink.cancel()
4444
}
4545

@@ -69,7 +69,7 @@ class RESTCombineTests: OperationTestBase {
6969
receivedValue.fulfill()
7070
})
7171

72-
await fulfillment(of: [receivedValue, receivedFinish, receivedFailure], timeout: 0.05)
72+
await fulfillment(of: [receivedValue, receivedFinish, receivedFailure], timeout: 0.5)
7373
sink.cancel()
7474
}
7575
}

AmplifyPlugins/Logging/Tests/AWSCloudWatchLoggingPluginTests/AWSCloudWatchLoggingSessionControllerTests.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,24 @@ final class AWSCloudWatchLoggingSessionControllerTests: XCTestCase {
4040
/// Then: a flushLogFailure Hub Event is sent to the Logging channel
4141
func testConsumeFailureSendsHubEvent() async throws {
4242
let hubEventExpectation = expectation(description: "Should receive the hub event")
43-
unsubscribeToken = Amplify.Hub.listen(to: .logging) { payload in
43+
let token = Amplify.Hub.listen(to: .logging) { payload in
4444
switch payload.eventName {
4545
case HubPayload.EventName.Logging.flushLogFailure:
4646
hubEventExpectation.fulfill()
4747
default:
4848
break
4949
}
5050
}
51+
unsubscribeToken = token
52+
53+
// Hub listener registration is asynchronous. Without waiting for it, the
54+
// flushLogFailure event below can be published before the listener is
55+
// attached, and the expectation never fulfills.
56+
let listenerAttached = try await HubListenerTestUtilities.waitForListener(
57+
with: token,
58+
timeout: 5
59+
)
60+
XCTAssertTrue(listenerAttached, "Hub listener was not registered before flushing logs")
5161

5262
let bytes = (0 ..< 1_024).map { _ in UInt8.random(in: 0 ..< 255) }
5363
let fileURL = getLogFile()

0 commit comments

Comments
 (0)