diff options
author | Sebastian Schmidt <mrschmidt@google.com> | 2018-06-12 10:58:35 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-12 10:58:35 -0700 |
commit | afea8d5aacf474b57b4364feda08be9ca195594b (patch) | |
tree | d43c39ae9f71e88d256012f4467cd2b707fc7ddd /Firestore/Example/Tests/Util | |
parent | 0db8ef7dbe6c8c191252d33090dbb88b98735148 (diff) |
Refactor Remote Event (#1396)
Diffstat (limited to 'Firestore/Example/Tests/Util')
-rw-r--r-- | Firestore/Example/Tests/Util/FSTHelpers.h | 54 | ||||
-rw-r--r-- | Firestore/Example/Tests/Util/FSTHelpers.mm | 135 |
2 files changed, 169 insertions, 20 deletions
diff --git a/Firestore/Example/Tests/Util/FSTHelpers.h b/Firestore/Example/Tests/Util/FSTHelpers.h index ccc01ca..7946c06 100644 --- a/Firestore/Example/Tests/Util/FSTHelpers.h +++ b/Firestore/Example/Tests/Util/FSTHelpers.h @@ -16,11 +16,11 @@ #import <Foundation/Foundation.h> -#include <map> #include <vector> #import "Firestore/Source/Core/FSTTypes.h" #import "Firestore/Source/Model/FSTDocumentDictionary.h" +#import "Firestore/Source/Remote/FSTRemoteEvent.h" #include "Firestore/core/src/firebase/firestore/model/field_path.h" #include "Firestore/core/src/firebase/firestore/model/field_value.h" @@ -148,6 +148,42 @@ inline NSString *FSTRemoveExceptionPrefix(NSString *exception) { XCTAssertTrue(didThrow, ##__VA_ARGS__); \ } while (0) +/** + * An implementation of FSTTargetMetadataProvider that provides controlled access to the + * `FSTTargetMetadataProvider` 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:(NSArray<FSTBoxedTargetID *> *)targets; + +/** + * 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:(NSArray<FSTBoxedTargetID *> *)targets; + +/** Sets or replaces the local state for the provided query data. */ +- (void)setSyncedKeys:(firebase::firestore::model::DocumentKeySet)keys + forQueryData:(FSTQueryData *)queryData; + +@end + /** 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); @@ -250,6 +286,9 @@ FSTDeleteMutation *FSTTestDeleteMutation(NSString *path); /** Converts a list of documents to a sorted map. */ FSTMaybeDocumentDictionary *FSTTestDocUpdates(NSArray<FSTMaybeDocument *> *docs); +/** Creates a remote event that inserts a new document. */ +FSTRemoteEvent *FSTTestAddedRemoteEvent(FSTMaybeDocument *doc, NSArray<NSNumber *> *addedToTargets); + /** Creates a remote event with changes to a document. */ FSTRemoteEvent *FSTTestUpdateRemoteEvent(FSTMaybeDocument *doc, NSArray<NSNumber *> *updatedInTargets, @@ -260,6 +299,19 @@ FSTLocalViewChanges *FSTTestViewChanges(FSTQuery *query, NSArray<NSString *> *addedKeys, NSArray<NSString *> *removedKeys); +/** Creates a test target change that acks all 'docs' and marks the target as CURRENT */ +FSTTargetChange *FSTTestTargetChangeAckDocuments(firebase::firestore::model::DocumentKeySet docs); + +/** Creates a test target change that marks the target as CURRENT */ +FSTTargetChange *FSTTestTargetChangeMarkCurrent(); + +/** Creates a test target change. */ +FSTTargetChange *FSTTestTargetChange(firebase::firestore::model::DocumentKeySet added, + firebase::firestore::model::DocumentKeySet modified, + firebase::firestore::model::DocumentKeySet removed, + NSData *resumeToken, + BOOL current); + /** Creates a resume token to match the given snapshot version. */ NSData *_Nullable FSTTestResumeTokenFromSnapshotVersion(FSTTestSnapshotVersion watchSnapshot); diff --git a/Firestore/Example/Tests/Util/FSTHelpers.mm b/Firestore/Example/Tests/Util/FSTHelpers.mm index 5ed4fd5..8ece82f 100644 --- a/Firestore/Example/Tests/Util/FSTHelpers.mm +++ b/Firestore/Example/Tests/Util/FSTHelpers.mm @@ -22,7 +22,7 @@ #include <cinttypes> #include <list> -#include <map> +#include <unordered_map> #include <utility> #include <vector> @@ -58,6 +58,7 @@ namespace util = firebase::firestore::util; namespace testutil = firebase::firestore::testutil; using firebase::firestore::model::DatabaseId; using firebase::firestore::model::DocumentKey; +using firebase::firestore::model::DocumentKeySet; using firebase::firestore::model::FieldMask; using firebase::firestore::model::FieldPath; using firebase::firestore::model::FieldTransform; @@ -65,8 +66,8 @@ using firebase::firestore::model::FieldValue; using firebase::firestore::model::Precondition; using firebase::firestore::model::ResourcePath; using firebase::firestore::model::ServerTimestampTransform; +using firebase::firestore::model::SnapshotVersion; using firebase::firestore::model::TransformOperation; -using firebase::firestore::model::DocumentKeySet; NS_ASSUME_NONNULL_BEGIN @@ -298,29 +299,125 @@ FSTViewSnapshot *_Nullable FSTTestApplyChanges(FSTView *view, .snapshot; } +@implementation FSTTestTargetMetadataProvider { + std::unordered_map<FSTTargetID, DocumentKeySet> _syncedKeys; + std::unordered_map<FSTTargetID, FSTQueryData *> _queryData; +} + ++ (instancetype)providerWithSingleResultForKey:(DocumentKey)documentKey + targets:(NSArray<FSTBoxedTargetID *> *)targets { + FSTTestTargetMetadataProvider *metadataProvider = [FSTTestTargetMetadataProvider new]; + FSTQuery *query = [FSTQuery queryWithPath:documentKey.path()]; + + for (FSTBoxedTargetID *targetID in targets) { + FSTQueryData *queryData = [[FSTQueryData alloc] initWithQuery:query + targetID:targetID.intValue + listenSequenceNumber:0 + purpose:FSTQueryPurposeListen]; + [metadataProvider setSyncedKeys:DocumentKeySet{documentKey} forQueryData:queryData]; + } + + return metadataProvider; +} + ++ (instancetype)providerWithEmptyResultForKey:(DocumentKey)documentKey + targets:(NSArray<FSTBoxedTargetID *> *)targets { + FSTTestTargetMetadataProvider *metadataProvider = [FSTTestTargetMetadataProvider new]; + FSTQuery *query = [FSTQuery queryWithPath:documentKey.path()]; + + for (FSTBoxedTargetID *targetID in targets) { + FSTQueryData *queryData = [[FSTQueryData alloc] initWithQuery:query + targetID:targetID.intValue + listenSequenceNumber:0 + purpose:FSTQueryPurposeListen]; + [metadataProvider setSyncedKeys:DocumentKeySet {} forQueryData:queryData]; + } + + return metadataProvider; +} + +- (void)setSyncedKeys:(DocumentKeySet)keys forQueryData:(FSTQueryData *)queryData { + _syncedKeys[queryData.targetID] = keys; + _queryData[queryData.targetID] = queryData; +} + +- (DocumentKeySet)remoteKeysForTarget:(FSTBoxedTargetID *)targetID { + auto it = _syncedKeys.find(targetID.intValue); + HARD_ASSERT(it != _syncedKeys.end(), "Cannot process unknown target %s", targetID.intValue); + return it->second; +} + +- (nullable FSTQueryData *)queryDataForTarget:(FSTBoxedTargetID *)targetID { + auto it = _queryData.find(targetID.intValue); + HARD_ASSERT(it != _queryData.end(), "Cannot process unknown target %s", targetID.intValue); + return it->second; +} + +@end + +FSTRemoteEvent *FSTTestAddedRemoteEvent(FSTMaybeDocument *doc, + NSArray<FSTBoxedTargetID *> *addedToTargets) { + HARD_ASSERT(![doc isKindOfClass:[FSTDocument class]] || ![(FSTDocument *)doc hasLocalMutations], + "Docs from remote updates shouldn't have local changes."); + FSTDocumentWatchChange *change = + [[FSTDocumentWatchChange alloc] initWithUpdatedTargetIDs:addedToTargets + removedTargetIDs:{} + documentKey:doc.key + document:doc]; + FSTWatchChangeAggregator *aggregator = [[FSTWatchChangeAggregator alloc] + initWithTargetMetadataProvider:[FSTTestTargetMetadataProvider + providerWithEmptyResultForKey:doc.key + targets:addedToTargets]]; + [aggregator handleDocumentChange:change]; + return [aggregator remoteEventAtSnapshotVersion:doc.version]; +} + FSTRemoteEvent *FSTTestUpdateRemoteEvent(FSTMaybeDocument *doc, - NSArray<NSNumber *> *updatedInTargets, - NSArray<NSNumber *> *removedFromTargets) { + NSArray<FSTBoxedTargetID *> *updatedInTargets, + NSArray<FSTBoxedTargetID *> *removedFromTargets) { + HARD_ASSERT(![doc isKindOfClass:[FSTDocument class]] || ![(FSTDocument *)doc hasLocalMutations], + "Docs from remote updates shouldn't have local changes."); FSTDocumentWatchChange *change = [[FSTDocumentWatchChange alloc] initWithUpdatedTargetIDs:updatedInTargets removedTargetIDs:removedFromTargets documentKey:doc.key document:doc]; - NSMutableDictionary<NSNumber *, FSTQueryData *> *listens = [NSMutableDictionary dictionary]; - FSTQueryData *dummyQueryData = [FSTQueryData alloc]; - for (NSNumber *targetID in updatedInTargets) { - listens[targetID] = dummyQueryData; - } - for (NSNumber *targetID in removedFromTargets) { - listens[targetID] = dummyQueryData; - } - NSMutableDictionary<NSNumber *, NSNumber *> *pending = [NSMutableDictionary dictionary]; - FSTWatchChangeAggregator *aggregator = - [[FSTWatchChangeAggregator alloc] initWithSnapshotVersion:doc.version - listenTargets:listens - pendingTargetResponses:pending]; - [aggregator addWatchChange:change]; - return [aggregator remoteEvent]; + NSArray<FSTBoxedTargetID *> *targets = + [updatedInTargets arrayByAddingObjectsFromArray:removedFromTargets]; + FSTWatchChangeAggregator *aggregator = [[FSTWatchChangeAggregator alloc] + initWithTargetMetadataProvider:[FSTTestTargetMetadataProvider + providerWithSingleResultForKey:doc.key + targets:targets]]; + [aggregator handleDocumentChange:change]; + return [aggregator remoteEventAtSnapshotVersion:doc.version]; +} + +FSTTargetChange *FSTTestTargetChangeMarkCurrent() { + return [[FSTTargetChange alloc] initWithResumeToken:[NSData data] + current:YES + addedDocuments:DocumentKeySet {} + modifiedDocuments:DocumentKeySet {} + removedDocuments:DocumentKeySet{}]; +} + +FSTTargetChange *FSTTestTargetChangeAckDocuments(DocumentKeySet docs) { + return [[FSTTargetChange alloc] initWithResumeToken:[NSData data] + current:YES + addedDocuments:docs + modifiedDocuments:DocumentKeySet {} + removedDocuments:DocumentKeySet{}]; +} + +FSTTargetChange *FSTTestTargetChange(DocumentKeySet added, + DocumentKeySet modified, + DocumentKeySet removed, + NSData *resumeToken, + BOOL current) { + return [[FSTTargetChange alloc] initWithResumeToken:resumeToken + current:current + addedDocuments:added + modifiedDocuments:modified + removedDocuments:removed]; } /** Creates a resume token to match the given snapshot version. */ |