aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firestore/Example
diff options
context:
space:
mode:
authorGravatar Konstantin Varlamov <var-const@users.noreply.github.com>2018-03-30 14:50:15 -0400
committerGravatar GitHub <noreply@github.com>2018-03-30 14:50:15 -0400
commita17740e9146e4e2431d62964d044287cccc3ee85 (patch)
tree479f280a07f4200924e0ef7cce183aa35e14c5bb /Firestore/Example
parent653aea7b50247bb0f6a7e8e1b4ab782553849f74 (diff)
Add a flag to control whether DocumentSnapshots return Dates or Timestamps for timestamp fields (#831)
* add a new property `timestampsInSnapshotsEnabled` to `FirestoreSettings`, `false` by default; * add a verbose warning message urging users to opt into the new behavior; * set `timestampsInSnapshotsEnabled` to true in the integration tests to reduce the verbose console spam during the test run and make sure the flag won't break anything once it's flipped.
Diffstat (limited to 'Firestore/Example')
-rw-r--r--Firestore/Example/SwiftBuildTest/main.swift2
-rw-r--r--Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm2
-rw-r--r--Firestore/Example/Tests/Integration/API/FIRFieldsTests.mm95
-rw-r--r--Firestore/Example/Tests/Integration/API/FIRServerTimestampTests.mm20
-rw-r--r--Firestore/Example/Tests/Integration/API/FIRTypeTests.mm17
-rw-r--r--Firestore/Example/Tests/Model/FSTFieldValueTests.mm18
-rw-r--r--Firestore/Example/Tests/Model/FSTMutationTests.mm2
-rw-r--r--Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm1
8 files changed, 115 insertions, 42 deletions
diff --git a/Firestore/Example/SwiftBuildTest/main.swift b/Firestore/Example/SwiftBuildTest/main.swift
index cd2462b..3087085 100644
--- a/Firestore/Example/SwiftBuildTest/main.swift
+++ b/Firestore/Example/SwiftBuildTest/main.swift
@@ -52,6 +52,7 @@ func initializeDb() -> Firestore {
let settings = FirestoreSettings()
settings.host = "localhost"
settings.isPersistenceEnabled = true
+ settings.areTimestampsInSnapshotsEnabled = true
firestore.settings = settings
return firestore
@@ -333,6 +334,7 @@ func types() {
let _: Firestore
let _: FirestoreSettings
let _: GeoPoint
+ let _: Timestamp
let _: ListenerRegistration
let _: QueryListenOptions
let _: Query
diff --git a/Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm b/Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm
index 751e7ff..312c3ff 100644
--- a/Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm
+++ b/Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm
@@ -181,7 +181,7 @@
FIRDocumentSnapshot *document = [self readDocumentForRef:doc];
XCTAssertEqual(document[@"updated"], @NO);
- XCTAssertTrue([document[@"time"] isKindOfClass:[NSDate class]]);
+ XCTAssertTrue([document[@"time"] isKindOfClass:[FIRTimestamp class]]);
}
- (void)testCanDeleteFieldUsingMerge {
diff --git a/Firestore/Example/Tests/Integration/API/FIRFieldsTests.mm b/Firestore/Example/Tests/Integration/API/FIRFieldsTests.mm
index 0e75b8e..30db5e3 100644
--- a/Firestore/Example/Tests/Integration/API/FIRFieldsTests.mm
+++ b/Firestore/Example/Tests/Integration/API/FIRFieldsTests.mm
@@ -26,6 +26,10 @@
@interface FIRFieldsTests : FSTIntegrationTestCase
@end
+NSDictionary<NSString *, id> *testDataWithTimestamps(FIRTimestamp *timestamp) {
+ return @{ @"timestamp" : timestamp, @"nested" : @{@"timestamp2" : timestamp} };
+}
+
@implementation FIRFieldsTests
- (NSDictionary<NSString *, id> *)testNestedDataNumbered:(int)number {
@@ -221,28 +225,83 @@
[self awaitExpectations];
}
-- (NSDictionary<NSString *, id> *)testDataWithTimestamp:(FIRTimestamp *)timestamp {
- return @{
- @"timestamp" : [timestamp approximateDateValue],
- @"metadata" : @{@"nestedTimestamp" : [timestamp approximateDateValue]}
- };
+- (FIRDocumentSnapshot *)snapshotWithTimestamps:(FIRTimestamp *)timestamp {
+ FIRDocumentReference *doc = [self documentRef];
+ NSDictionary<NSString *, id> *data =
+ @{ @"timestamp" : timestamp,
+ @"nested" : @{@"timestamp2" : timestamp} };
+ [self writeDocumentRef:doc data:data];
+ return [self readDocumentForRef:doc];
}
-// This test should break once the default for how timestamps are returned changes.
-- (void)testThatDataContainsNativeDateType {
- NSDate *date = [NSDate date];
- FIRTimestamp *timestamp = [FIRTimestamp timestampWithDate:date];
+// Note: timestampsInSnapshotsEnabled is set to "true" in FSTIntegrationTestCase, so this test is
+// not affected by the current default in FIRFirestoreSettings.
+- (void)testTimestampsInSnapshots {
+ FIRTimestamp *originalTimestamp = [FIRTimestamp timestampWithSeconds:100 nanoseconds:123456789];
FIRDocumentReference *doc = [self documentRef];
- [self writeDocumentRef:doc data:[self testDataWithTimestamp:timestamp]];
+ [self writeDocumentRef:doc data:testDataWithTimestamps(originalTimestamp)];
+
+ FIRDocumentSnapshot *snapshot = [self readDocumentForRef:doc];
+ NSDictionary<NSString *, id> *data = [snapshot data];
+ // Timestamp are currently truncated to microseconds after being written to the database.
+ FIRTimestamp *truncatedTimestamp =
+ [FIRTimestamp timestampWithSeconds:originalTimestamp.seconds
+ nanoseconds:originalTimestamp.nanoseconds / 1000 * 1000];
+
+ FIRTimestamp *timestampFromSnapshot = snapshot[@"timestamp"];
+ FIRTimestamp *timestampFromData = data[@"timestamp"];
+ XCTAssertEqualObjects(truncatedTimestamp, timestampFromData);
+ XCTAssertEqualObjects(timestampFromSnapshot, timestampFromData);
+
+ timestampFromSnapshot = snapshot[@"nested.timestamp2"];
+ timestampFromData = data[@"nested"][@"timestamp2"];
+ XCTAssertEqualObjects(truncatedTimestamp, timestampFromData);
+ XCTAssertEqualObjects(timestampFromSnapshot, timestampFromData);
+}
+@end
- FIRDocumentSnapshot *result = [self readDocumentForRef:doc];
- NSDate *resultDate = result.data[@"timestamp"];
- XCTAssertEqualWithAccuracy([resultDate timeIntervalSince1970], [date timeIntervalSince1970],
- 0.000001);
- XCTAssertEqualObjects(result.data[@"timestamp"], resultDate);
- NSDate *resultNestedDate = result[@"metadata.nestedTimestamp"];
- XCTAssertEqualWithAccuracy([resultNestedDate timeIntervalSince1970], [date timeIntervalSince1970],
- 0.000001);
+@interface FIRTimestampsInSnapshotsLegacyBehaviorTests : FSTIntegrationTestCase
+@end
+
+@implementation FIRTimestampsInSnapshotsLegacyBehaviorTests
+
+- (void)setUp {
+ [super setUp];
+ // Settings can only be redefined before client is initialized, so this has to happen in setUp.
+ FIRFirestoreSettings *settings = self.db.settings;
+ settings.timestampsInSnapshotsEnabled = NO;
+ self.db.settings = settings;
+}
+
+- (void)testLegacyBehaviorForTimestampFields {
+ NSDate *originalDate = [NSDate date];
+ FIRDocumentReference *doc = [self documentRef];
+ [self writeDocumentRef:doc
+ data:testDataWithTimestamps([FIRTimestamp timestampWithDate:originalDate])];
+ FIRDocumentSnapshot *snapshot = [self readDocumentForRef:doc];
+ NSDictionary<NSString *, id> *data = [snapshot data];
+ double microsecond = 0.000001;
+
+ NSDate *timestampFromSnapshot = snapshot[@"timestamp"];
+ NSDate *timestampFromData = data[@"timestamp"];
+ XCTAssertEqualObjects(timestampFromSnapshot, timestampFromData);
+ XCTAssertEqualWithAccuracy([timestampFromSnapshot timeIntervalSince1970],
+ [originalDate timeIntervalSince1970], microsecond);
+
+ timestampFromSnapshot = snapshot[@"nested.timestamp2"];
+ timestampFromData = data[@"nested"][@"timestamp2"];
+ XCTAssertEqualObjects(timestampFromSnapshot, timestampFromData);
+ XCTAssertEqualWithAccuracy([timestampFromSnapshot timeIntervalSince1970],
+ [originalDate timeIntervalSince1970], microsecond);
+}
+
+- (void)testLegacyBehaviorForServerTimestampFields {
+ FIRDocumentReference *doc = [self documentRef];
+ [self writeDocumentRef:doc data:@{@"when" : [FIRFieldValue fieldValueForServerTimestamp]}];
+
+ FIRDocumentSnapshot *snapshot = [self readDocumentForRef:doc];
+ XCTAssertTrue([snapshot[@"when"] isKindOfClass:[NSDate class]]);
+ XCTAssertTrue([snapshot.data[@"when"] isKindOfClass:[NSDate class]]);
}
@end
diff --git a/Firestore/Example/Tests/Integration/API/FIRServerTimestampTests.mm b/Firestore/Example/Tests/Integration/API/FIRServerTimestampTests.mm
index 916ce7e..4d51434 100644
--- a/Firestore/Example/Tests/Integration/API/FIRServerTimestampTests.mm
+++ b/Firestore/Example/Tests/Integration/API/FIRServerTimestampTests.mm
@@ -125,7 +125,7 @@
/** Verifies a snapshot containing _setData but with a local estimate for the timestamps. */
- (void)verifyTimestampsAreEstimatedInSnapshot:(FIRDocumentSnapshot *)snapshot {
id timestamp = [snapshot valueForField:@"when" options:_returnEstimatedValue];
- XCTAssertTrue([timestamp isKindOfClass:[NSDate class]]);
+ XCTAssertTrue([timestamp isKindOfClass:[FIRTimestamp class]]);
XCTAssertEqualObjects([snapshot dataWithOptions:_returnEstimatedValue],
[self expectedDataWithTimestamp:timestamp]);
}
@@ -148,10 +148,10 @@
/** Verifies a snapshot containing _setData but with resolved server timestamps. */
- (void)verifySnapshotWithResolvedTimestamps:(FIRDocumentSnapshot *)snapshot {
XCTAssertTrue(snapshot.exists);
- NSDate *when = snapshot[@"when"];
- XCTAssertTrue([when isKindOfClass:[NSDate class]]);
+ FIRTimestamp *when = snapshot[@"when"];
+ XCTAssertTrue([when isKindOfClass:[FIRTimestamp class]]);
// Tolerate up to 10 seconds of clock skew between client and server.
- XCTAssertEqualWithAccuracy(when.timeIntervalSinceNow, 0, 10);
+ XCTAssertEqualWithAccuracy(when.seconds, [FIRTimestamp timestamp].seconds, 10);
// Validate the rest of the document.
XCTAssertEqualObjects(snapshot.data, [self expectedDataWithTimestamp:when]);
@@ -213,14 +213,14 @@
XCTAssertEqualObjects([localSnapshot valueForField:@"a"], [NSNull null]);
XCTAssertEqualObjects([localSnapshot valueForField:@"a" options:_returnPreviousValue], @42);
XCTAssertTrue([[localSnapshot valueForField:@"a" options:_returnEstimatedValue]
- isKindOfClass:[NSDate class]]);
+ isKindOfClass:[FIRTimestamp class]]);
FIRDocumentSnapshot *remoteSnapshot = [self waitForRemoteEvent];
- XCTAssertTrue([[remoteSnapshot valueForField:@"a"] isKindOfClass:[NSDate class]]);
+ XCTAssertTrue([[remoteSnapshot valueForField:@"a"] isKindOfClass:[FIRTimestamp class]]);
XCTAssertTrue([[remoteSnapshot valueForField:@"a" options:_returnPreviousValue]
- isKindOfClass:[NSDate class]]);
+ isKindOfClass:[FIRTimestamp class]]);
XCTAssertTrue([[remoteSnapshot valueForField:@"a" options:_returnEstimatedValue]
- isKindOfClass:[NSDate class]]);
+ isKindOfClass:[FIRTimestamp class]]);
}
- (void)testServerTimestampsWithConsecutiveUpdates {
@@ -241,7 +241,7 @@
[self enableNetwork];
FIRDocumentSnapshot *remoteSnapshot = [self waitForRemoteEvent];
- XCTAssertTrue([[remoteSnapshot valueForField:@"a"] isKindOfClass:[NSDate class]]);
+ XCTAssertTrue([[remoteSnapshot valueForField:@"a"] isKindOfClass:[FIRTimestamp class]]);
}
- (void)testServerTimestampsPreviousValueFromLocalMutation {
@@ -266,7 +266,7 @@
[self enableNetwork];
FIRDocumentSnapshot *remoteSnapshot = [self waitForRemoteEvent];
- XCTAssertTrue([[remoteSnapshot valueForField:@"a"] isKindOfClass:[NSDate class]]);
+ XCTAssertTrue([[remoteSnapshot valueForField:@"a"] isKindOfClass:[FIRTimestamp class]]);
}
- (void)testServerTimestampsWorkViaTransactionSet {
diff --git a/Firestore/Example/Tests/Integration/API/FIRTypeTests.mm b/Firestore/Example/Tests/Integration/API/FIRTypeTests.mm
index 5140b90..740cde0 100644
--- a/Firestore/Example/Tests/Integration/API/FIRTypeTests.mm
+++ b/Firestore/Example/Tests/Integration/API/FIRTypeTests.mm
@@ -56,9 +56,22 @@
}];
}
-- (void)testCanReadAndWriteTimestampFields {
+- (void)testCanReadAndWriteDateFields {
// Choose a value that can be converted losslessly between fixed point and double
- NSDate *timestamp = [NSDate dateWithTimeIntervalSince1970:1491847082.125];
+ NSDate *date = [NSDate dateWithTimeIntervalSince1970:1491847082.125];
+
+ // NSDates are read back as FIRTimestamps, so assertSuccessfulRoundtrip cannot be used here.
+ FIRDocumentReference *doc = [self.db documentWithPath:@"rooms/eros"];
+ [self writeDocumentRef:doc data:@{@"date" : date}];
+ FIRDocumentSnapshot *document = [self readDocumentForRef:doc];
+ XCTAssertTrue(document.exists);
+ XCTAssertEqualObjects(document.data, @{@"date" : [FIRTimestamp timestampWithDate:date]});
+}
+
+- (void)testCanReadAndWriteTimestampFields {
+ // Timestamps are currently truncated to microseconds on the backend, so only be precise to
+ // microseconds to ensure the value read back is exactly the same.
+ FIRTimestamp *timestamp = [FIRTimestamp timestampWithSeconds:123456 nanoseconds:123456000];
[self assertSuccessfulRoundtrip:@{@"timestamp" : timestamp}];
}
diff --git a/Firestore/Example/Tests/Model/FSTFieldValueTests.mm b/Firestore/Example/Tests/Model/FSTFieldValueTests.mm
index 1a207f4..98504b5 100644
--- a/Firestore/Example/Tests/Model/FSTFieldValueTests.mm
+++ b/Firestore/Example/Tests/Model/FSTFieldValueTests.mm
@@ -227,10 +227,8 @@ union DoubleBits {
for (id value in values) {
FSTFieldValue *wrapped = FSTTestFieldValue(value);
XCTAssertEqualObjects([wrapped class], [FSTTimestampValue class]);
- XCTAssertEqualObjects([wrapped value], value);
-
- XCTAssertEqualObjects(((FSTTimestampValue *)wrapped).internalValue,
- [FIRTimestamp timestampWithDate:value]);
+ XCTAssertEqualObjects([[wrapped value] class], [FIRTimestamp class]);
+ XCTAssertEqualObjects([wrapped value], [FIRTimestamp timestampWithDate:value]);
}
}
@@ -572,14 +570,14 @@ union DoubleBits {
FSTObjectValue *value = FSTTestObjectValue(input);
id output = [value value];
{
- XCTAssertTrue([output[@"array"][1] isKindOfClass:[NSDate class]]);
- NSDate *actual = output[@"array"][1];
- XCTAssertEqualWithAccuracy(date.timeIntervalSince1970, actual.timeIntervalSince1970, 0.000001);
+ XCTAssertTrue([output[@"array"][1] isKindOfClass:[FIRTimestamp class]]);
+ FIRTimestamp *actual = output[@"array"][1];
+ XCTAssertEqualObjects([FIRTimestamp timestampWithDate:date], actual);
}
{
- XCTAssertTrue([output[@"obj"][@"date"] isKindOfClass:[NSDate class]]);
- NSDate *actual = output[@"obj"][@"date"];
- XCTAssertEqualWithAccuracy(date.timeIntervalSince1970, actual.timeIntervalSince1970, 0.000001);
+ XCTAssertTrue([output[@"obj"][@"date"] isKindOfClass:[FIRTimestamp class]]);
+ FIRTimestamp *actual = output[@"array"][1];
+ XCTAssertEqualObjects([FIRTimestamp timestampWithDate:date], actual);
}
}
diff --git a/Firestore/Example/Tests/Model/FSTMutationTests.mm b/Firestore/Example/Tests/Model/FSTMutationTests.mm
index 40ded40..1f9193e 100644
--- a/Firestore/Example/Tests/Model/FSTMutationTests.mm
+++ b/Firestore/Example/Tests/Model/FSTMutationTests.mm
@@ -143,7 +143,7 @@ using firebase::firestore::model::DocumentKey;
mutationResult:mutationResult];
NSDictionary *expectedData =
- @{ @"foo" : @{@"bar" : _timestamp.approximateDateValue},
+ @{ @"foo" : @{@"bar" : _timestamp.dateValue},
@"baz" : @"baz-value" };
XCTAssertEqualObjects(transformedDoc, FSTTestDoc("collection/key", 0, expectedData, NO));
}
diff --git a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm
index 059f257..611bcc8 100644
--- a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm
+++ b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm
@@ -129,6 +129,7 @@ NS_ASSUME_NONNULL_BEGIN
}
settings.host = host;
settings.persistenceEnabled = YES;
+ settings.timestampsInSnapshotsEnabled = YES;
NSLog(@"Configured integration test for %@ with SSL: %@", settings.host,
settings.sslEnabled ? @"YES" : @"NO");
return settings;