Skip to content

Commit b71cfdc

Browse files
author
Michael Lehenbauer
committed
Add priming logic to integration tests to avoid backend cold start issues.
Port of firebase/firebase-js-sdk#1259 except I didn't use EventAccumulator since it hits the default timeout. I just manually do the listener.
1 parent 3ec5075 commit b71cfdc

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@
2222
#import <FirebaseFirestore/FIRDocumentChange.h>
2323
#import <FirebaseFirestore/FIRDocumentReference.h>
2424
#import <FirebaseFirestore/FIRDocumentSnapshot.h>
25+
#import <FirebaseFirestore/FIRFirestore.h>
2526
#import <FirebaseFirestore/FIRFirestoreSettings.h>
2627
#import <FirebaseFirestore/FIRQuerySnapshot.h>
2728
#import <FirebaseFirestore/FIRSnapshotMetadata.h>
29+
#import <FirebaseFirestore/FIRTransaction.h>
2830
#import <GRPCClient/GRPCCall+ChannelArg.h>
2931
#import <GRPCClient/GRPCCall+Tests.h>
3032

@@ -61,6 +63,12 @@
6163

6264
NS_ASSUME_NONNULL_BEGIN
6365

66+
/**
67+
* Firestore databases can be subject to a ~30s "cold start" delay if they have not been used
68+
* recently, so before any tests run we "prime" the backend.
69+
*/
70+
static const double kPrimingTimeout = 45.0;
71+
6472
@interface FIRFirestore (Testing)
6573
@property(nonatomic, strong) FSTDispatchQueue *workerDispatchQueue;
6674
@end
@@ -195,9 +203,55 @@ - (FIRFirestore *)firestoreWithProjectID:(NSString *)projectID {
195203
firestore.settings = [FSTIntegrationTestCase settings];
196204

197205
[_firestores addObject:firestore];
206+
207+
[self primeBackend:firestore];
208+
198209
return firestore;
199210
}
200211

212+
- (void)primeBackend:(FIRFirestore *)db {
213+
static dispatch_once_t onceToken;
214+
dispatch_once(&onceToken, ^{
215+
XCTestExpectation *watchInitialized =
216+
[self expectationWithDescription:@"Prime backend: Watch initialized"];
217+
__block XCTestExpectation *watchUpdateReceived;
218+
FIRDocumentReference *docRef = [db documentWithPath:[self documentPath]];
219+
id<FIRListenerRegistration> listenerRegistration =
220+
[docRef addSnapshotListener:^(FIRDocumentSnapshot *snapshot, NSError *error) {
221+
if ([snapshot[@"value"] isEqual:@"done"]) {
222+
[watchUpdateReceived fulfill];
223+
} else {
224+
[watchInitialized fulfill];
225+
}
226+
}];
227+
228+
// Wait for watch to initialize and deliver first event.
229+
[self awaitExpectations];
230+
231+
watchUpdateReceived = [self expectationWithDescription:@"Prime backend: Watch update received"];
232+
233+
// Use a transaction to perform a write without triggering any local events.
234+
[docRef.firestore
235+
runTransactionWithBlock:^id(FIRTransaction *transaction, NSError **pError) {
236+
[transaction setData:@{@"value" : @"done"} forDocument:docRef];
237+
return nil;
238+
}
239+
completion:^(id result, NSError *error){
240+
}];
241+
242+
// Wait to see the write on the watch stream.
243+
[self waitForExpectationsWithTimeout:kPrimingTimeout
244+
handler:^(NSError *_Nullable expectationError) {
245+
if (expectationError) {
246+
XCTFail(@"Error waiting for prime backend: %@",
247+
expectationError);
248+
}
249+
}];
250+
251+
[listenerRegistration remove];
252+
});
253+
}
254+
201255
- (void)shutdownFirestore:(FIRFirestore *)firestore {
202256
[firestore shutdownWithCompletion:[self completionForExpectationWithName:@"shutdown"]];
203257
[self awaitExpectations];

0 commit comments

Comments
 (0)