aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm
diff options
context:
space:
mode:
Diffstat (limited to 'Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm')
-rw-r--r--Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm158
1 files changed, 158 insertions, 0 deletions
diff --git a/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm b/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm
new file mode 100644
index 0000000..1e66aac
--- /dev/null
+++ b/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm
@@ -0,0 +1,158 @@
+/*
+ * 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 "Local/FSTLevelDBMutationQueue.h"
+
+#import <XCTest/XCTest.h>
+#include <leveldb/db.h>
+
+#import "Protos/objc/firestore/local/Mutation.pbobjc.h"
+#import "Auth/FSTUser.h"
+#import "Local/FSTLevelDB.h"
+#import "Local/FSTLevelDBKey.h"
+#import "Local/FSTWriteGroup.h"
+#include "Port/ordered_code.h"
+
+#import "FSTMutationQueueTests.h"
+#import "FSTPersistenceTestHelpers.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+using leveldb::DB;
+using leveldb::Slice;
+using leveldb::Status;
+using leveldb::WriteOptions;
+using Firestore::StringView;
+using Firestore::OrderedCode;
+
+// A dummy mutation value, useful for testing code that's known to examine only mutation keys.
+static const char *kDummy = "1";
+
+/**
+ * Most of the tests for FSTLevelDBMutationQueue are performed on the FSTMutationQueue protocol in
+ * FSTMutationQueueTests. This class is responsible for setting up the @a mutationQueue plus any
+ * additional LevelDB-specific tests.
+ */
+@interface FSTLevelDBMutationQueueTests : FSTMutationQueueTests
+@end
+
+/**
+ * Creates a key that's structurally the same as FSTLevelDBMutationKey except it allows for
+ * nonstandard table names.
+ */
+std::string MutationLikeKey(StringView table, StringView userID, FSTBatchID batchID) {
+ std::string key;
+ OrderedCode::WriteString(&key, table);
+ OrderedCode::WriteString(&key, userID);
+ OrderedCode::WriteSignedNumIncreasing(&key, batchID);
+ return key;
+}
+
+@implementation FSTLevelDBMutationQueueTests {
+ FSTLevelDB *_db;
+}
+
+- (void)setUp {
+ [super setUp];
+ _db = [FSTPersistenceTestHelpers levelDBPersistence];
+ self.mutationQueue = [_db mutationQueueForUser:[[FSTUser alloc] initWithUID:@"user"]];
+ self.persistence = _db;
+
+ FSTWriteGroup *group = [self.persistence startGroupWithAction:@"Start MutationQueue"];
+ [self.mutationQueue startWithGroup:group];
+ [self.persistence commitGroup:group];
+}
+
+- (void)testLoadNextBatchID_zeroWhenTotallyEmpty {
+ // Initial seek is invalid
+ XCTAssertEqual([FSTLevelDBMutationQueue loadNextBatchIDFromDB:_db.ptr], 0);
+}
+
+- (void)testLoadNextBatchID_zeroWhenNoMutations {
+ // Initial seek finds no mutations
+ [self setDummyValueForKey:MutationLikeKey("mutationr", "foo", 20)];
+ [self setDummyValueForKey:MutationLikeKey("mutationsa", "foo", 10)];
+ XCTAssertEqual([FSTLevelDBMutationQueue loadNextBatchIDFromDB:_db.ptr], 0);
+}
+
+- (void)testLoadNextBatchID_findsSingleRow {
+ // Seeks off the end of the table altogether
+ [self setDummyValueForKey:[FSTLevelDBMutationKey keyWithUserID:@"foo" batchID:6]];
+
+ XCTAssertEqual([FSTLevelDBMutationQueue loadNextBatchIDFromDB:_db.ptr], 7);
+}
+
+- (void)testLoadNextBatchID_findsSingleRowAmongNonMutations {
+ // Seeks into table following mutations.
+ [self setDummyValueForKey:[FSTLevelDBMutationKey keyWithUserID:@"foo" batchID:6]];
+ [self setDummyValueForKey:MutationLikeKey("mutationsa", "foo", 10)];
+
+ XCTAssertEqual([FSTLevelDBMutationQueue loadNextBatchIDFromDB:_db.ptr], 7);
+}
+
+- (void)testLoadNextBatchID_findsMaxAcrossUsers {
+ [self setDummyValueForKey:[FSTLevelDBMutationKey keyWithUserID:@"fo" batchID:5]];
+ [self setDummyValueForKey:[FSTLevelDBMutationKey keyWithUserID:@"food" batchID:3]];
+
+ [self setDummyValueForKey:[FSTLevelDBMutationKey keyWithUserID:@"foo" batchID:6]];
+ [self setDummyValueForKey:[FSTLevelDBMutationKey keyWithUserID:@"foo" batchID:2]];
+ [self setDummyValueForKey:[FSTLevelDBMutationKey keyWithUserID:@"foo" batchID:1]];
+
+ XCTAssertEqual([FSTLevelDBMutationQueue loadNextBatchIDFromDB:_db.ptr], 7);
+}
+
+- (void)testLoadNextBatchID_onlyFindsMutations {
+ // Write higher-valued batchIDs in nearby "tables"
+ auto tables = @[ @"mutatio", @"mutationsa", @"bears", @"zombies" ];
+ FSTBatchID highBatchID = 5;
+ for (NSString *table in tables) {
+ [self setDummyValueForKey:MutationLikeKey(table, "", highBatchID++)];
+ }
+
+ [self setDummyValueForKey:[FSTLevelDBMutationKey keyWithUserID:@"bar" batchID:3]];
+ [self setDummyValueForKey:[FSTLevelDBMutationKey keyWithUserID:@"bar" batchID:2]];
+ [self setDummyValueForKey:[FSTLevelDBMutationKey keyWithUserID:@"foo" batchID:1]];
+
+ // None of the higher tables should match -- this is the only entry that's in the mutations
+ // table
+ XCTAssertEqual([FSTLevelDBMutationQueue loadNextBatchIDFromDB:_db.ptr], 4);
+}
+
+- (void)testEmptyProtoCanBeUpgraded {
+ // An empty protocol buffer serializes to a zero-length byte buffer.
+ GPBEmpty *empty = [GPBEmpty message];
+ NSData *emptyData = [empty data];
+ XCTAssertEqual(emptyData.length, 0);
+
+ // Choose some other (arbitrary) proto and parse it from the empty message and it should all be
+ // defaults. This shows that empty proto values within the index row value don't pose any future
+ // liability.
+ NSError *error;
+ FSTPBMutationQueue *parsedMessage = [FSTPBMutationQueue parseFromData:emptyData error:&error];
+ XCTAssertNil(error);
+
+ FSTPBMutationQueue *defaultMessage = [FSTPBMutationQueue message];
+ XCTAssertEqual(parsedMessage.lastAcknowledgedBatchId, defaultMessage.lastAcknowledgedBatchId);
+ XCTAssertEqualObjects(parsedMessage.lastStreamToken, defaultMessage.lastStreamToken);
+}
+
+- (void)setDummyValueForKey:(const std::string &)key {
+ _db.ptr->Put(WriteOptions(), key, kDummy);
+}
+
+@end
+
+NS_ASSUME_NONNULL_END