Skip to content

Commit 24370d3

Browse files
Add spec test support for target-scoped resume tokens
1 parent 063d1e9 commit 24370d3

13 files changed

+1172
-310
lines changed

Firestore/Example/Tests/SpecTests/FSTMockDatastore.mm

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ - (void)failStreamWithError:(NSError *)error {
138138

139139
#pragma mark - Helper methods.
140140

141-
- (void)writeWatchChange:(FSTWatchChange *)change snapshotVersion:(const SnapshotVersion &)snap {
141+
- (void)writeWatchChange:(FSTWatchChange *)change snapshotVersion:(SnapshotVersion)snap {
142142
if ([change isKindOfClass:[FSTWatchTargetChange class]]) {
143143
FSTWatchTargetChange *targetChange = (FSTWatchTargetChange *)change;
144144
if (targetChange.cause) {
@@ -152,6 +152,11 @@ - (void)writeWatchChange:(FSTWatchChange *)change snapshotVersion:(const Snapsho
152152
[self.activeTargets removeObjectForKey:targetID];
153153
}
154154
}
155+
if ([targetChange.targetIDs count] != 0) {
156+
// If the list of target IDs is not empty, we reset the snapshot version to NONE as
157+
// done in `FSTSerializerBeta.versionFromListenResponse:`.
158+
snap = SnapshotVersion::None();
159+
}
155160
}
156161
[self.delegate watchStreamDidChange:change snapshotVersion:snap];
157162
}

Firestore/Example/Tests/SpecTests/FSTSpecTests.mm

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -194,25 +194,25 @@ - (void)doDelete:(NSString *)key {
194194
[self.driver writeUserMutation:FSTTestDeleteMutation(key)];
195195
}
196196

197-
- (void)doWatchAck:(NSArray<NSNumber *> *)ackedTargets snapshot:(NSNumber *)watchSnapshot {
197+
- (void)doWatchAck:(NSArray<NSNumber *> *)ackedTargets {
198198
FSTWatchTargetChange *change =
199199
[FSTWatchTargetChange changeWithState:FSTWatchTargetChangeStateAdded
200200
targetIDs:ackedTargets
201201
cause:nil];
202-
[self.driver receiveWatchChange:change snapshotVersion:[self parseVersion:watchSnapshot]];
202+
[self.driver receiveWatchChange:change snapshotVersion:SnapshotVersion::None()];
203203
}
204204

205-
- (void)doWatchCurrent:(NSArray<id> *)currentSpec snapshot:(NSNumber *)watchSnapshot {
205+
- (void)doWatchCurrent:(NSArray<id> *)currentSpec {
206206
NSArray<NSNumber *> *currentTargets = currentSpec[0];
207207
NSData *resumeToken = [currentSpec[1] dataUsingEncoding:NSUTF8StringEncoding];
208208
FSTWatchTargetChange *change =
209209
[FSTWatchTargetChange changeWithState:FSTWatchTargetChangeStateCurrent
210210
targetIDs:currentTargets
211211
resumeToken:resumeToken];
212-
[self.driver receiveWatchChange:change snapshotVersion:[self parseVersion:watchSnapshot]];
212+
[self.driver receiveWatchChange:change snapshotVersion:SnapshotVersion::None()];
213213
}
214214

215-
- (void)doWatchRemove:(NSDictionary *)watchRemoveSpec snapshot:(NSNumber *)watchSnapshot {
215+
- (void)doWatchRemove:(NSDictionary *)watchRemoveSpec {
216216
NSError *error = nil;
217217
NSDictionary *cause = watchRemoveSpec[@"cause"];
218218
if (cause) {
@@ -226,19 +226,16 @@ - (void)doWatchRemove:(NSDictionary *)watchRemoveSpec snapshot:(NSNumber *)watch
226226
[FSTWatchTargetChange changeWithState:FSTWatchTargetChangeStateRemoved
227227
targetIDs:watchRemoveSpec[@"targetIds"]
228228
cause:error];
229-
[self.driver receiveWatchChange:change snapshotVersion:[self parseVersion:watchSnapshot]];
229+
[self.driver receiveWatchChange:change snapshotVersion:SnapshotVersion::None()];
230230
// Unlike web, the FSTMockDatastore detects a watch removal with cause and will remove active
231231
// targets
232232
}
233233

234-
- (void)doWatchEntity:(NSDictionary *)watchEntity snapshot:(NSNumber *_Nullable)watchSnapshot {
234+
- (void)doWatchEntity:(NSDictionary *)watchEntity {
235235
if (watchEntity[@"docs"]) {
236236
HARD_ASSERT(!watchEntity[@"doc"], "Exactly one of |doc| or |docs| needs to be set.");
237-
int count = 0;
238237
NSArray *docs = watchEntity[@"docs"];
239238
for (NSDictionary *doc in docs) {
240-
count++;
241-
bool isLast = (count == docs.count);
242239
NSMutableDictionary *watchSpec = [NSMutableDictionary dictionary];
243240
watchSpec[@"doc"] = doc;
244241
if (watchEntity[@"targets"]) {
@@ -247,11 +244,7 @@ - (void)doWatchEntity:(NSDictionary *)watchEntity snapshot:(NSNumber *_Nullable)
247244
if (watchEntity[@"removedTargets"]) {
248245
watchSpec[@"removedTargets"] = watchEntity[@"removedTargets"];
249246
}
250-
NSNumber *_Nullable version = nil;
251-
if (isLast) {
252-
version = watchSnapshot;
253-
}
254-
[self doWatchEntity:watchSpec snapshot:version];
247+
[self doWatchEntity:watchSpec];
255248
}
256249
} else if (watchEntity[@"doc"]) {
257250
NSArray *docSpec = watchEntity[@"doc"];
@@ -270,21 +263,21 @@ - (void)doWatchEntity:(NSDictionary *)watchEntity snapshot:(NSNumber *_Nullable)
270263
removedTargetIDs:watchEntity[@"removedTargets"]
271264
documentKey:doc.key
272265
document:doc];
273-
[self.driver receiveWatchChange:change snapshotVersion:[self parseVersion:watchSnapshot]];
266+
[self.driver receiveWatchChange:change snapshotVersion:SnapshotVersion::None()];
274267
} else if (watchEntity[@"key"]) {
275268
FSTDocumentKey *docKey = FSTTestDocKey(watchEntity[@"key"]);
276269
FSTWatchChange *change =
277270
[[FSTDocumentWatchChange alloc] initWithUpdatedTargetIDs:@[]
278271
removedTargetIDs:watchEntity[@"removedTargets"]
279272
documentKey:docKey
280273
document:nil];
281-
[self.driver receiveWatchChange:change snapshotVersion:[self parseVersion:watchSnapshot]];
274+
[self.driver receiveWatchChange:change snapshotVersion:SnapshotVersion::None()];
282275
} else {
283276
HARD_FAIL("Either key, doc or docs must be set.");
284277
}
285278
}
286279

287-
- (void)doWatchFilter:(NSArray *)watchFilter snapshot:(NSNumber *_Nullable)watchSnapshot {
280+
- (void)doWatchFilter:(NSArray *)watchFilter {
288281
NSArray<NSNumber *> *targets = watchFilter[0];
289282
HARD_ASSERT(targets.count == 1, "ExistenceFilters currently support exactly one target only.");
290283

@@ -294,15 +287,29 @@ - (void)doWatchFilter:(NSArray *)watchFilter snapshot:(NSNumber *_Nullable)watch
294287
FSTExistenceFilter *filter = [FSTExistenceFilter filterWithCount:keyCount];
295288
FSTExistenceFilterWatchChange *change =
296289
[FSTExistenceFilterWatchChange changeWithFilter:filter targetID:targets[0].intValue];
297-
[self.driver receiveWatchChange:change snapshotVersion:[self parseVersion:watchSnapshot]];
290+
[self.driver receiveWatchChange:change snapshotVersion:SnapshotVersion::None()];
298291
}
299292

300-
- (void)doWatchReset:(NSArray<NSNumber *> *)watchReset snapshot:(NSNumber *_Nullable)watchSnapshot {
293+
- (void)doWatchReset:(NSArray<NSNumber *> *)watchReset {
301294
FSTWatchTargetChange *change =
302295
[FSTWatchTargetChange changeWithState:FSTWatchTargetChangeStateReset
303296
targetIDs:watchReset
304297
cause:nil];
305-
[self.driver receiveWatchChange:change snapshotVersion:[self parseVersion:watchSnapshot]];
298+
[self.driver receiveWatchChange:change snapshotVersion:SnapshotVersion::None()];
299+
}
300+
301+
- (void)doWatchSnapshot:(NSDictionary *)watchSnapshot {
302+
// The client will only respond to watchSnapshots if they are on a target change with an empty
303+
// set of target IDs.
304+
NSArray<NSNumber *> *targetIDs =
305+
watchSnapshot[@"targetIds"] ? watchSnapshot[@"targetIds"] : [NSArray array];
306+
NSData *resumeToken = [watchSnapshot[@"resumeToken"] dataUsingEncoding:NSUTF8StringEncoding];
307+
FSTWatchTargetChange *change =
308+
[FSTWatchTargetChange changeWithState:FSTWatchTargetChangeStateNoChange
309+
targetIDs:targetIDs
310+
resumeToken:resumeToken];
311+
[self.driver receiveWatchChange:change
312+
snapshotVersion:[self parseVersion:watchSnapshot[@"version"]]];
306313
}
307314

308315
- (void)doWatchStreamClose:(NSDictionary *)closeSpec {
@@ -415,17 +422,19 @@ - (void)doStep:(NSDictionary *)step {
415422
} else if (step[@"userDelete"]) {
416423
[self doDelete:step[@"userDelete"]];
417424
} else if (step[@"watchAck"]) {
418-
[self doWatchAck:step[@"watchAck"] snapshot:step[@"watchSnapshot"]];
425+
[self doWatchAck:step[@"watchAck"]];
419426
} else if (step[@"watchCurrent"]) {
420-
[self doWatchCurrent:step[@"watchCurrent"] snapshot:step[@"watchSnapshot"]];
427+
[self doWatchCurrent:step[@"watchCurrent"]];
421428
} else if (step[@"watchRemove"]) {
422-
[self doWatchRemove:step[@"watchRemove"] snapshot:step[@"watchSnapshot"]];
429+
[self doWatchRemove:step[@"watchRemove"]];
423430
} else if (step[@"watchEntity"]) {
424-
[self doWatchEntity:step[@"watchEntity"] snapshot:step[@"watchSnapshot"]];
431+
[self doWatchEntity:step[@"watchEntity"]];
425432
} else if (step[@"watchFilter"]) {
426-
[self doWatchFilter:step[@"watchFilter"] snapshot:step[@"watchSnapshot"]];
433+
[self doWatchFilter:step[@"watchFilter"]];
427434
} else if (step[@"watchReset"]) {
428-
[self doWatchReset:step[@"watchReset"] snapshot:step[@"watchSnapshot"]];
435+
[self doWatchReset:step[@"watchReset"]];
436+
} else if (step[@"watchSnapshot"]) {
437+
[self doWatchSnapshot:step[@"watchSnapshot"]];
429438
} else if (step[@"watchStreamClose"]) {
430439
[self doWatchStreamClose:step[@"watchStreamClose"]];
431440
} else if (step[@"watchProto"]) {

Firestore/Example/Tests/SpecTests/json/collection_spec_test.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,12 @@
5656
2
5757
],
5858
"resume-token-1001"
59-
],
60-
"watchSnapshot": 1001,
59+
]
60+
},
61+
{
62+
"watchSnapshot": {
63+
"version": 1001
64+
},
6165
"expect": [
6266
{
6367
"query": {

0 commit comments

Comments
 (0)