Skip to content

Commit

Permalink
C++ migration: port watch stream-related part of FSTRemoteStore (#2331
Browse files Browse the repository at this point in the history
)
  • Loading branch information
var-const authored Feb 3, 2019
1 parent 3905bd2 commit 456e8eb
Show file tree
Hide file tree
Showing 22 changed files with 767 additions and 539 deletions.
2 changes: 1 addition & 1 deletion Firestore/Example/Tests/Integration/FSTDatastoreTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ - (void)testStreamingWrite {
FSTRemoteStoreEventCapture *capture = [[FSTRemoteStoreEventCapture alloc] initWithTestCase:self];
[capture expectWriteEventWithDescription:@"write mutations"];

_remoteStore.syncEngine = capture;
[_remoteStore setSyncEngine:capture];

FSTSetMutation *mutation = [self setMutation];
FSTMutationBatch *batch = [[FSTMutationBatch alloc] initWithBatchID:23
Expand Down
9 changes: 6 additions & 3 deletions Firestore/Example/Tests/Local/FSTLocalStoreTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#import <FirebaseFirestore/FIRTimestamp.h>
#import <XCTest/XCTest.h>

#include <vector>

#import "Firestore/Source/Core/FSTQuery.h"
#import "Firestore/Source/Local/FSTLocalWriteResult.h"
#import "Firestore/Source/Local/FSTPersistence.h"
Expand Down Expand Up @@ -51,6 +53,7 @@
using firebase::firestore::model::SnapshotVersion;
using firebase::firestore::model::TargetId;
using firebase::firestore::remote::RemoteEvent;
using firebase::firestore::remote::TestTargetMetadataProvider;
using firebase::firestore::remote::WatchChangeAggregator;
using firebase::firestore::remote::WatchTargetChange;
using firebase::firestore::remote::WatchTargetChangeState;
Expand Down Expand Up @@ -906,9 +909,9 @@ - (void)testPersistsResumeTokens {
NSData *resumeToken = FSTTestResumeTokenFromSnapshotVersion(1000);

WatchTargetChange watchChange{WatchTargetChangeState::Current, {targetID}, resumeToken};
WatchChangeAggregator aggregator{[FSTTestTargetMetadataProvider
providerWithSingleResultForKey:testutil::Key("foo/bar")
targets:{targetID}]};
auto metadataProvider = TestTargetMetadataProvider::CreateSingleResultProvider(
testutil::Key("foo/bar"), std::vector<TargetId>{targetID});
WatchChangeAggregator aggregator{&metadataProvider};
aggregator.HandleTargetChange(watchChange);
RemoteEvent remoteEvent = aggregator.CreateRemoteEvent(testutil::Version(1000));
[self applyRemoteEvent:remoteEvent];
Expand Down
15 changes: 7 additions & 8 deletions Firestore/Example/Tests/Remote/FSTRemoteEventTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
using firebase::firestore::remote::ExistenceFilterWatchChange;
using firebase::firestore::remote::RemoteEvent;
using firebase::firestore::remote::TargetChange;
using firebase::firestore::remote::TestTargetMetadataProvider;
using firebase::firestore::remote::WatchChange;
using firebase::firestore::remote::WatchChangeAggregator;
using firebase::firestore::remote::WatchTargetChange;
Expand Down Expand Up @@ -92,13 +93,12 @@ @interface FSTRemoteEventTests : XCTestCase

@implementation FSTRemoteEventTests {
NSData *_resumeToken1;
FSTTestTargetMetadataProvider *_targetMetadataProvider;
TestTargetMetadataProvider _targetMetadataProvider;
std::unordered_map<TargetId, int> _noOutstandingResponses;
}

- (void)setUp {
_resumeToken1 = [@"resume1" dataUsingEncoding:NSUTF8StringEncoding];
_targetMetadataProvider = [FSTTestTargetMetadataProvider new];
}

/**
Expand Down Expand Up @@ -145,7 +145,7 @@ - (void)setUp {
* considered active, or `_noOutstandingResponses` if all targets are already active.
* @param existingKeys The set of documents that are considered synced with the test targets as
* part of a previous listen. To modify this set during test execution, invoke
* `[_targetMetadataProvider setSyncedKeys:forQueryData:]`.
* `_targetMetadataProvider.SetSyncedKeys()`.
* @param watchChanges The watch changes to apply before returning the aggregator. Supported
* changes are `DocumentWatchChange` and `WatchTargetChange`.
*/
Expand All @@ -154,15 +154,15 @@ - (void)setUp {
outstandingResponses:(const std::unordered_map<TargetId, int> &)outstandingResponses
existingKeys:(DocumentKeySet)existingKeys
changes:(const std::vector<std::unique_ptr<WatchChange>> &)watchChanges {
WatchChangeAggregator aggregator{_targetMetadataProvider};
WatchChangeAggregator aggregator{&_targetMetadataProvider};

std::vector<TargetId> targetIDs;
for (const auto &kv : targetMap) {
TargetId targetID = kv.first;
FSTQueryData *queryData = kv.second;

targetIDs.push_back(targetID);
[_targetMetadataProvider setSyncedKeys:existingKeys forQueryData:queryData];
_targetMetadataProvider.SetSyncedKeys(existingKeys, queryData);
};

for (const auto &kv : outstandingResponses) {
Expand Down Expand Up @@ -223,7 +223,7 @@ - (void)setUp {

- (void)testWillAccumulateDocumentAddedAndRemovedEvents {
// The target map that contains an entry for every target in this test. If a target ID is
// omitted, the target is considered inactive and FSTTestTargetMetadataProvider will fail on
// omitted, the target is considered inactive and `TestTargetMetadataProvider` will fail on
// access.
std::unordered_map<TargetId, FSTQueryData *> targetMap{
[self queryDataForTargets:{1, 2, 3, 4, 5, 6}]};
Expand Down Expand Up @@ -614,8 +614,7 @@ - (void)testDocumentUpdate {
XCTAssertEqualObjects(event.document_updates().at(doc1.key), doc1);
XCTAssertEqualObjects(event.document_updates().at(doc2.key), doc2);

[_targetMetadataProvider setSyncedKeys:DocumentKeySet{doc1.key, doc2.key}
forQueryData:targetMap[1]];
_targetMetadataProvider.SetSyncedKeys(DocumentKeySet{doc1.key, doc2.key}, targetMap[1]);

FSTDeletedDocument *deletedDoc1 = [FSTDeletedDocument documentWithKey:doc1.key
version:testutil::Version(3)
Expand Down
2 changes: 1 addition & 1 deletion Firestore/Example/Tests/SpecTests/FSTMockDatastore.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class MockDatastore : public Datastore {
util::AsyncQueue* worker_queue,
auth::CredentialsProvider* credentials);

std::shared_ptr<WatchStream> CreateWatchStream(id<FSTWatchStreamDelegate> delegate) override;
std::shared_ptr<WatchStream> CreateWatchStream(WatchStreamCallback* callback) override;
std::shared_ptr<WriteStream> CreateWriteStream(id<FSTWriteStreamDelegate> delegate) override;

/**
Expand Down
18 changes: 9 additions & 9 deletions Firestore/Example/Tests/SpecTests/FSTMockDatastore.mm
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@
CredentialsProvider* credentials_provider,
FSTSerializerBeta* serializer,
GrpcConnection* grpc_connection,
id<FSTWatchStreamDelegate> delegate,
WatchStreamCallback* callback,
MockDatastore* datastore)
: WatchStream{worker_queue, credentials_provider, serializer, grpc_connection, delegate},
: WatchStream{worker_queue, credentials_provider, serializer, grpc_connection, callback},
datastore_{datastore},
delegate_{delegate} {
callback_{callback} {
}

const std::unordered_map<TargetId, FSTQueryData*>& ActiveTargets() const {
Expand All @@ -84,7 +84,7 @@
void Start() override {
HARD_ASSERT(!open_, "Trying to start already started watch stream");
open_ = true;
[delegate_ watchStreamDidOpen];
callback_->OnWatchStreamOpen();
}

void Stop() override {
Expand Down Expand Up @@ -118,7 +118,7 @@ void UnwatchTargetId(model::TargetId target_id) override {

void FailStream(const Status& error) {
open_ = false;
[delegate_ watchStreamWasInterruptedWithError:error];
callback_->OnWatchStreamClose(error);
}

void WriteWatchChange(const WatchChange& change, SnapshotVersion snap) {
Expand All @@ -145,14 +145,14 @@ void WriteWatchChange(const WatchChange& change, SnapshotVersion snap) {
}
}

[delegate_ watchStreamDidChange:change snapshotVersion:snap];
callback_->OnWatchStreamChange(change, snap);
}

private:
bool open_ = false;
std::unordered_map<TargetId, FSTQueryData*> active_targets_;
MockDatastore* datastore_ = nullptr;
id<FSTWatchStreamDelegate> delegate_ = nullptr;
WatchStreamCallback* callback_ = nullptr;
};

class MockWriteStream : public WriteStream {
Expand Down Expand Up @@ -248,11 +248,11 @@ int sent_mutations_count() const {
credentials_{credentials} {
}

std::shared_ptr<WatchStream> MockDatastore::CreateWatchStream(id<FSTWatchStreamDelegate> delegate) {
std::shared_ptr<WatchStream> MockDatastore::CreateWatchStream(WatchStreamCallback* callback) {
watch_stream_ = std::make_shared<MockWatchStream>(
worker_queue_, credentials_,
[[FSTSerializerBeta alloc] initWithDatabaseID:&database_info_->database_id()],
grpc_connection(), delegate, this);
grpc_connection(), callback, this);

return watch_stream_;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ - (instancetype)initWithPersistence:(id<FSTPersistence>)persistence
_syncEngine = [[FSTSyncEngine alloc] initWithLocalStore:_localStore
remoteStore:_remoteStore
initialUser:initialUser];
_remoteStore.syncEngine = _syncEngine;
[_remoteStore setSyncEngine:_syncEngine];
_eventManager = [FSTEventManager eventManagerWithSyncEngine:_syncEngine];

// Set up internal event tracking for the spec tests.
Expand Down
89 changes: 48 additions & 41 deletions Firestore/Example/Tests/Util/FSTHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#import <Foundation/Foundation.h>

#include <string>
#include <unordered_map>
#include <vector>

#import "Firestore/Source/Model/FSTDocument.h"
Expand Down Expand Up @@ -141,51 +142,57 @@ inline NSString *FSTRemoveExceptionPrefix(NSString *exception) {
} while (0)

/**
* An implementation of FSTTargetMetadataProvider that provides controlled access to the
* `FSTTargetMetadataProvider` callbacks. Any target accessed via these callbacks must be
* An implementation of `TargetMetadataProvider` that provides controlled access to the
* `TargetMetadataProvider` callbacks. Any target accessed via these callbacks must be
* registered beforehand via the factory methods or via `setSyncedKeys:forQueryData:`.
*/
@interface FSTTestTargetMetadataProvider : NSObject <FSTTargetMetadataProvider>

/**
* Creates an FSTTestTargetMetadataProvider that behaves as if there's an established listen for
* each of the given targets, where each target has previously seen query results containing just
* the given documentKey.
*
* Internally this means that the `remoteKeysForTarget` callback for these targets will return just
* the documentKey and that the provided targets will be returned as active from the
* `queryDataForTarget` target.
*/
+ (instancetype)
providerWithSingleResultForKey:(firebase::firestore::model::DocumentKey)documentKey
targets:
(const std::vector<firebase::firestore::model::TargetId> &)targets;

+ (instancetype)
providerWithSingleResultForKey:(firebase::firestore::model::DocumentKey)documentKey
listenTargets:
(const std::vector<firebase::firestore::model::TargetId> &)listenTargets
limboTargets:
(const std::vector<firebase::firestore::model::TargetId> &)limboTargets;

/**
* Creates an FSTTestTargetMetadataProvider that behaves as if there's an established listen for
* each of the given targets, where each target has not seen any previous document.
*
* Internally this means that the `remoteKeysForTarget` callback for these targets will return an
* empty set of document keys and that the provided targets will be returned as active from the
* `queryDataForTarget` target.
*/
+ (instancetype)
providerWithEmptyResultForKey:(firebase::firestore::model::DocumentKey)documentKey
targets:
(const std::vector<firebase::firestore::model::TargetId> &)targets;
namespace firebase {
namespace firestore {
namespace remote {

/** Sets or replaces the local state for the provided query data. */
- (void)setSyncedKeys:(firebase::firestore::model::DocumentKeySet)keys
forQueryData:(FSTQueryData *)queryData;
class TestTargetMetadataProvider : public TargetMetadataProvider {
public:
/**
* Creates a `TestTargetMetadataProvider` that behaves as if there's an established listen for
* each of the given targets, where each target has previously seen query results containing just
* the given `document_key`.
*
* Internally this means that the `GetRemoteKeysForTarget` callback for these targets will return
* just the `document_key` and that the provided targets will be returned as active from the
* `GetQueryDataForTarget` target.
*/
static TestTargetMetadataProvider CreateSingleResultProvider(
model::DocumentKey document_key, const std::vector<model::TargetId> &targets);
static TestTargetMetadataProvider CreateSingleResultProvider(
model::DocumentKey document_key,
const std::vector<model::TargetId> &targets,
const std::vector<model::TargetId> &limbo_targets);

/**
* Creates an `TestTargetMetadataProvider` that behaves as if there's an established listen for
* each of the given targets, where each target has not seen any previous document.
*
* Internally this means that the `GetRemoteKeysForTarget` callback for these targets will return
* an empty set of document keys and that the provided targets will be returned as active from the
* `GetQueryDataForTarget` target.
*/
static TestTargetMetadataProvider CreateEmptyResultProvider(
const model::DocumentKey &document_key, const std::vector<model::TargetId> &targets);

/** Sets or replaces the local state for the provided query data. */
void SetSyncedKeys(model::DocumentKeySet keys, FSTQueryData *query_data);

model::DocumentKeySet GetRemoteKeysForTarget(model::TargetId target_id) const override;
FSTQueryData *GetQueryDataForTarget(model::TargetId target_id) const override;

private:
std::unordered_map<model::TargetId, model::DocumentKeySet> synced_keys_;
std::unordered_map<model::TargetId, FSTQueryData *> query_data_;
};

@end
} // namespace remote
} // namespace firestore
} // namespace firebase

/** Creates a new FIRTimestamp from components. Note that year, month, and day are all one-based. */
FIRTimestamp *FSTTestTimestamp(int year, int month, int day, int hour, int minute, int second);
Expand Down
Loading

0 comments on commit 456e8eb

Please sign in to comment.