Skip to content

Commit 47e7a88

Browse files
authored
Firestore: QueryTest.java: add a test that resumes a query with existence filter (#4799)
1 parent c989076 commit 47e7a88

File tree

2 files changed

+91
-1
lines changed

2 files changed

+91
-1
lines changed

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

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package com.google.firebase.firestore;
1616

17+
import static com.google.common.truth.Truth.assertWithMessage;
1718
import static com.google.firebase.firestore.testutil.IntegrationTestUtil.isRunningAgainstEmulator;
1819
import static com.google.firebase.firestore.testutil.IntegrationTestUtil.nullList;
1920
import static com.google.firebase.firestore.testutil.IntegrationTestUtil.querySnapshotToIds;
@@ -39,6 +40,8 @@
3940
import com.google.firebase.firestore.testutil.EventAccumulator;
4041
import com.google.firebase.firestore.testutil.IntegrationTestUtil;
4142
import java.util.ArrayList;
43+
import java.util.HashMap;
44+
import java.util.HashSet;
4245
import java.util.LinkedHashMap;
4346
import java.util.List;
4447
import java.util.Map;
@@ -1030,6 +1033,73 @@ public void testMultipleUpdatesWhileOffline() {
10301033
assertEquals(asList(map("foo", "zzyzx", "bar", "2")), querySnapshotToValues(snapshot2));
10311034
}
10321035

1036+
@Test
1037+
public void resumingAQueryShouldUseExistenceFilterToDetectDeletes() throws Exception {
1038+
// Prepare the names and contents of the 100 documents to create.
1039+
Map<String, Map<String, Object>> testData = new HashMap<>();
1040+
for (int i = 0; i < 100; i++) {
1041+
testData.put("doc" + (1000 + i), map("key", 42));
1042+
}
1043+
1044+
// Create 100 documents in a new collection.
1045+
CollectionReference collection = testCollectionWithDocs(testData);
1046+
1047+
// Run a query to populate the local cache with the 100 documents and a resume token.
1048+
List<DocumentReference> createdDocuments = new ArrayList<>();
1049+
{
1050+
QuerySnapshot querySnapshot = waitFor(collection.get());
1051+
assertWithMessage("querySnapshot1").that(querySnapshot.size()).isEqualTo(100);
1052+
for (DocumentSnapshot documentSnapshot : querySnapshot.getDocuments()) {
1053+
createdDocuments.add(documentSnapshot.getReference());
1054+
}
1055+
}
1056+
1057+
// Delete 50 of the 100 documents. Do this in a transaction, rather than
1058+
// DocumentReference.delete(), to avoid affecting the local cache.
1059+
HashSet<String> deletedDocumentIds = new HashSet<>();
1060+
waitFor(
1061+
collection
1062+
.getFirestore()
1063+
.runTransaction(
1064+
transaction -> {
1065+
for (int i = 0; i < createdDocuments.size(); i += 2) {
1066+
DocumentReference documentToDelete = createdDocuments.get(i);
1067+
transaction.delete(documentToDelete);
1068+
deletedDocumentIds.add(documentToDelete.getId());
1069+
}
1070+
return null;
1071+
}));
1072+
1073+
// Wait for 10 seconds, during which Watch will stop tracking the query and will send an
1074+
// existence filter rather than "delete" events when the query is resumed.
1075+
Thread.sleep(10000);
1076+
1077+
// Resume the query and save the resulting snapshot for verification.
1078+
QuerySnapshot snapshot2 = waitFor(collection.get());
1079+
1080+
// Verify that the snapshot from the resumed query contains the expected documents; that is,
1081+
// that it contains the 50 documents that were _not_ deleted.
1082+
// TODO(b/270731363): Remove the "if" condition below once the Firestore Emulator is fixed to
1083+
// send an existence filter. At the time of writing, the Firestore emulator fails to send an
1084+
// existence filter, resulting in the client including the deleted documents in the snapshot
1085+
// of the resumed query.
1086+
if (!(isRunningAgainstEmulator() && snapshot2.size() == 100)) {
1087+
HashSet<String> actualDocumentIds = new HashSet<>();
1088+
for (DocumentSnapshot documentSnapshot : snapshot2.getDocuments()) {
1089+
actualDocumentIds.add(documentSnapshot.getId());
1090+
}
1091+
HashSet<String> expectedDocumentIds = new HashSet<>();
1092+
for (DocumentReference documentRef : createdDocuments) {
1093+
if (!deletedDocumentIds.contains(documentRef.getId())) {
1094+
expectedDocumentIds.add(documentRef.getId());
1095+
}
1096+
}
1097+
assertWithMessage("snapshot2.docs")
1098+
.that(actualDocumentIds)
1099+
.containsExactlyElementsIn(expectedDocumentIds);
1100+
}
1101+
}
1102+
10331103
@Test
10341104
public void testOrQueries() {
10351105
Map<String, Map<String, Object>> testDocs =

firebase-firestore/src/androidTest/java/com/google/firebase/firestore/testutil/IntegrationTestUtil.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import com.google.firebase.firestore.ListenerRegistration;
3737
import com.google.firebase.firestore.MetadataChanges;
3838
import com.google.firebase.firestore.QuerySnapshot;
39+
import com.google.firebase.firestore.WriteBatch;
3940
import com.google.firebase.firestore.auth.User;
4041
import com.google.firebase.firestore.core.DatabaseInfo;
4142
import com.google.firebase.firestore.model.DatabaseId;
@@ -347,8 +348,27 @@ public static CollectionReference testCollectionWithDocs(Map<String, Map<String,
347348

348349
public static void writeAllDocs(
349350
CollectionReference collection, Map<String, Map<String, Object>> docs) {
351+
WriteBatch writeBatch = null;
352+
int writeBatchSize = 0;
353+
350354
for (Map.Entry<String, Map<String, Object>> doc : docs.entrySet()) {
351-
waitFor(collection.document(doc.getKey()).set(doc.getValue()));
355+
if (writeBatch == null) {
356+
writeBatch = collection.getFirestore().batch();
357+
}
358+
359+
writeBatch.set(collection.document(doc.getKey()), doc.getValue());
360+
writeBatchSize++;
361+
362+
// Write batches are capped at 500 writes. Use 400 just to be safe.
363+
if (writeBatchSize == 400) {
364+
waitFor(writeBatch.commit());
365+
writeBatch = null;
366+
writeBatchSize = 0;
367+
}
368+
}
369+
370+
if (writeBatch != null) {
371+
waitFor(writeBatch.commit());
352372
}
353373
}
354374

0 commit comments

Comments
 (0)