Skip to content

Commit 32edd5b

Browse files
committed
add integration test for raising initial snapshot from cached empty result
1 parent 301de89 commit 32edd5b

File tree

5 files changed

+65
-12
lines changed

5 files changed

+65
-12
lines changed

firebase-firestore/src/androidTest/java/com/google/firebase/firestore/QueryTest.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,50 @@ public void testQueriesFireFromCacheWhenOffline() {
550550
listener.remove();
551551
}
552552

553+
@Test
554+
public void testQueriesCanRaiseInitialSnapshotFromCachedEmptyResults() {
555+
CollectionReference collectionReference = testCollection();
556+
557+
// Populate the cache with empty query result.
558+
QuerySnapshot querySnapshotA = waitFor(collectionReference.get());
559+
assertFalse(querySnapshotA.getMetadata().isFromCache());
560+
assertEquals(asList(), querySnapshotToValues(querySnapshotA));
561+
562+
// Add a snapshot listener whose first event should be raised from cache.
563+
EventAccumulator<QuerySnapshot> accum = new EventAccumulator<>();
564+
ListenerRegistration listenerRegistration =
565+
collectionReference.addSnapshotListener(accum.listener());
566+
QuerySnapshot querySnapshotB = accum.await();
567+
assertTrue(querySnapshotB.getMetadata().isFromCache());
568+
assertEquals(asList(), querySnapshotToValues(querySnapshotB));
569+
570+
listenerRegistration.remove();
571+
}
572+
573+
@Test
574+
public void testQueriesCanRaiseInitialSnapshotFromEmptyDueToDeleteCachedResults() {
575+
Map<String, Map<String, Object>> testDocs = map("a", map("foo", 1L));
576+
CollectionReference collectionReference = testCollectionWithDocs(testDocs);
577+
// Populate the cache with single document.
578+
QuerySnapshot querySnapshotA = waitFor(collectionReference.get());
579+
assertFalse(querySnapshotA.getMetadata().isFromCache());
580+
assertEquals(asList(testDocs.get("a")), querySnapshotToValues(querySnapshotA));
581+
582+
// delete the document, make cached result empty.
583+
DocumentReference docRef = collectionReference.document("a");
584+
waitFor(docRef.delete());
585+
586+
// Add a snapshot listener whose first event should be raised from cache.
587+
EventAccumulator<QuerySnapshot> accum = new EventAccumulator<>();
588+
ListenerRegistration listenerRegistration =
589+
collectionReference.addSnapshotListener(accum.listener());
590+
QuerySnapshot querySnapshotB = accum.await();
591+
assertTrue(querySnapshotB.getMetadata().isFromCache());
592+
assertEquals(asList(), querySnapshotToValues(querySnapshotB));
593+
594+
listenerRegistration.remove();
595+
}
596+
553597
@Test
554598
public void testQueriesCanUseNotEqualFilters() {
555599
// These documents are ordered by value in "zip" since the notEquals filter is an inequality,

firebase-firestore/src/main/java/com/google/firebase/firestore/core/SyncEngine.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,11 @@ private ViewSnapshot initializeViewAndComputeSnapshot(
225225
if (this.queriesByTarget.get(targetId) != null) {
226226
Query mirrorQuery = this.queriesByTarget.get(targetId).get(0);
227227
currentTargetSyncState = this.queryViewsByQuery.get(mirrorQuery).getView().getSyncState();
228-
synthesizedCurrentChange =
229-
TargetChange.createSynthesizedTargetChangeForCurrentChange(
230-
currentTargetSyncState == SyncState.SYNCED, resumeToken);
231228
}
229+
;
230+
synthesizedCurrentChange =
231+
TargetChange.createSynthesizedTargetChangeForCurrentChange(
232+
currentTargetSyncState == SyncState.SYNCED, resumeToken);
232233

233234
// TODO(wuandy): Investigate if we can extract the logic of view change computation and
234235
// update tracked limbo in one place, and have both emitNewSnapsAndNotifyLocalStore

firebase-firestore/src/main/java/com/google/firebase/firestore/core/ViewSnapshot.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ public int hashCode() {
174174
result = 31 * result + (isFromCache ? 1 : 0);
175175
result = 31 * result + (didSyncStateChange ? 1 : 0);
176176
result = 31 * result + (excludesMetadataChanges ? 1 : 0);
177+
result = 31 * result + (hasCachedResults ? 1 : 0);
177178
return result;
178179
}
179180

firebase-firestore/src/roboUtil/java/com/google/firebase/firestore/TestUtil.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ public static QuerySnapshot querySnapshot(
8383
Map<String, ObjectValue> oldDocs,
8484
Map<String, ObjectValue> docsToAdd,
8585
boolean hasPendingWrites,
86-
boolean isFromCache) {
86+
boolean isFromCache,
87+
boolean hasCachedResults) {
8788
DocumentSet oldDocuments = docSet(Document.KEY_COMPARATOR);
8889
ImmutableSortedSet<DocumentKey> mutatedKeys = DocumentKey.emptyKeySet();
8990
for (Map.Entry<String, ObjectValue> pair : oldDocs.entrySet()) {
@@ -117,7 +118,7 @@ public static QuerySnapshot querySnapshot(
117118
mutatedKeys,
118119
/* didSyncStateChange= */ true,
119120
/* excludesMetadataChanges= */ false,
120-
/* hasCachedResults= */ false);
121+
hasCachedResults);
121122
return new QuerySnapshot(query(path), viewSnapshot, FIRESTORE);
122123
}
123124

firebase-firestore/src/test/java/com/google/firebase/firestore/QuerySnapshotTest.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,26 @@ public void testEquals() {
5656
ObjectValue firstValue = wrapObject("a", 1);
5757
ObjectValue secondValue = wrapObject("b", 1);
5858

59-
QuerySnapshot foo = TestUtil.querySnapshot("foo", map(), map("a", firstValue), true, false);
60-
QuerySnapshot fooDup = TestUtil.querySnapshot("foo", map(), map("a", firstValue), true, false);
59+
QuerySnapshot foo =
60+
TestUtil.querySnapshot("foo", map(), map("a", firstValue), true, false, false);
61+
QuerySnapshot fooDup =
62+
TestUtil.querySnapshot("foo", map(), map("a", firstValue), true, false, false);
6163
QuerySnapshot differentPath =
62-
TestUtil.querySnapshot("bar", map(), map("a", firstValue), true, false);
64+
TestUtil.querySnapshot("bar", map(), map("a", firstValue), true, false, false);
6365
QuerySnapshot differentDoc =
64-
TestUtil.querySnapshot("foo", map(), map("a", secondValue), true, false);
66+
TestUtil.querySnapshot("foo", map(), map("a", secondValue), true, false, false);
6567
QuerySnapshot noPendingWrites =
66-
TestUtil.querySnapshot("foo", map(), map("a", firstValue), false, false);
68+
TestUtil.querySnapshot("foo", map(), map("a", firstValue), false, false, false);
6769
QuerySnapshot fromCache =
68-
TestUtil.querySnapshot("foo", map(), map("a", firstValue), true, true);
70+
TestUtil.querySnapshot("foo", map(), map("a", firstValue), true, true, false);
71+
QuerySnapshot hasCachedResults =
72+
TestUtil.querySnapshot("foo", map(), map("a", firstValue), true, false, true);
6973
assertEquals(foo, fooDup);
7074
assertNotEquals(foo, differentPath);
7175
assertNotEquals(foo, differentDoc);
7276
assertNotEquals(foo, noPendingWrites);
7377
assertNotEquals(foo, fromCache);
78+
assertNotEquals(foo, hasCachedResults);
7479

7580
// Note: `foo` and `differentDoc` have the same hash code since we no longer take document
7681
// contents into account.
@@ -88,7 +93,8 @@ public void testToObjects() {
8893

8994
ObjectValue objectData =
9095
ObjectValue.fromMap(map("timestamp", ServerTimestamps.valueOf(Timestamp.now(), null)));
91-
QuerySnapshot foo = TestUtil.querySnapshot("foo", map(), map("a", objectData), true, false);
96+
QuerySnapshot foo =
97+
TestUtil.querySnapshot("foo", map(), map("a", objectData), true, false, false);
9298

9399
List<POJO> docs = foo.toObjects(POJO.class);
94100
assertEquals(1, docs.size());

0 commit comments

Comments
 (0)