Skip to content

Adding onSnapshotsInSync (not public) #3850

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,42 @@ - (void)testAddingToACollectionYieldsTheCorrectDocumentReference {
[self awaitExpectations];
}

- (void)testSnapshotsInSyncListenerFiresAfterListenersInSync {
FIRCollectionReference *coll = [self.db collectionWithPath:@"collection"];
FIRDocumentReference *ref = [coll addDocumentWithData:@{@"foo" : @1}];
NSMutableArray<NSString *> *events = [NSMutableArray array];

XCTestExpectation *gotInitialSnapshot = [self expectationWithDescription:@"gotInitialSnapshot"];
__block bool setupComplete = false;
[ref addSnapshotListener:^(FIRDocumentSnapshot *snapshot, NSError *error) {
XCTAssertNil(error);
[events addObject:@"doc"];
// Wait for the initial event from the backend so that we know we'll get exactly one snapshot
// event for our local write below.
if (!setupComplete) {
setupComplete = true;
[gotInitialSnapshot fulfill];
}
}];

[self awaitExpectations];
[events removeAllObjects];

XCTestExpectation *done = [self expectationWithDescription:@"SnapshotsInSyncListenerDone"];
[ref.firestore addSnapshotsInSyncListener:^() {
[events addObject:@"snapshots-in-sync"];
if ([events count] == 3) {
// We should have an initial snapshots-in-sync event, then a snapshot event
// for set(), then another event to indicate we're in sync again.
NSArray<NSString *> *expected = @[ @"snapshots-in-sync", @"doc", @"snapshots-in-sync" ];
XCTAssertEqualObjects(events, expected);
[done fulfill];
}
}];

[self writeDocumentRef:ref data:@{@"foo" : @3}];
}

