From f6de35c504de88bc57d200f1d60da2c1e92c07f4 Mon Sep 17 00:00:00 2001 From: Marek Gilbert Date: Mon, 28 Jan 2019 14:23:55 -0800 Subject: [PATCH 1/4] Reorder tests to match Android --- .../Integration/API/FIRWriteBatchTests.mm | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm b/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm index 472b8ac565e..7fd44572c0e 100644 --- a/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm +++ b/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm @@ -124,6 +124,52 @@ - (void)testCannotUpdateNonexistentDocuments { XCTAssertFalse(result.exists); } +- (void)testUpdateFieldsWithDots { + FIRDocumentReference *doc = [self documentRef]; + + XCTestExpectation *expectation = [self expectationWithDescription:@"testUpdateFieldsWithDots"]; + FIRWriteBatch *batch = [doc.firestore batch]; + [batch setData:@{@"a.b" : @"old", @"c.d" : @"old"} forDocument:doc]; + [batch updateData:@{[[FIRFieldPath alloc] initWithFields:@[ @"a.b" ]] : @"new"} forDocument:doc]; + + [batch commitWithCompletion:^(NSError *_Nullable error) { + XCTAssertNil(error); + [doc getDocumentWithCompletion:^(FIRDocumentSnapshot *snapshot, NSError *error) { + XCTAssertNil(error); + XCTAssertEqualObjects(snapshot.data, (@{@"a.b" : @"new", @"c.d" : @"old"})); + }]; + [expectation fulfill]; + }]; + + [self awaitExpectations]; +} + +- (void)testUpdateNestedFields { + FIRDocumentReference *doc = [self documentRef]; + + XCTestExpectation *expectation = [self expectationWithDescription:@"testUpdateNestedFields"]; + FIRWriteBatch *batch = [doc.firestore batch]; + [batch setData:@{@"a" : @{@"b" : @"old"}, @"c" : @{@"d" : @"old"}, @"e" : @{@"f" : @"old"}} + forDocument:doc]; + [batch + updateData:@{@"a.b" : @"new", [[FIRFieldPath alloc] initWithFields:@[ @"c", @"d" ]] : @"new"} + forDocument:doc]; + [batch commitWithCompletion:^(NSError *_Nullable error) { + XCTAssertNil(error); + [doc getDocumentWithCompletion:^(FIRDocumentSnapshot *snapshot, NSError *error) { + XCTAssertNil(error); + XCTAssertEqualObjects(snapshot.data, (@{ + @"a" : @{@"b" : @"new"}, + @"c" : @{@"d" : @"new"}, + @"e" : @{@"f" : @"old"} + })); + }]; + [expectation fulfill]; + }]; + + [self awaitExpectations]; +} + - (void)testDeleteDocuments { FIRDocumentReference *doc = [self documentRef]; [self writeDocumentRef:doc data:@{@"foo" : @"bar"}]; @@ -265,52 +311,6 @@ - (void)testCanWriteTheSameDocumentMultipleTimes { XCTAssertEqualObjects(serverSnap.data, (@{@"a" : @1, @"b" : @2, @"when" : when})); } -- (void)testUpdateFieldsWithDots { - FIRDocumentReference *doc = [self documentRef]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"testUpdateFieldsWithDots"]; - FIRWriteBatch *batch = [doc.firestore batch]; - [batch setData:@{@"a.b" : @"old", @"c.d" : @"old"} forDocument:doc]; - [batch updateData:@{[[FIRFieldPath alloc] initWithFields:@[ @"a.b" ]] : @"new"} forDocument:doc]; - - [batch commitWithCompletion:^(NSError *_Nullable error) { - XCTAssertNil(error); - [doc getDocumentWithCompletion:^(FIRDocumentSnapshot *snapshot, NSError *error) { - XCTAssertNil(error); - XCTAssertEqualObjects(snapshot.data, (@{@"a.b" : @"new", @"c.d" : @"old"})); - }]; - [expectation fulfill]; - }]; - - [self awaitExpectations]; -} - -- (void)testUpdateNestedFields { - FIRDocumentReference *doc = [self documentRef]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"testUpdateNestedFields"]; - FIRWriteBatch *batch = [doc.firestore batch]; - [batch setData:@{@"a" : @{@"b" : @"old"}, @"c" : @{@"d" : @"old"}, @"e" : @{@"f" : @"old"}} - forDocument:doc]; - [batch - updateData:@{@"a.b" : @"new", [[FIRFieldPath alloc] initWithFields:@[ @"c", @"d" ]] : @"new"} - forDocument:doc]; - [batch commitWithCompletion:^(NSError *_Nullable error) { - XCTAssertNil(error); - [doc getDocumentWithCompletion:^(FIRDocumentSnapshot *snapshot, NSError *error) { - XCTAssertNil(error); - XCTAssertEqualObjects(snapshot.data, (@{ - @"a" : @{@"b" : @"new"}, - @"c" : @{@"d" : @"new"}, - @"e" : @{@"f" : @"old"} - })); - }]; - [expectation fulfill]; - }]; - - [self awaitExpectations]; -} - // Returns how much memory the test application is currently using, in megabytes (fractional part is // truncated), or -1 if the OS call fails. // TODO(varconst): move the helper function and the test into a new test target for performance From 51da7c618f49a61e6cb9911ef5c9b4e7a67d9eaf Mon Sep 17 00:00:00 2001 From: Marek Gilbert Date: Mon, 28 Jan 2019 14:40:55 -0800 Subject: [PATCH 2/4] Add missing NS_ASSUME_NONNULL_BEGIN --- Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm b/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm index 7fd44572c0e..3584ffd0bac 100644 --- a/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm +++ b/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm @@ -24,6 +24,8 @@ #import "Firestore/Example/Tests/Util/FSTEventAccumulator.h" #import "Firestore/Example/Tests/Util/FSTIntegrationTestCase.h" +NS_ASSUME_NONNULL_BEGIN + @interface FIRWriteBatchTests : FSTIntegrationTestCase @end @@ -363,3 +365,5 @@ - (void)testReasonableMemoryUsageForLotsOfMutations { } @end + +NS_ASSUME_NONNULL_END From 888af16c27b81b14f1ed780b25b2b19f68927de1 Mon Sep 17 00:00:00 2001 From: Marek Gilbert Date: Mon, 28 Jan 2019 14:41:16 -0800 Subject: [PATCH 3/4] Add missing [self awaitExpectations] --- Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm b/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm index 3584ffd0bac..963363f05c4 100644 --- a/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm +++ b/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm @@ -209,6 +209,7 @@ - (void)testBatchesCommitAtomicallyRaisingCorrectEvents { XCTAssertNil(error); [expectation fulfill]; }]; + [self awaitExpectations]; FIRQuerySnapshot *localSnap = [accumulator awaitEventWithName:@"local event"]; XCTAssertTrue(localSnap.metadata.hasPendingWrites); @@ -240,6 +241,7 @@ - (void)testBatchesFailAtomicallyRaisingCorrectEvents { XCTAssertEqual(error.code, FIRFirestoreErrorCodeNotFound); [expectation fulfill]; }]; + [self awaitExpectations]; // Local event with the set document. FIRQuerySnapshot *localSnap = [accumulator awaitEventWithName:@"local event"]; @@ -271,6 +273,7 @@ - (void)testWriteTheSameServerTimestampAcrossWrites { XCTAssertNil(error); [expectation fulfill]; }]; + [self awaitExpectations]; FIRQuerySnapshot *localSnap = [accumulator awaitEventWithName:@"local event"]; XCTAssertTrue(localSnap.metadata.hasPendingWrites); @@ -302,6 +305,7 @@ - (void)testCanWriteTheSameDocumentMultipleTimes { XCTAssertNil(error); [expectation fulfill]; }]; + [self awaitExpectations]; FIRDocumentSnapshot *localSnap = [accumulator awaitEventWithName:@"local event"]; XCTAssertTrue(localSnap.metadata.hasPendingWrites); From 43d7543e45e8be151a227945cc37c8ad4edb4ebe Mon Sep 17 00:00:00 2001 From: Marek Gilbert Date: Mon, 28 Jan 2019 14:53:03 -0800 Subject: [PATCH 4/4] Port can write very large batches from Android --- .../Integration/API/FIRWriteBatchTests.mm | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm b/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm index 963363f05c4..7347e182e33 100644 --- a/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm +++ b/Firestore/Example/Tests/Integration/API/FIRWriteBatchTests.mm @@ -24,6 +24,12 @@ #import "Firestore/Example/Tests/Util/FSTEventAccumulator.h" #import "Firestore/Example/Tests/Util/FSTIntegrationTestCase.h" +#include "Firestore/core/src/firebase/firestore/util/autoid.h" +#include "Firestore/core/src/firebase/firestore/util/string_apple.h" + +using firebase::firestore::util::CreateAutoId; +using firebase::firestore::util::WrapNSString; + NS_ASSUME_NONNULL_BEGIN @interface FIRWriteBatchTests : FSTIntegrationTestCase @@ -317,6 +323,41 @@ - (void)testCanWriteTheSameDocumentMultipleTimes { XCTAssertEqualObjects(serverSnap.data, (@{@"a" : @1, @"b" : @2, @"when" : when})); } +- (void)testCanWriteVeryLargeBatches { + // On Android, SQLite Cursors are limited reading no more than 2 MB per row (despite being able + // to write very large values). This test verifies that the local MutationQueue is not subject + // to this limitation. + + // Create a map containing nearly 1 MB of data. Note that if you use 1024 below this will create + // a document larger than 1 MB, which will be rejected by the backend as too large. + NSString *kb = [@"" stringByPaddingToLength:1000 withString:@"a" startingAtIndex:0]; + NSMutableDictionary *values = [NSMutableDictionary dictionary]; + for (int i = 0; i < 1000; i++) { + values[WrapNSString(CreateAutoId())] = kb; + } + + FIRDocumentReference *doc = [self documentRef]; + FIRWriteBatch *batch = [doc.firestore batch]; + + // Write a batch containing 3 copies of the data, creating a ~3 MB batch. Writing to the same + // document in a batch is allowed and so long as the net size of the document is under 1 MB the + // batch is allowed. + [batch setData:values forDocument:doc]; + for (int i = 0; i < 2; i++) { + [batch updateData:values forDocument:doc]; + } + + XCTestExpectation *expectation = [self expectationWithDescription:@"batch written"]; + [batch commitWithCompletion:^(NSError *_Nullable error) { + XCTAssertNil(error); + [expectation fulfill]; + }]; + [self awaitExpectations]; + + FIRDocumentSnapshot *snap = [self readDocumentForRef:doc]; + XCTAssertEqualObjects(values, snap.data); +} + // Returns how much memory the test application is currently using, in megabytes (fractional part is // truncated), or -1 if the OS call fails. // TODO(varconst): move the helper function and the test into a new test target for performance