|
20 | 20 | #include <string>
|
21 | 21 | #include <vector>
|
22 | 22 |
|
| 23 | +#import "Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h" |
23 | 24 | #import "Firestore/Protos/objc/firestore/local/Target.pbobjc.h"
|
24 | 25 | #import "Firestore/Source/Local/FSTLevelDB.h"
|
25 | 26 | #import "Firestore/Source/Local/FSTLevelDBMutationQueue.h"
|
26 | 27 | #import "Firestore/Source/Local/FSTLevelDBQueryCache.h"
|
27 | 28 |
|
28 | 29 | #include "Firestore/core/src/firebase/firestore/local/leveldb_key.h"
|
29 | 30 | #include "Firestore/core/src/firebase/firestore/local/leveldb_migrations.h"
|
| 31 | +#include "Firestore/core/src/firebase/firestore/model/document_key.h" |
30 | 32 | #include "Firestore/core/src/firebase/firestore/util/ordered_code.h"
|
31 | 33 | #include "Firestore/core/src/firebase/firestore/util/status.h"
|
32 | 34 | #include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
|
|
38 | 40 | NS_ASSUME_NONNULL_BEGIN
|
39 | 41 |
|
40 | 42 | using firebase::firestore::FirestoreErrorCode;
|
| 43 | +using firebase::firestore::local::LevelDbDocumentMutationKey; |
41 | 44 | using firebase::firestore::local::LevelDbDocumentTargetKey;
|
42 | 45 | using firebase::firestore::local::LevelDbMigrations;
|
43 | 46 | using firebase::firestore::local::LevelDbMutationKey;
|
|
47 | 50 | using firebase::firestore::local::LevelDbTargetKey;
|
48 | 51 | using firebase::firestore::local::LevelDbTransaction;
|
49 | 52 | using firebase::firestore::model::BatchId;
|
| 53 | +using firebase::firestore::model::DocumentKey; |
50 | 54 | using firebase::firestore::model::TargetId;
|
51 | 55 | using firebase::firestore::testutil::Key;
|
52 | 56 | using firebase::firestore::util::OrderedCode;
|
@@ -199,6 +203,111 @@ - (void)testDropsTheQueryCacheWithThousandsOfEntries {
|
199 | 203 | }
|
200 | 204 | }
|
201 | 205 |
|
| 206 | +- (void)testRemovesMutationBatches { |
| 207 | + std::string emptyBuffer; |
| 208 | + DocumentKey testWriteFoo = DocumentKey::FromPathString("docs/foo"); |
| 209 | + DocumentKey testWriteBar = DocumentKey::FromPathString("docs/bar"); |
| 210 | + DocumentKey testWriteBaz = DocumentKey::FromPathString("docs/baz"); |
| 211 | + DocumentKey testWritePending = DocumentKey::FromPathString("docs/pending"); |
| 212 | + // Do everything up until the mutation batch migration. |
| 213 | + LevelDbMigrations::RunMigrations(_db.get(), 3); |
| 214 | + // Set up data |
| 215 | + { |
| 216 | + LevelDbTransaction transaction(_db.get(), "Setup Foo"); |
| 217 | + // User 'foo' has two acknowledged mutations and one that is pending. |
| 218 | + FSTPBMutationQueue *fooQueue = [[FSTPBMutationQueue alloc] init]; |
| 219 | + fooQueue.lastAcknowledgedBatchId = 2; |
| 220 | + std::string fooKey = LevelDbMutationQueueKey::Key("foo"); |
| 221 | + transaction.Put(fooKey, fooQueue); |
| 222 | + |
| 223 | + FSTPBWriteBatch *fooBatch1 = [[FSTPBWriteBatch alloc] init]; |
| 224 | + fooBatch1.batchId = 1; |
| 225 | + std::string fooBatchKey1 = LevelDbMutationKey::Key("foo", 1); |
| 226 | + transaction.Put(fooBatchKey1, fooBatch1); |
| 227 | + transaction.Put(LevelDbDocumentMutationKey::Key("foo", testWriteFoo, 1), emptyBuffer); |
| 228 | + |
| 229 | + FSTPBWriteBatch *fooBatch2 = [[FSTPBWriteBatch alloc] init]; |
| 230 | + fooBatch2.batchId = 2; |
| 231 | + std::string fooBatchKey2 = LevelDbMutationKey::Key("foo", 2); |
| 232 | + transaction.Put(fooBatchKey2, fooBatch2); |
| 233 | + transaction.Put(LevelDbDocumentMutationKey::Key("foo", testWriteFoo, 2), emptyBuffer); |
| 234 | + |
| 235 | + FSTPBWriteBatch *fooBatch3 = [[FSTPBWriteBatch alloc] init]; |
| 236 | + fooBatch3.batchId = 5; |
| 237 | + std::string fooBatchKey3 = LevelDbMutationKey::Key("foo", 5); |
| 238 | + transaction.Put(fooBatchKey3, fooBatch3); |
| 239 | + transaction.Put(LevelDbDocumentMutationKey::Key("foo", testWritePending, 5), emptyBuffer); |
| 240 | + |
| 241 | + transaction.Commit(); |
| 242 | + } |
| 243 | + |
| 244 | + { |
| 245 | + LevelDbTransaction transaction(_db.get(), "Setup Bar"); |
| 246 | + // User 'bar' has one acknowledged mutation and one that is pending |
| 247 | + FSTPBMutationQueue *barQueue = [[FSTPBMutationQueue alloc] init]; |
| 248 | + barQueue.lastAcknowledgedBatchId = 3; |
| 249 | + std::string barKey = LevelDbMutationQueueKey::Key("bar"); |
| 250 | + transaction.Put(barKey, barQueue); |
| 251 | + |
| 252 | + FSTPBWriteBatch *barBatch1 = [[FSTPBWriteBatch alloc] init]; |
| 253 | + barBatch1.batchId = 3; |
| 254 | + std::string barBatchKey1 = LevelDbMutationKey::Key("bar", 3); |
| 255 | + transaction.Put(barBatchKey1, barBatch1); |
| 256 | + transaction.Put(LevelDbDocumentMutationKey::Key("bar", testWriteBar, 3), emptyBuffer); |
| 257 | + transaction.Put(LevelDbDocumentMutationKey::Key("bar", testWriteBaz, 3), emptyBuffer); |
| 258 | + |
| 259 | + FSTPBWriteBatch *barBatch2 = [[FSTPBWriteBatch alloc] init]; |
| 260 | + barBatch2.batchId = 4; |
| 261 | + std::string barBatchKey2 = LevelDbMutationKey::Key("bar", 4); |
| 262 | + transaction.Put(barBatchKey2, barBatch2); |
| 263 | + transaction.Put(LevelDbDocumentMutationKey::Key("bar", testWritePending, 4), emptyBuffer); |
| 264 | + |
| 265 | + transaction.Commit(); |
| 266 | + } |
| 267 | + |
| 268 | + { |
| 269 | + LevelDbTransaction transaction(_db.get(), "Setup Empty"); |
| 270 | + // User 'empty' has no mutations |
| 271 | + FSTPBMutationQueue *emptyQueue = [[FSTPBMutationQueue alloc] init]; |
| 272 | + emptyQueue.lastAcknowledgedBatchId = -1; |
| 273 | + std::string emptyKey = LevelDbMutationQueueKey::Key("empty"); |
| 274 | + transaction.Put(emptyKey, emptyQueue); |
| 275 | + |
| 276 | + transaction.Commit(); |
| 277 | + } |
| 278 | + |
| 279 | + LevelDbMigrations::RunMigrations(_db.get(), 4); |
| 280 | + |
| 281 | + { |
| 282 | + // Verify |
| 283 | + std::string buffer; |
| 284 | + LevelDbTransaction transaction(_db.get(), "Verify"); |
| 285 | + auto it = transaction.NewIterator(); |
| 286 | + // verify that we deleted the correct batches |
| 287 | + XCTAssertTrue(transaction.Get(LevelDbMutationKey::Key("foo", 1), &buffer).IsNotFound()); |
| 288 | + XCTAssertTrue(transaction.Get(LevelDbMutationKey::Key("foo", 2), &buffer).IsNotFound()); |
| 289 | + XCTAssertTrue(transaction.Get(LevelDbMutationKey::Key("foo", 5), &buffer).ok()); |
| 290 | + |
| 291 | + XCTAssertTrue(transaction.Get(LevelDbMutationKey::Key("bar", 3), &buffer).IsNotFound()); |
| 292 | + XCTAssertTrue(transaction.Get(LevelDbMutationKey::Key("bar", 4), &buffer).ok()); |
| 293 | + |
| 294 | + // verify document associations have been removed |
| 295 | + XCTAssertTrue(transaction.Get(LevelDbDocumentMutationKey::Key("foo", testWriteFoo, 1), &buffer) |
| 296 | + .IsNotFound()); |
| 297 | + XCTAssertTrue(transaction.Get(LevelDbDocumentMutationKey::Key("foo", testWriteFoo, 2), &buffer) |
| 298 | + .IsNotFound()); |
| 299 | + XCTAssertTrue( |
| 300 | + transaction.Get(LevelDbDocumentMutationKey::Key("foo", testWritePending, 5), &buffer).ok()); |
| 301 | + |
| 302 | + XCTAssertTrue(transaction.Get(LevelDbDocumentMutationKey::Key("bar", testWriteBar, 3), &buffer) |
| 303 | + .IsNotFound()); |
| 304 | + XCTAssertTrue(transaction.Get(LevelDbDocumentMutationKey::Key("bar", testWriteBaz, 3), &buffer) |
| 305 | + .IsNotFound()); |
| 306 | + XCTAssertTrue( |
| 307 | + transaction.Get(LevelDbDocumentMutationKey::Key("bar", testWritePending, 4), &buffer).ok()); |
| 308 | + } |
| 309 | +} |
| 310 | + |
202 | 311 | /**
|
203 | 312 | * Creates the name of a dummy entry to make sure the iteration is correctly bounded.
|
204 | 313 | */
|
|
0 commit comments