use of com.google.firebase.firestore.remote.WatchChange.DocumentChange in project firebase-android-sdk by firebase.
the class SpecTestCase method doWatchEntity.
private void doWatchEntity(JSONObject watchEntity) throws Exception {
if (watchEntity.has("docs")) {
Assert.hardAssert(!watchEntity.has("doc"), "Exactly one of |doc| or |docs| needs to be set.");
JSONArray docs = watchEntity.getJSONArray("docs");
for (int i = 0; i < docs.length(); ++i) {
JSONObject doc = docs.getJSONObject(i);
JSONObject watchSpec = new JSONObject();
watchSpec.put("doc", doc);
if (watchEntity.has("targets")) {
watchSpec.put("targets", watchEntity.get("targets"));
}
if (watchEntity.has("removedTargets")) {
watchSpec.put("removedTargets", watchEntity.get("removedTargets"));
}
doWatchEntity(watchSpec);
}
} else if (watchEntity.has("doc")) {
JSONObject docSpec = watchEntity.getJSONObject("doc");
String key = docSpec.getString("key");
@Nullable Map<String, Object> value = !docSpec.isNull("value") ? parseMap(docSpec.getJSONObject("value")) : null;
long version = docSpec.getLong("version");
MutableDocument doc = value != null ? doc(key, version, value) : deletedDoc(key, version);
List<Integer> updated = parseIntList(watchEntity.optJSONArray("targets"));
List<Integer> removed = parseIntList(watchEntity.optJSONArray("removedTargets"));
WatchChange change = new DocumentChange(updated, removed, doc.getKey(), doc);
writeWatchChange(change, SnapshotVersion.NONE);
} else if (watchEntity.has("key")) {
String key = watchEntity.getString("key");
List<Integer> removed = parseIntList(watchEntity.optJSONArray("removedTargets"));
WatchChange change = new DocumentChange(Collections.emptyList(), removed, key(key), null);
writeWatchChange(change, SnapshotVersion.NONE);
} else {
throw Assert.fail("Either key, doc or docs must be set.");
}
}
use of com.google.firebase.firestore.remote.WatchChange.DocumentChange in project firebase-android-sdk by firebase.
the class RemoteEventTest method createAggregator.
/**
* Creates an aggregator initialized with the set of provided WatchChanges. Tests can add further
* changes via `handleDocumentChange`, `handleTargetChange` and `handleExistenceFilterChange`.
*
* @param targetMap A map of query data for all active targets. The map must include an entry for
* every target referenced by any of the watch changes.
* @param outstandingResponses The number of outstanding ACKs a target has to receive before it is
* considered active, or `noOutstandingResponses` if all targets are already active.
* @param existingKeys The set of documents that are considered synced with the test targets as
* part of a previous listen. To modify this set during test execution, invoke
* `targetMetadataProvider.setSyncedKeys()`.
* @param watchChanges The watch changes to apply before returning the aggregator. Supported
* changes are DocumentWatchChange and WatchTargetChange.
*/
private WatchChangeAggregator createAggregator(Map<Integer, TargetData> targetMap, Map<Integer, Integer> outstandingResponses, ImmutableSortedSet<DocumentKey> existingKeys, WatchChange... watchChanges) {
WatchChangeAggregator aggregator = new WatchChangeAggregator(targetMetadataProvider);
List<Integer> targetIds = new ArrayList<>();
for (Map.Entry<Integer, TargetData> entry : targetMap.entrySet()) {
targetIds.add(entry.getKey());
targetMetadataProvider.setSyncedKeys(entry.getValue(), existingKeys);
}
for (Map.Entry<Integer, Integer> entry : outstandingResponses.entrySet()) {
for (int i = 0; i < entry.getValue(); ++i) {
aggregator.recordPendingTargetRequest(entry.getKey());
}
}
for (WatchChange watchChange : watchChanges) {
if (watchChange instanceof DocumentChange) {
aggregator.handleDocumentChange((DocumentChange) watchChange);
} else if (watchChange instanceof WatchTargetChange) {
aggregator.handleTargetChange((WatchTargetChange) watchChange);
} else {
fail("Encountered unexpected type of WatchChange");
}
}
aggregator.handleTargetChange(new WatchTargetChange(WatchTargetChangeType.NoChange, targetIds, resumeToken));
return aggregator;
}
use of com.google.firebase.firestore.remote.WatchChange.DocumentChange in project firebase-android-sdk by firebase.
the class RemoteEventTest method testExistenceFilterMismatchRemovesCurrentChanges.
@Test
public void testExistenceFilterMismatchRemovesCurrentChanges() {
Map<Integer, TargetData> targetMap = activeQueries(1);
WatchChangeAggregator aggregator = createAggregator(targetMap, noOutstandingResponses, noExistingKeys);
WatchTargetChange markCurrent = new WatchTargetChange(WatchTargetChangeType.Current, asList(1));
aggregator.handleTargetChange(markCurrent);
MutableDocument doc1 = doc("docs/1", 1, map("value", 1));
DocumentChange addDoc = new DocumentChange(asList(1), emptyList(), doc1.getKey(), doc1);
aggregator.handleDocumentChange(addDoc);
// The existence filter mismatch will remove the document from target 1, but not synthesize a
// document delete.
WatchChange.ExistenceFilterWatchChange existenceFilter = new WatchChange.ExistenceFilterWatchChange(1, new ExistenceFilter(0));
aggregator.handleExistenceFilter(existenceFilter);
RemoteEvent event = aggregator.createRemoteEvent(version(3));
assertEquals(version(3), event.getSnapshotVersion());
assertEquals(1, event.getDocumentUpdates().size());
assertEquals(1, event.getTargetMismatches().size());
assertEquals(doc1, event.getDocumentUpdates().get(doc1.getKey()));
assertEquals(1, event.getTargetChanges().size());
TargetChange mapping1 = targetChange(ByteString.EMPTY, false, null, null, null);
assertEquals(mapping1, event.getTargetChanges().get(1));
}
use of com.google.firebase.firestore.remote.WatchChange.DocumentChange in project firebase-android-sdk by firebase.
the class RemoteEventTest method testWillAccumulateDocumentAddedAndRemovedEvents.
@Test
public void testWillAccumulateDocumentAddedAndRemovedEvents() {
Map<Integer, TargetData> targetMap = activeQueries(1, 2, 3, 4, 5, 6);
MutableDocument existingDoc = doc("docs/1", 1, map("value", 1));
MutableDocument newDoc = doc("docs/2", 2, map("value", 2));
WatchChange change1 = new DocumentChange(asList(1, 2, 3), asList(4, 5, 6), existingDoc.getKey(), existingDoc);
WatchChange change2 = new DocumentChange(asList(1, 4), asList(2, 6), newDoc.getKey(), newDoc);
RemoteEvent event = createRemoteEvent(3, targetMap, noOutstandingResponses, keySet(existingDoc.getKey()), change1, change2);
assertEquals(version(3), event.getSnapshotVersion());
assertEquals(2, event.getDocumentUpdates().size());
assertEquals(existingDoc, event.getDocumentUpdates().get(existingDoc.getKey()));
assertEquals(newDoc, event.getDocumentUpdates().get(newDoc.getKey()));
assertEquals(6, event.getTargetChanges().size());
TargetChange mapping1 = targetChange(resumeToken, false, asList(newDoc), asList(existingDoc), null);
assertEquals(mapping1, event.getTargetChanges().get(1));
TargetChange mapping2 = targetChange(resumeToken, false, null, asList(existingDoc), null);
assertEquals(mapping2, event.getTargetChanges().get(2));
TargetChange mapping3 = targetChange(resumeToken, false, null, asList(existingDoc), null);
assertEquals(mapping3, event.getTargetChanges().get(3));
TargetChange mapping4 = targetChange(resumeToken, false, asList(newDoc), null, asList(existingDoc));
assertEquals(mapping4, event.getTargetChanges().get(4));
TargetChange mapping5 = targetChange(resumeToken, false, null, null, asList(existingDoc));
assertEquals(mapping5, event.getTargetChanges().get(5));
TargetChange mapping6 = targetChange(resumeToken, false, null, null, asList(existingDoc));
assertEquals(mapping6, event.getTargetChanges().get(6));
}
use of com.google.firebase.firestore.remote.WatchChange.DocumentChange in project firebase-android-sdk by firebase.
the class RemoteEventTest method testTargetAddedChangeWillResetPreviousState.
@Test
public void testTargetAddedChangeWillResetPreviousState() {
Map<Integer, TargetData> targetMap = activeQueries(1, 3);
MutableDocument doc1 = doc("docs/1", 1, map("value", 1));
MutableDocument doc2 = doc("docs/2", 2, map("value", 2));
WatchChange change1 = new DocumentChange(asList(1, 3), asList(2), doc1.getKey(), doc1);
WatchChange change2 = new WatchTargetChange(WatchTargetChangeType.Current, asList(1, 2, 3));
WatchChange change3 = new WatchTargetChange(WatchTargetChangeType.Removed, asList(1));
WatchChange change4 = new WatchTargetChange(WatchTargetChangeType.Removed, asList(2));
WatchChange change5 = new WatchTargetChange(WatchTargetChangeType.Added, asList(1));
WatchChange change6 = new DocumentChange(asList(1), asList(3), doc2.getKey(), doc2);
Map<Integer, Integer> outstanding = new HashMap<>();
outstanding.put(1, 2);
outstanding.put(2, 1);
RemoteEvent event = createRemoteEvent(3, targetMap, outstanding, keySet(doc2.getKey()), change1, change2, change3, change4, change5, change6);
assertEquals(version(3), event.getSnapshotVersion());
assertEquals(2, event.getDocumentUpdates().size());
assertEquals(doc1, event.getDocumentUpdates().get(doc1.getKey()));
assertEquals(doc2, event.getDocumentUpdates().get(doc2.getKey()));
// target 1 and 3 are affected (1 because of re-add), target 2 is not because of remove.
assertEquals(2, event.getTargetChanges().size());
// doc1 was before the remove, so it does not show up in the mapping.
// Current was before the remove.
TargetChange mapping1 = targetChange(resumeToken, false, null, asList(doc2), null);
assertEquals(mapping1, event.getTargetChanges().get(1));
// Doc1 was before the remove.
// Current was after the remove
TargetChange mapping3 = targetChange(resumeToken, true, asList(doc1), null, asList(doc2));
assertEquals(mapping3, event.getTargetChanges().get(3));
}
Aggregations