Skip to content

Commit 6c23083

Browse files
Adding test
1 parent 1e6792f commit 6c23083

File tree

4 files changed

+91
-10
lines changed

4 files changed

+91
-10
lines changed

firebase-firestore/src/main/java/com/google/firebase/firestore/local/SQLitePersistence.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public static String databaseName(String persistenceKey, DatabaseId databaseId)
7777
}
7878
}
7979

80-
private final OpenHelper opener;
80+
private final SQLiteOpenHelper opener;
8181
private final LocalSerializer serializer;
8282
private final StatsCollector statsCollector;
8383
private final SQLiteQueryCache queryCache;
@@ -125,8 +125,19 @@ public SQLitePersistence(
125125
LocalSerializer serializer,
126126
StatsCollector statsCollector,
127127
LruGarbageCollector.Params params) {
128-
String databaseName = databaseName(persistenceKey, databaseId);
129-
this.opener = new OpenHelper(context, databaseName);
128+
this(
129+
serializer,
130+
statsCollector,
131+
params,
132+
new OpenHelper(context, databaseName(persistenceKey, databaseId)));
133+
}
134+
135+
public SQLitePersistence(
136+
LocalSerializer serializer,
137+
StatsCollector statsCollector,
138+
LruGarbageCollector.Params params,
139+
SQLiteOpenHelper openHelper) {
140+
this.opener = openHelper;
130141
this.serializer = serializer;
131142
this.statsCollector = statsCollector;
132143
this.queryCache = new SQLiteQueryCache(this, this.serializer);

firebase-firestore/src/main/java/com/google/firebase/firestore/local/SQLiteRemoteDocumentCache.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public ImmutableSortedMap<DocumentKey, Document> getAllDocumentsMatchingQuery(
147147

148148
String prefixPath = EncodedPath.encode(prefix);
149149
String prefixSuccessorPath = EncodedPath.prefixSuccessor(prefixPath);
150-
Timestamp updateTime = sinceReadTime.getTimestamp();
150+
Timestamp readTime = sinceReadTime.getTimestamp();
151151

152152
BackgroundQueue backgroundQueue = new BackgroundQueue();
153153

@@ -163,9 +163,9 @@ public ImmutableSortedMap<DocumentKey, Document> getAllDocumentsMatchingQuery(
163163
.binding(
164164
prefixPath,
165165
prefixSuccessorPath,
166-
updateTime.getSeconds(),
167-
updateTime.getSeconds(),
168-
updateTime.getNanoseconds())
166+
readTime.getSeconds(),
167+
readTime.getSeconds(),
168+
readTime.getNanoseconds())
169169
.forEach(
170170
row -> {
171171
// TODO: Actually implement a single-collection query

firebase-firestore/src/main/java/com/google/firebase/firestore/local/SQLiteSchema.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ class SQLiteSchema {
4646
* The version of the schema. Increase this by one for each migration added to runMigrations
4747
* below.
4848
*
49-
* <p>TODO(index-free): The migration to schema version 9 doesn't backfill `update_time` as this
49+
* <p>TODO(index-free): The migration to schema version 9 doesn't backfill `read_time` as this
5050
* requires rewriting the RemoteDocumentCache. For index-free queries to efficiently handle
51-
* existing documents, we still need to populate update_time for all existing entries, drop the
51+
* existing documents, we still need to populate read_time for all existing entries, drop the
5252
* RemoteDocumentCache or ask users to invoke `clearPersistence()` manually. If we decide to
5353
* backfill or drop the contents of the RemoteDocumentCache, we need to perform an additional
5454
* schema migration.

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

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616

1717
import static com.google.firebase.firestore.local.EncodedPath.decodeResourcePath;
1818
import static com.google.firebase.firestore.local.EncodedPath.encode;
19+
import static com.google.firebase.firestore.testutil.TestUtil.key;
1920
import static com.google.firebase.firestore.testutil.TestUtil.map;
2021
import static com.google.firebase.firestore.testutil.TestUtil.path;
22+
import static com.google.firebase.firestore.testutil.TestUtil.query;
23+
import static com.google.firebase.firestore.testutil.TestUtil.version;
2124
import static java.util.Arrays.asList;
2225
import static org.junit.Assert.assertEquals;
2326
import static org.junit.Assert.assertFalse;
@@ -28,9 +31,13 @@
2831
import android.database.sqlite.SQLiteDatabase;
2932
import android.database.sqlite.SQLiteOpenHelper;
3033
import androidx.test.core.app.ApplicationProvider;
34+
import com.google.firebase.database.collection.ImmutableSortedMap;
3135
import com.google.firebase.firestore.model.DatabaseId;
36+
import com.google.firebase.firestore.model.DocumentKey;
3237
import com.google.firebase.firestore.model.ResourcePath;
38+
import com.google.firebase.firestore.proto.MaybeDocument;
3339
import com.google.firebase.firestore.proto.WriteBatch;
40+
import com.google.firebase.firestore.remote.RemoteSerializer;
3441
import com.google.firestore.v1.Document;
3542
import com.google.firestore.v1.Write;
3643
import java.util.ArrayList;
@@ -55,10 +62,11 @@ public class SQLiteSchemaTest {
5562

5663
private SQLiteDatabase db;
5764
private SQLiteSchema schema;
65+
private SQLiteOpenHelper opener;
5866

5967
@Before
6068
public void setUp() {
61-
SQLiteOpenHelper opener =
69+
opener =
6270
new SQLiteOpenHelper(ApplicationProvider.getApplicationContext(), "foo", null, 1) {
6371
@Override
6472
public void onCreate(SQLiteDatabase db) {}
@@ -394,6 +402,68 @@ public void canCreateCollectionParentsIndex() {
394402
assertEquals(expectedParents, actualParents);
395403
}
396404

405+
@Test
406+
public void existingDocumentsRemainReadableAfterIndexFreeMigration() {
407+
// Initialize the schema to the state prior to the index-free migration.
408+
schema.runMigrations(0, 8);
409+
db.execSQL(
410+
"INSERT INTO remote_documents (path, contents) VALUES (?, ?)",
411+
new Object[] {encode(path("coll/existing")), createDummyDocument("coll/existing")});
412+
413+
// Run the index-free migration.
414+
schema.runMigrations(8, 9);
415+
db.execSQL(
416+
"INSERT INTO remote_documents (path, read_time_seconds, read_time_nanos, contents) VALUES (?, ?, ?, ?)",
417+
new Object[] {encode(path("coll/old")), 0, 1000, createDummyDocument("coll/old")});
418+
db.execSQL(
419+
"INSERT INTO remote_documents (path, read_time_seconds, read_time_nanos, contents) VALUES (?, ?, ?, ?)",
420+
new Object[] {encode(path("coll/current")), 0, 2000, createDummyDocument("coll/current")});
421+
db.execSQL(
422+
"INSERT INTO remote_documents (path, read_time_seconds, read_time_nanos, contents) VALUES (?, ?, ?, ?)",
423+
new Object[] {encode(path("coll/new")), 0, 3000, createDummyDocument("coll/new")});
424+
425+
SQLiteRemoteDocumentCache remoteDocumentCache = createRemoteDocumentCache();
426+
ImmutableSortedMap<DocumentKey, com.google.firebase.firestore.model.Document> results =
427+
remoteDocumentCache.getAllDocumentsMatchingQuery(query("coll"), version(2));
428+
429+
// Verify that queries return the documents that existed prior to the index-free migration, as
430+
// well as any documents with a newer read time than the one passed in.
431+
assertResultsContain(results, "coll/existing", "coll/new");
432+
}
433+
434+
private SQLiteRemoteDocumentCache createRemoteDocumentCache() {
435+
DatabaseId databaseId = DatabaseId.forProject("foo");
436+
LocalSerializer serializer = new LocalSerializer(new RemoteSerializer(databaseId));
437+
SQLitePersistence persistence =
438+
new SQLitePersistence(
439+
serializer,
440+
StatsCollector.NO_OP_STATS_COLLECTOR,
441+
LruGarbageCollector.Params.Default(),
442+
opener);
443+
persistence.start();
444+
return new SQLiteRemoteDocumentCache(
445+
persistence, serializer, StatsCollector.NO_OP_STATS_COLLECTOR);
446+
}
447+
448+
private byte[] createDummyDocument(String name) {
449+
return MaybeDocument.newBuilder()
450+
.setDocument(
451+
Document.newBuilder()
452+
.setName("projects/foo/databases/(default)/documents/" + name)
453+
.build())
454+
.build()
455+
.toByteArray();
456+
}
457+
458+
private void assertResultsContain(
459+
ImmutableSortedMap<DocumentKey, com.google.firebase.firestore.model.Document> actualResults,
460+
String... docs) {
461+
for (String doc : docs) {
462+
assertTrue("Expected result for " + doc, actualResults.containsKey(key(doc)));
463+
}
464+
assertEquals("Results contain unexpected entries", docs.length, actualResults.size());
465+
}
466+
397467
private void assertNoResultsForQuery(String query, String[] args) {
398468
Cursor cursor = null;
399469
try {

0 commit comments

Comments
 (0)