Skip to content

Commit 54a9c86

Browse files
committed
SQLiteLocalStoreTest.java: add tests
1 parent 8298296 commit 54a9c86

File tree

2 files changed

+99
-1
lines changed

2 files changed

+99
-1
lines changed

firebase-firestore/src/test/java/com/google/firebase/firestore/local/SQLiteLocalStoreTest.java

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package com.google.firebase.firestore.local;
1616

1717
import static com.google.common.truth.Truth.assertThat;
18+
import static com.google.common.truth.Truth.assertWithMessage;
1819
import static com.google.firebase.firestore.testutil.TestUtil.addedRemoteEvent;
1920
import static com.google.firebase.firestore.testutil.TestUtil.deleteMutation;
2021
import static com.google.firebase.firestore.testutil.TestUtil.deletedDoc;
@@ -27,6 +28,7 @@
2728
import static com.google.firebase.firestore.testutil.TestUtil.orFilters;
2829
import static com.google.firebase.firestore.testutil.TestUtil.orderBy;
2930
import static com.google.firebase.firestore.testutil.TestUtil.query;
31+
import static com.google.firebase.firestore.testutil.TestUtil.removedRemoteEvent;
3032
import static com.google.firebase.firestore.testutil.TestUtil.setMutation;
3133
import static com.google.firebase.firestore.testutil.TestUtil.updateRemoteEvent;
3234
import static com.google.firebase.firestore.testutil.TestUtil.version;
@@ -39,7 +41,9 @@
3941
import com.google.firebase.firestore.model.DocumentKey;
4042
import com.google.firebase.firestore.model.FieldIndex;
4143
import com.google.firebase.firestore.model.FieldPath;
44+
import com.google.firebase.firestore.model.MutableDocument;
4245
import com.google.firebase.firestore.model.ObjectValue;
46+
import com.google.firebase.firestore.model.ResourcePath;
4347
import com.google.firebase.firestore.model.ServerTimestamps;
4448
import com.google.firebase.firestore.model.mutation.FieldMask;
4549
import com.google.firebase.firestore.model.mutation.FieldTransform;
@@ -64,9 +68,16 @@
6468
@RunWith(RobolectricTestRunner.class)
6569
@Config(manifest = Config.NONE)
6670
public class SQLiteLocalStoreTest extends LocalStoreTestCase {
71+
72+
private final AtomicReference<SQLitePersistence> sqlitePersistence = new AtomicReference<>();
73+
6774
@Override
6875
Persistence getPersistence() {
69-
return PersistenceTestHelpers.createSQLitePersistence();
76+
SQLitePersistence sqlitePersistence = PersistenceTestHelpers.createSQLitePersistence();
77+
if (!this.sqlitePersistence.compareAndSet(null, sqlitePersistence)) {
78+
throw new RuntimeException("getPersistence() has already been called [error code qvw3g9kns]");
79+
}
80+
return sqlitePersistence;
7081
}
7182

7283
@Override
@@ -816,4 +827,78 @@ public void testIndexAutoCreationDoesnotWorkWithMultipleInequality() {
816827
assertRemoteDocumentsRead(/* byKey= */ 0, /* byCollection= */ 2);
817828
assertQueryReturned("coll/a", "coll/e");
818829
}
830+
831+
@Test
832+
public void testDocumentTypeIsSetWhenDocumentedAdded() {
833+
Query query = query("coll");
834+
int targetId = allocateQuery(query);
835+
MutableDocument doc = doc("coll/a", 10, map("foo", 42));
836+
837+
applyRemoteEvent(addedRemoteEvent(doc, targetId));
838+
839+
Map<ResourcePath, Integer> expected = new HashMap<>();
840+
expected.put(doc.getKey().getPath(), 2); // 2 is a "found" document
841+
assertThat(getDocumentTypeByPathFromRemoteDocumentsTable()).containsExactlyEntriesIn(expected);
842+
}
843+
844+
@Test
845+
public void testDocumentTypeIsUpdatedWhenDocumentedDeleted() {
846+
Query query = query("coll");
847+
int targetId = allocateQuery(query);
848+
MutableDocument doc = doc("coll/a", 10, map("foo", 42));
849+
applyRemoteEvent(addedRemoteEvent(doc, targetId));
850+
851+
applyRemoteEvent(removedRemoteEvent(doc.getKey(), 11, targetId));
852+
853+
Map<ResourcePath, Integer> expected = new HashMap<>();
854+
expected.put(doc.getKey().getPath(), 1); // 1 is a "no" document
855+
assertThat(getDocumentTypeByPathFromRemoteDocumentsTable()).containsExactlyEntriesIn(expected);
856+
}
857+
858+
@Test
859+
public void testDocumentTypeColumnIsBackfilledByQuery() {
860+
Query query = query("coll");
861+
int targetId = allocateQuery(query);
862+
MutableDocument existingDoc = doc("coll/a", 10, map("foo", 42));
863+
applyRemoteEvent(addedRemoteEvent(existingDoc, targetId));
864+
MutableDocument deletedDoc = doc("coll/b", 10, map("foo", 42));
865+
applyRemoteEvent(addedRemoteEvent(deletedDoc, targetId));
866+
applyRemoteEvent(removedRemoteEvent(deletedDoc.getKey(), 11, targetId));
867+
SQLitePersistence persistence = this.sqlitePersistence.get();
868+
persistence.execute("UPDATE remote_documents SET document_type = NULL");
869+
assertWithMessage("precondition check: all rows have null document type")
870+
.that(getDocumentTypeByPathFromRemoteDocumentsTable().values())
871+
.containsExactly(null, null);
872+
873+
executeQuery(query);
874+
875+
Map<ResourcePath, Integer> expected = new HashMap<>();
876+
expected.put(existingDoc.getKey().getPath(), 2); // 2 is a "found" document
877+
expected.put(deletedDoc.getKey().getPath(), 1); // 1 is a "no" document
878+
assertThat(getDocumentTypeByPathFromRemoteDocumentsTable()).containsExactlyEntriesIn(expected);
879+
}
880+
881+
/**
882+
* Scans the entire "remote documents" sqlite table and returns the value of the "document type"
883+
* column for each row, keyed by the value of the "path" column of the corresponding row. Note
884+
* that the values of the returned map may be `null`, if the column value for that row is null.
885+
*/
886+
private Map<ResourcePath, Integer> getDocumentTypeByPathFromRemoteDocumentsTable() {
887+
HashMap<ResourcePath, Integer> documentTypeByPath = new HashMap<>();
888+
sqlitePersistence
889+
.get()
890+
.query("SELECT path, document_type FROM remote_documents")
891+
.forEach(
892+
row -> {
893+
String encodedPath = row.getString(0);
894+
ResourcePath path = EncodedPath.decodeResourcePath(encodedPath);
895+
Integer documentType = row.isNull(1) ? null : row.getInt(1);
896+
synchronized (documentTypeByPath) {
897+
documentTypeByPath.put(path, documentType);
898+
}
899+
});
900+
synchronized (documentTypeByPath) {
901+
return documentTypeByPath;
902+
}
903+
}
819904
}

firebase-firestore/src/testUtil/java/com/google/firebase/firestore/testutil/TestUtil.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,19 @@ public TargetData getTargetDataForTarget(int targetId) {
545545
return aggregator.createRemoteEvent(doc.getVersion());
546546
}
547547

548+
public static RemoteEvent removedRemoteEvent(DocumentKey key, int version, Integer targetId) {
549+
return removedRemoteEvent(key, version(version), targetId);
550+
}
551+
552+
public static RemoteEvent removedRemoteEvent(
553+
DocumentKey key, SnapshotVersion version, Integer targetId) {
554+
return removedRemoteEvent(MutableDocument.newNoDocument(key, version), targetId);
555+
}
556+
557+
public static RemoteEvent removedRemoteEvent(MutableDocument doc, Integer targetId) {
558+
return addedRemoteEvent(singletonList(doc), emptyList(), singletonList(targetId));
559+
}
560+
548561
public static SetMutation setMutation(String path, Map<String, Object> values) {
549562
UserDataReader dataReader = new UserDataReader(TEST_PROJECT);
550563
ParsedSetData parsed = dataReader.parseSetData(values);

0 commit comments

Comments
 (0)