Files
firebase-ios-sdk/Firestore/Example/Tests/Model/FSTMutationTests.mm
T
zxu 4e7296b080 port DocumentKey to non-container types of Model/* (#930)
* naively remove FSTPath import and source/test files.

* port FieldPath, part I

* port FieldPath, part II

* port ResourcePath, part I

* port ResourcePath, part II

* the grand commit to fix build errors

* use testutil:: helper instead of those from FSTHelpers

* fix test and lint

* use c_str in errmsg directly

* fix

* fix

* make code clean

* fix integration test I missed

* fix to avoid naming collision in preprocessor

* address changes

* address changes

* address changes

* fix: fieldMask are actually shared with different context.

* address changes

* add converter function between two DocumentKey implementations

* add unit test

* address changes

* fix lint

* using DocumentKey in model except for the container types `FSTDocumentDictionary`, `FSTDocumentKeySet`, and  `FSTDocumentVersionDictionary`

* change other place w.r.t. the use of `DocumentKey` in model

* update parameter of test helpers from NSString to string_view

* revert a temporary change used in debug

* address changes
2018-03-16 15:42:05 -04:00

234 lines
10 KiB
Plaintext

/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "Firestore/Source/Model/FSTMutation.h"
#import <FirebaseFirestore/FIRTimestamp.h>
#import <XCTest/XCTest.h>
#import "Firestore/Source/Model/FSTDocument.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
namespace testutil = firebase::firestore::testutil;
using firebase::firestore::model::DocumentKey;
@interface FSTMutationTests : XCTestCase
@end
@implementation FSTMutationTests {
FIRTimestamp *_timestamp;
}
- (void)setUp {
_timestamp = [FIRTimestamp timestamp];
}
- (void)testAppliesSetsToDocuments {
NSDictionary *docData = @{@"foo" : @"foo-value", @"baz" : @"baz-value"};
FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO);
FSTMutation *set = FSTTestSetMutation(@"collection/key", @{@"bar" : @"bar-value"});
FSTMaybeDocument *setDoc = [set applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
NSDictionary *expectedData = @{@"bar" : @"bar-value"};
XCTAssertEqualObjects(setDoc, FSTTestDoc("collection/key", 0, expectedData, YES));
}
- (void)testAppliesPatchesToDocuments {
NSDictionary *docData = @{ @"foo" : @{@"bar" : @"bar-value"}, @"baz" : @"baz-value" };
FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO);
FSTMutation *patch = FSTTestPatchMutation("collection/key", @{@"foo.bar" : @"new-bar-value"}, {});
FSTMaybeDocument *patchedDoc =
[patch applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
NSDictionary *expectedData = @{ @"foo" : @{@"bar" : @"new-bar-value"}, @"baz" : @"baz-value" };
XCTAssertEqualObjects(patchedDoc, FSTTestDoc("collection/key", 0, expectedData, YES));
}
- (void)testDeletesValuesFromTheFieldMask {
NSDictionary *docData = @{ @"foo" : @{@"bar" : @"bar-value", @"baz" : @"baz-value"} };
FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO);
DocumentKey key = testutil::Key("collection/key");
FSTFieldMask *mask = [[FSTFieldMask alloc] initWithFields:{testutil::Field("foo.bar")}];
FSTMutation *patch = [[FSTPatchMutation alloc] initWithKey:key
fieldMask:mask
value:[FSTObjectValue objectValue]
precondition:[FSTPrecondition none]];
FSTMaybeDocument *patchedDoc =
[patch applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
NSDictionary *expectedData = @{ @"foo" : @{@"baz" : @"baz-value"} };
XCTAssertEqualObjects(patchedDoc, FSTTestDoc("collection/key", 0, expectedData, YES));
}
- (void)testPatchesPrimitiveValue {
NSDictionary *docData = @{@"foo" : @"foo-value", @"baz" : @"baz-value"};
FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO);
FSTMutation *patch = FSTTestPatchMutation("collection/key", @{@"foo.bar" : @"new-bar-value"}, {});
FSTMaybeDocument *patchedDoc =
[patch applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
NSDictionary *expectedData = @{ @"foo" : @{@"bar" : @"new-bar-value"}, @"baz" : @"baz-value" };
XCTAssertEqualObjects(patchedDoc, FSTTestDoc("collection/key", 0, expectedData, YES));
}
- (void)testPatchingDeletedDocumentsDoesNothing {
FSTMaybeDocument *baseDoc = FSTTestDeletedDoc("collection/key", 0);
FSTMutation *patch = FSTTestPatchMutation("collection/key", @{@"foo" : @"bar"}, {});
FSTMaybeDocument *patchedDoc =
[patch applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
XCTAssertEqualObjects(patchedDoc, baseDoc);
}
- (void)testAppliesLocalTransformsToDocuments {
NSDictionary *docData = @{ @"foo" : @{@"bar" : @"bar-value"}, @"baz" : @"baz-value" };
FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO);
FSTMutation *transform = FSTTestTransformMutation(@"collection/key", @[ @"foo.bar" ]);
FSTMaybeDocument *transformedDoc =
[transform applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
// Server timestamps aren't parsed, so we manually insert it.
FSTObjectValue *expectedData = FSTTestObjectValue(
@{ @"foo" : @{@"bar" : @"<server-timestamp>"},
@"baz" : @"baz-value" });
expectedData =
[expectedData objectBySettingValue:[FSTServerTimestampValue
serverTimestampValueWithLocalWriteTime:_timestamp
previousValue:nil]
forPath:testutil::Field("foo.bar")];
FSTDocument *expectedDoc = [FSTDocument documentWithData:expectedData
key:FSTTestDocKey(@"collection/key")
version:FSTTestVersion(0)
hasLocalMutations:YES];
XCTAssertEqualObjects(transformedDoc, expectedDoc);
}
- (void)testAppliesServerAckedTransformsToDocuments {
NSDictionary *docData = @{ @"foo" : @{@"bar" : @"bar-value"}, @"baz" : @"baz-value" };
FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO);
FSTMutation *transform = FSTTestTransformMutation(@"collection/key", @[ @"foo.bar" ]);
FSTMutationResult *mutationResult = [[FSTMutationResult alloc]
initWithVersion:FSTTestVersion(1)
transformResults:@[ [FSTTimestampValue timestampValue:_timestamp] ]];
FSTMaybeDocument *transformedDoc = [transform applyTo:baseDoc
baseDocument:baseDoc
localWriteTime:_timestamp
mutationResult:mutationResult];
NSDictionary *expectedData =
@{ @"foo" : @{@"bar" : _timestamp.approximateDateValue},
@"baz" : @"baz-value" };
XCTAssertEqualObjects(transformedDoc, FSTTestDoc("collection/key", 0, expectedData, NO));
}
- (void)testDeleteDeletes {
NSDictionary *docData = @{@"foo" : @"bar"};
FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO);
FSTMutation *mutation = FSTTestDeleteMutation(@"collection/key");
FSTMaybeDocument *result =
[mutation applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
XCTAssertEqualObjects(result, FSTTestDeletedDoc("collection/key", 0));
}
- (void)testSetWithMutationResult {
NSDictionary *docData = @{@"foo" : @"bar"};
FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO);
FSTMutation *set = FSTTestSetMutation(@"collection/key", @{@"foo" : @"new-bar"});
FSTMutationResult *mutationResult =
[[FSTMutationResult alloc] initWithVersion:FSTTestVersion(4) transformResults:nil];
FSTMaybeDocument *setDoc = [set applyTo:baseDoc
baseDocument:baseDoc
localWriteTime:_timestamp
mutationResult:mutationResult];
NSDictionary *expectedData = @{@"foo" : @"new-bar"};
XCTAssertEqualObjects(setDoc, FSTTestDoc("collection/key", 0, expectedData, NO));
}
- (void)testPatchWithMutationResult {
NSDictionary *docData = @{@"foo" : @"bar"};
FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO);
FSTMutation *patch = FSTTestPatchMutation("collection/key", @{@"foo" : @"new-bar"}, {});
FSTMutationResult *mutationResult =
[[FSTMutationResult alloc] initWithVersion:FSTTestVersion(4) transformResults:nil];
FSTMaybeDocument *patchedDoc = [patch applyTo:baseDoc
baseDocument:baseDoc
localWriteTime:_timestamp
mutationResult:mutationResult];
NSDictionary *expectedData = @{@"foo" : @"new-bar"};
XCTAssertEqualObjects(patchedDoc, FSTTestDoc("collection/key", 0, expectedData, NO));
}
#define ASSERT_VERSION_TRANSITION(mutation, base, expected) \
do { \
FSTMutationResult *mutationResult = \
[[FSTMutationResult alloc] initWithVersion:FSTTestVersion(0) transformResults:nil]; \
FSTMaybeDocument *actual = [mutation applyTo:base \
baseDocument:base \
localWriteTime:_timestamp \
mutationResult:mutationResult]; \
XCTAssertEqualObjects(actual, expected); \
} while (0);
/**
* Tests the transition table documented in FSTMutation.h.
*/
- (void)testTransitions {
FSTDocument *docV0 = FSTTestDoc("collection/key", 0, @{}, NO);
FSTDeletedDocument *deletedV0 = FSTTestDeletedDoc("collection/key", 0);
FSTDocument *docV3 = FSTTestDoc("collection/key", 3, @{}, NO);
FSTDeletedDocument *deletedV3 = FSTTestDeletedDoc("collection/key", 3);
FSTMutation *setMutation = FSTTestSetMutation(@"collection/key", @{});
FSTMutation *patchMutation = FSTTestPatchMutation("collection/key", {}, {});
FSTMutation *deleteMutation = FSTTestDeleteMutation(@"collection/key");
ASSERT_VERSION_TRANSITION(setMutation, docV3, docV3);
ASSERT_VERSION_TRANSITION(setMutation, deletedV3, docV0);
ASSERT_VERSION_TRANSITION(setMutation, nil, docV0);
ASSERT_VERSION_TRANSITION(patchMutation, docV3, docV3);
ASSERT_VERSION_TRANSITION(patchMutation, deletedV3, deletedV3);
ASSERT_VERSION_TRANSITION(patchMutation, nil, nil);
ASSERT_VERSION_TRANSITION(deleteMutation, docV3, deletedV0);
ASSERT_VERSION_TRANSITION(deleteMutation, deletedV3, deletedV0);
ASSERT_VERSION_TRANSITION(deleteMutation, nil, deletedV0);
}
#undef ASSERT_TRANSITION
@end