Search in sources :

Example 1 with TargetData

use of com.google.firebase.firestore.local.TargetData in project firebase-android-sdk by firebase.

the class SpecTestCase method validateExpectedState.

private void validateExpectedState(@Nullable JSONObject expectedState) throws JSONException {
    if (expectedState != null) {
        if (expectedState.has("numOutstandingWrites")) {
            assertEquals(expectedState.getInt("numOutstandingWrites"), writesSent());
        }
        if (expectedState.has("writeStreamRequestCount")) {
            assertEquals(expectedState.getInt("writeStreamRequestCount"), datastore.getWriteStreamRequestCount());
        }
        if (expectedState.has("watchStreamRequestCount")) {
            assertEquals(expectedState.getInt("watchStreamRequestCount"), datastore.getWatchStreamRequestCount());
        }
        if (expectedState.has("activeLimboDocs")) {
            expectedActiveLimboDocs = new HashSet<>();
            JSONArray limboDocs = expectedState.getJSONArray("activeLimboDocs");
            for (int i = 0; i < limboDocs.length(); i++) {
                expectedActiveLimboDocs.add(key((String) limboDocs.get(i)));
            }
        }
        if (expectedState.has("enqueuedLimboDocs")) {
            expectedEnqueuedLimboDocs = new HashSet<>();
            JSONArray limboDocs = expectedState.getJSONArray("enqueuedLimboDocs");
            for (int i = 0; i < limboDocs.length(); i++) {
                expectedEnqueuedLimboDocs.add(key((String) limboDocs.get(i)));
            }
        }
        if (expectedState.has("activeTargets")) {
            expectedActiveTargets = new HashMap<>();
            JSONObject activeTargets = expectedState.getJSONObject("activeTargets");
            Iterator<String> keys = activeTargets.keys();
            while (keys.hasNext()) {
                String targetIdString = keys.next();
                int targetId = Integer.parseInt(targetIdString);
                JSONObject queryDataJson = activeTargets.getJSONObject(targetIdString);
                JSONArray queryArrayJson = queryDataJson.getJSONArray("queries");
                expectedActiveTargets.put(targetId, new ArrayList<>());
                for (int i = 0; i < queryArrayJson.length(); i++) {
                    Query query = parseQuery(queryArrayJson.getJSONObject(i));
                    // TODO: populate the purpose of the target once it's possible to encode that in the
                    // spec tests. For now, hard-code that it's a listen despite the fact that it's not
                    // always the right value.
                    TargetData targetData = new TargetData(query.toTarget(), targetId, ARBITRARY_SEQUENCE_NUMBER, QueryPurpose.LISTEN);
                    if (queryDataJson.has("resumeToken")) {
                        targetData = targetData.withResumeToken(ByteString.copyFromUtf8(queryDataJson.getString("resumeToken")), SnapshotVersion.NONE);
                    } else {
                        targetData = targetData.withResumeToken(ByteString.EMPTY, version(queryDataJson.getInt("readTime")));
                    }
                    expectedActiveTargets.get(targetId).add(targetData);
                }
            }
        }
    }
    // Always validate the we received the expected number of events.
    validateUserCallbacks(expectedState);
    // Always validate that the expected limbo docs match the actual limbo docs.
    validateActiveLimboDocs();
    validateEnqueuedLimboDocs();
    // Always validate that the expected active targets match the actual active targets.
    validateActiveTargets();
}
Also used : TargetData(com.google.firebase.firestore.local.TargetData) JSONObject(org.json.JSONObject) Query(com.google.firebase.firestore.core.Query) JSONArray(org.json.JSONArray) ByteString(com.google.protobuf.ByteString)

Example 2 with TargetData

use of com.google.firebase.firestore.local.TargetData in project firebase-android-sdk by firebase.

the class SpecTestCase method validateActiveTargets.