- (void)testListenCanBeCalledMultipleTimes {
FIRCollectionReference *coll = [self.db collectionWithPath:@"collection"];
FIRDocumentReference *doc = [coll documentWithAutoID];
Expand Down
19 changes: 19 additions & 0 deletions Firestore/Example/Tests/SpecTests/FSTSpecTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,14 @@ - (void)doDelete:(NSString *)key {
[self.driver writeUserMutation:FSTTestDeleteMutation(key)];
}

- (void)doAddSnapshotsInSyncListener {
[self.driver addSnapshotsInSyncListener];
}

- (void)doRemoveSnapshotsInSyncListener {
[self.driver removeSnapshotsInSyncListener];
}

- (void)doWatchAck:(NSArray<NSNumber *> *)ackedTargets {
WatchTargetChange change{WatchTargetChangeState::Added, ConvertTargetsArray(ackedTargets)};
[self.driver receiveWatchChange:change snapshotVersion:SnapshotVersion::None()];
Expand Down Expand Up @@ -479,6 +487,10 @@ - (void)doStep:(NSDictionary *)step {
[self doPatch:step[@"userPatch"]];
} else if (step[@"userDelete"]) {
[self doDelete:step[@"userDelete"]];
} else if (step[@"addSnapshotsInSyncListener"]) {
[self doAddSnapshotsInSyncListener];
} else if (step[@"removeSnapshotsInSyncListener"]) {
[self doRemoveSnapshotsInSyncListener];
} else if (step[@"drainQueue"]) {
[self doDrainQueue];
} else if (step[@"watchAck"]) {
Expand Down Expand Up @@ -651,6 +663,11 @@ - (void)validateStateExpectations:(nullable NSDictionary *)expected {
[self validateActiveTargets];
}

- (void)validateSnapshotsInSyncEvents:(int)expectedSnapshotInSyncEvents {
XCTAssertEqual(expectedSnapshotInSyncEvents, [self.driver snapshotsInSyncEvents]);
[self.driver resetSnapshotsInSyncEvents];
}

- (void)validateUserCallbacks:(nullable NSDictionary *)expected {
NSDictionary *expectedCallbacks = expected[@"userCallbacks"];
NSArray<NSString *> *actualAcknowledgedDocs =
Expand Down Expand Up @@ -728,6 +745,8 @@ - (void)runSpecTestSteps:(NSArray *)steps config:(NSDictionary *)config {
[self doStep:step];
[self validateStepExpectations:step[@"expect"]];
[self validateStateExpectations:step[@"stateExpect"]];
int expectedSnapshotsInSyncEvents = [step[@"expectedSnapshotsInSyncEvents"] intValue];
[self validateSnapshotsInSyncEvents:expectedSnapshotsInSyncEvents];
}
[self.driver validateUsage];
} @finally {
Expand Down
22 changes: 22 additions & 0 deletions Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <vector>

#include "Firestore/core/src/firebase/firestore/auth/user.h"
#include "Firestore/core/src/firebase/firestore/core/event_listener.h"
#include "Firestore/core/src/firebase/firestore/core/query.h"
#include "Firestore/core/src/firebase/firestore/core/view_snapshot.h"
#include "Firestore/core/src/firebase/firestore/local/query_data.h"
Expand All @@ -32,6 +33,7 @@
#include "Firestore/core/src/firebase/firestore/model/types.h"
#include "Firestore/core/src/firebase/firestore/remote/watch_change.h"
#include "Firestore/core/src/firebase/firestore/util/async_queue.h"
#include "Firestore/core/src/firebase/firestore/util/empty.h"

namespace firebase {
namespace firestore {
Expand Down Expand Up @@ -311,6 +313,26 @@ typedef std::unordered_map<firebase::firestore::auth::User,
/** The current user for the FSTSyncEngine; determines which mutation queue is active. */
@property(nonatomic, assign, readonly) const firebase::firestore::auth::User &currentUser;

/**
* The number of snapshots-in-sync events that have been received.
*/
@property(nonatomic, readonly) int snapshotsInSyncEvents;

- (void)incrementSnapshotsInSyncEvents;

- (void)resetSnapshotsInSyncEvents;

/**
* Adds a snpahots-in-sync listener to the event manager and keeps track of it so that it
* can be easily removed later.
*/
- (void)addSnapshotsInSyncListener;

/**
* Removes the snapshots-in-sync listener from the event manager.
*/
- (void)removeSnapshotsInSyncListener;

/** The set of active targets as observed on the watch stream. */
- (const std::unordered_map<firebase::firestore::model::TargetId, local::QueryData> &)activeTargets;

Expand Down
33 changes: 33 additions & 0 deletions Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
using firebase::firestore::auth::HashUser;
using firebase::firestore::auth::User;
using firebase::firestore::core::DatabaseInfo;
using firebase::firestore::core::EventListener;
using firebase::firestore::core::EventManager;
using firebase::firestore::core::ListenOptions;
using firebase::firestore::core::Query;
Expand All @@ -78,6 +79,7 @@
using firebase::firestore::remote::WatchChange;
using firebase::firestore::util::AsyncQueue;
using firebase::firestore::util::DelayedConstructor;
using firebase::firestore::util::Empty;
using firebase::firestore::util::ExecutorLibdispatch;
using firebase::firestore::util::MakeNSError;
using firebase::firestore::util::MakeNSString;
Expand Down Expand Up @@ -170,7 +172,10 @@ @implementation FSTSyncEngineTestDriver {
DatabaseInfo _databaseInfo;
User _currentUser;

std::vector<std::shared_ptr<EventListener<Empty>>> _snapshotsInSyncListeners;
std::shared_ptr<MockDatastore> _datastore;

int _snapshotsInSyncEvents;
}

- (instancetype)initWithPersistence:(std::unique_ptr<Persistence>)persistence {
Expand Down Expand Up @@ -246,6 +251,34 @@ - (void)drainQueue {
return _currentUser;
}

- (void)incrementSnapshotsInSyncEvents {
_snapshotsInSyncEvents += 1;
}

- (void)resetSnapshotsInSyncEvents {
_snapshotsInSyncEvents = 0;
}

- (void)addSnapshotsInSyncListener {
std::shared_ptr<EventListener<Empty>> eventListener = EventListener<Empty>::Create(
[self](const StatusOr<Empty> &) { [self incrementSnapshotsInSyncEvents]; });
_snapshotsInSyncListeners.push_back(eventListener);
_eventManager->AddSnapshotsInSyncListener(eventListener);
}

- (void)removeSnapshotsInSyncListener {
if (_snapshotsInSyncListeners.empty()) {
HARD_FAIL("There must be a listener to unlisten to");
} else {
_eventManager->RemoveSnapshotsInSyncListener(_snapshotsInSyncListeners.back());
_snapshotsInSyncListeners.pop_back();
}
}

- (int)snapshotsInSyncEvents {
return _snapshotsInSyncEvents;
}

- (void)start {
_workerQueue->EnqueueBlocking([&] {
_localStore->Start();
Expand Down
Loading