19
19
#import < FirebaseFirestore/FIRFirestoreErrors.h>
20
20
21
21
#include < algorithm>
22
+ #include < cstddef>
23
+ #include < limits>
22
24
#include < map>
23
25
#include < memory>
26
+ #include < set>
24
27
#include < string>
25
28
#include < unordered_map>
26
29
#include < utility>
@@ -152,16 +155,24 @@ ByteString MakeResumeToken(NSString *specString) {
152
155
return MakeByteString ([specString dataUsingEncoding: NSUTF8StringEncoding]);
153
156
}
154
157
155
- NSString *ToDocumentListString (const std::map <DocumentKey, TargetId > &map ) {
158
+ NSString *ToDocumentListString (const std::set <DocumentKey> &keys ) {
156
159
std::vector<std::string> strings;
157
- strings.reserve (map .size ());
158
- for (const auto &kv : map ) {
159
- strings.push_back (kv. first .ToString ());
160
+ strings.reserve (keys .size ());
161
+ for (const auto &key : keys ) {
162
+ strings.push_back (key .ToString ());
160
163
}
161
164
std::sort (strings.begin (), strings.end ());
162
165
return MakeNSString (absl::StrJoin (strings, " , " ));
163
166
}
164
167
168
+ NSString *ToDocumentListString (const std::map<DocumentKey, TargetId> &map) {
169
+ std::set<DocumentKey> keys;
170
+ for (const auto &kv : map) {
171
+ keys.insert (kv.first );
172
+ }
173
+ return ToDocumentListString (keys);
174
+ }
175
+
165
176
NSString *ToTargetIdListString (const ActiveTargetMap &map) {
166
177
std::vector<model::TargetId> targetIds;
167
178
targetIds.reserve (map.size ());
@@ -181,6 +192,7 @@ @interface FSTSpecTests ()
181
192
182
193
@implementation FSTSpecTests {
183
194
BOOL _gcEnabled;
195
+ size_t _maxConcurrentLimboResolutions;
184
196
BOOL _networkEnabled;
185
197
FSTUserDataConverter *_converter;
186
198
}
@@ -212,12 +224,20 @@ - (void)setUpForSpecWithConfig:(NSDictionary *)config {
212
224
// Store GCEnabled so we can re-use it in doRestart.
213
225
NSNumber *GCEnabled = config[@" useGarbageCollection" ];
214
226
_gcEnabled = [GCEnabled boolValue ];
227
+ NSNumber *maxConcurrentLimboResolutions = config[@" maxConcurrentLimboResolutions" ];
228
+ _maxConcurrentLimboResolutions = (maxConcurrentLimboResolutions == nil )
229
+ ? std::numeric_limits<size_t >::max ()
230
+ : maxConcurrentLimboResolutions.unsignedIntValue ;
215
231
NSNumber *numClients = config[@" numClients" ];
216
232
if (numClients) {
217
233
XCTAssertEqualObjects (numClients, @1 , @" The iOS client does not support multi-client tests" );
218
234
}
219
235
std::unique_ptr<Persistence> persistence = [self persistenceWithGCEnabled: _gcEnabled];
220
- self.driver = [[FSTSyncEngineTestDriver alloc ] initWithPersistence: std: :move (persistence)];
236
+ self.driver =
237
+ [[FSTSyncEngineTestDriver alloc ] initWithPersistence: std: :move (persistence)
238
+ initialUser:User: :Unauthenticated ()
239
+ outstandingWrites: {}
240
+ maxConcurrentLimboResolutions: _maxConcurrentLimboResolutions];
221
241
[self .driver start ];
222
242
}
223
243
@@ -522,9 +542,11 @@ - (void)doRestart {
522
542
[self .driver shutdown ];
523
543
524
544
std::unique_ptr<Persistence> persistence = [self persistenceWithGCEnabled: _gcEnabled];
525
- self.driver = [[FSTSyncEngineTestDriver alloc ] initWithPersistence: std: :move (persistence)
526
- initialUser: currentUser
527
- outstandingWrites: outstandingWrites];
545
+ self.driver =
546
+ [[FSTSyncEngineTestDriver alloc ] initWithPersistence: std: :move (persistence)
547
+ initialUser: currentUser
548
+ outstandingWrites: outstandingWrites
549
+ maxConcurrentLimboResolutions: _maxConcurrentLimboResolutions];
528
550
[self .driver start ];
529
551
}
530
552
@@ -689,9 +711,18 @@ - (void)validateExpectedState:(nullable NSDictionary *)expectedState {
689
711
for (NSString *name in docNames) {
690
712
expectedActiveLimboDocuments = expectedActiveLimboDocuments.insert (FSTTestDocKey (name));
691
713
}
692
- // Update the expected limbo documents
714
+ // Update the expected active limbo documents
693
715
[self .driver setExpectedActiveLimboDocuments: std: :move (expectedActiveLimboDocuments)];
694
716
}
717
+ if (expectedState[@" enqueuedLimboDocs" ]) {
718
+ DocumentKeySet expectedEnqueuedLimboDocuments;
719
+ NSArray *docNames = expectedState[@" enqueuedLimboDocs" ];
720
+ for (NSString *name in docNames) {
721
+ expectedEnqueuedLimboDocuments = expectedEnqueuedLimboDocuments.insert (FSTTestDocKey (name));
722
+ }
723
+ // Update the expected enqueued limbo documents
724
+ [self .driver setExpectedEnqueuedLimboDocuments: std: :move (expectedEnqueuedLimboDocuments)];
725
+ }
695
726
if (expectedState[@" activeTargets" ]) {
696
727
__block ActiveTargetMap expectedActiveTargets;
697
728
[expectedState[@" activeTargets" ]
@@ -719,7 +750,8 @@ - (void)validateExpectedState:(nullable NSDictionary *)expectedState {
719
750
// Always validate the we received the expected number of callbacks.
720
751
[self validateUserCallbacks: expectedState];
721
752
// Always validate that the expected limbo docs match the actual limbo docs.
722
- [self validateLimboDocuments ];
753
+ [self validateActiveLimboDocuments ];
754
+ [self validateEnqueuedLimboDocuments ];
723
755
// Always validate that the expected active targets match the actual active targets.
724
756
[self validateActiveTargets ];
725
757
}
@@ -744,9 +776,9 @@ - (void)validateUserCallbacks:(nullable NSDictionary *)expected {
744
776
}
745
777
}
746
778
747
- - (void )validateLimboDocuments {
779
+ - (void )validateActiveLimboDocuments {
748
780
// Make a copy so it can modified while checking against the expected limbo docs.
749
- std::map<DocumentKey, TargetId> actualLimboDocs = self.driver .currentLimboDocuments ;
781
+ std::map<DocumentKey, TargetId> actualLimboDocs = self.driver .activeLimboDocumentResolutions ;
750
782
751
783
// Validate that each active limbo doc has an expected active target
752
784
for (const auto &kv : actualLimboDocs) {
@@ -767,6 +799,31 @@ - (void)validateLimboDocuments {
767
799
ToDocumentListString (actualLimboDocs));
768
800
}
769
801
802
+ - (void )validateEnqueuedLimboDocuments {
803
+ std::set<DocumentKey> actualLimboDocs;
804
+ for (const auto &key : self.driver .enqueuedLimboDocumentResolutions ) {
805
+ actualLimboDocs.insert (key);
806
+ }
807
+ std::set<DocumentKey> expectedLimboDocs;
808
+ for (const auto &key : self.driver .expectedEnqueuedLimboDocuments ) {
809
+ expectedLimboDocs.insert (key);
810
+ }
811
+
812
+ for (const auto &key : actualLimboDocs) {
813
+ XCTAssertTrue (expectedLimboDocs.find (key) != expectedLimboDocs.end (),
814
+ @" Found enqueued limbo doc %s , but it was not in the set of "
815
+ @" expected enqueued limbo documents (%@ )" ,
816
+ key.ToString ().c_str (), ToDocumentListString (expectedLimboDocs));
817
+ }
818
+
819
+ for (const auto &key : expectedLimboDocs) {
820
+ XCTAssertTrue (actualLimboDocs.find (key) != actualLimboDocs.end (),
821
+ @" Expected doc %s to be enqueued for limbo resolution, "
822
+ @" but it was not in the queue (%@ )" ,
823
+ key.ToString ().c_str (), ToDocumentListString (actualLimboDocs));
824
+ }
825
+ }
826
+
770
827
- (void )validateActiveTargets {
771
828
if (!_networkEnabled) {
772
829
return ;
0 commit comments