private void validateActiveTargets() {
    if (!networkEnabled) {
        return;
    }
    // Create a copy so we can modify it in tests
    Map<Integer, TargetData> actualTargets = new HashMap<>(datastore.activeTargets());
    for (Map.Entry<Integer, List<TargetData>> expected : expectedActiveTargets.entrySet()) {
        assertTrue("Expected active target not found: " + expected.getValue(), actualTargets.containsKey(expected.getKey()));
        List<TargetData> expectedQueries = expected.getValue();
        TargetData expectedTarget = expectedQueries.get(0);
        TargetData actualTarget = actualTargets.get(expected.getKey());
        // TODO: validate the purpose of the target once it's possible to encode that in the
        // spec tests. For now, only validate properties that can be validated.
        // assertEquals(expectedTarget, actualTarget);
        assertEquals(expectedTarget.getTarget(), actualTarget.getTarget());
        assertEquals(expectedTarget.getTargetId(), actualTarget.getTargetId());
        assertEquals(expectedTarget.getSnapshotVersion(), actualTarget.getSnapshotVersion());
        assertEquals(expectedTarget.getResumeToken().toStringUtf8(), actualTarget.getResumeToken().toStringUtf8());
        actualTargets.remove(expected.getKey());
    }
    assertTrue("Unexpected active targets: " + actualTargets, actualTargets.isEmpty());
}
Also used : TargetData(com.google.firebase.firestore.local.TargetData) HashMap(java.util.HashMap) Collections.singletonList(java.util.Collections.singletonList) List(java.util.List) ArrayList(java.util.ArrayList) Map(java.util.Map) HashMap(java.util.HashMap)

Example 3 with TargetData

use of com.google.firebase.firestore.local.TargetData 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;
}
Also used : TargetData(com.google.firebase.firestore.local.TargetData) ArrayList(java.util.ArrayList) DocumentChange(com.google.firebase.firestore.remote.WatchChange.DocumentChange) HashMap(java.util.HashMap) Map(java.util.Map) WatchTargetChange(com.google.firebase.firestore.remote.WatchChange.WatchTargetChange)

Example 4 with TargetData

use of com.google.firebase.firestore.local.TargetData 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));
}
Also used : MutableDocument(com.google.firebase.firestore.model.MutableDocument) DocumentChange(com.google.firebase.firestore.remote.WatchChange.DocumentChange) WatchTargetChange(com.google.firebase.firestore.remote.WatchChange.WatchTargetChange) TargetData(com.google.firebase.firestore.local.TargetData) WatchTargetChange(com.google.firebase.firestore.remote.WatchChange.WatchTargetChange) Test(org.junit.Test)

Example 5 with TargetData

use of com.google.firebase.firestore.local.TargetData 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));
}
Also used : TargetData(com.google.firebase.firestore.local.TargetData) WatchTargetChange(com.google.firebase.firestore.remote.WatchChange.WatchTargetChange) MutableDocument(com.google.firebase.firestore.model.MutableDocument) DocumentChange(com.google.firebase.firestore.remote.WatchChange.DocumentChange) Test(org.junit.Test)

Aggregations

TargetData (com.google.firebase.firestore.local.TargetData)38 Test (org.junit.Test)23 WatchTargetChange (com.google.firebase.firestore.remote.WatchChange.WatchTargetChange)22 MutableDocument (com.google.firebase.firestore.model.MutableDocument)15 DocumentChange (com.google.firebase.firestore.remote.WatchChange.DocumentChange)14 HashMap (java.util.HashMap)8 Query (com.google.firebase.firestore.core.Query)7 StructuredQuery (com.google.firestore.v1.StructuredQuery)6 DocumentKey (com.google.firebase.firestore.model.DocumentKey)5 WatchChangeAggregator (com.google.firebase.firestore.remote.WatchChangeAggregator)4 ByteString (com.google.protobuf.ByteString)4 ImmutableSortedSet (com.google.firebase.database.collection.ImmutableSortedSet)3 Target (com.google.firestore.v1.Target)3 DocumentsTarget (com.google.firestore.v1.Target.DocumentsTarget)3 QueryTarget (com.google.firestore.v1.Target.QueryTarget)3 Map (java.util.Map)3 WatchChange (com.google.firebase.firestore.remote.WatchChange)2 ArrayList (java.util.ArrayList)2 LinkedHashMap (java.util.LinkedHashMap)2 Target (com.google.firebase.firestore.core.Target)1