Skip to content

Commit c5f0747

Browse files
committed
Add some more spec tests
1 parent cddbae3 commit c5f0747

File tree

2 files changed

+120
-18
lines changed

2 files changed

+120
-18
lines changed

packages/firestore/src/core/sync_engine_impl.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -929,9 +929,13 @@ function trackLimboChange(
929929
limboChange: AddedLimboDocument
930930
): void {
931931
const key = limboChange.key;
932-
if (!syncEngineImpl.activeLimboTargetsByKey.get(key)) {
932+
const keyString = key.path.canonicalString();
933+
if (
934+
!syncEngineImpl.activeLimboTargetsByKey.get(key) &&
935+
!syncEngineImpl.enqueuedLimboResolutions.has(keyString)
936+
) {
933937
logDebug(LOG_TAG, 'New document in limbo: ' + key);
934-
syncEngineImpl.enqueuedLimboResolutions.add(key.path.canonicalString());
938+
syncEngineImpl.enqueuedLimboResolutions.add(keyString);
935939
pumpEnqueuedLimboResolutions(syncEngineImpl);
936940
}
937941
}

packages/firestore/test/unit/specs/limbo_spec.test.ts

Lines changed: 114 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,7 @@ describeSpec('Limbo Documents:', [], () => {
924924
);
925925

926926
specTest(
927-
'Enqueued limbo resolutions should be removed when query listen stops',
927+
'A limbo resolution for a document should be removed from the queue when the last query listen stops',
928928
[],
929929
() => {
930930
const doc1 = doc('collection1/doc', 1000, { key: 1 });
@@ -934,38 +934,136 @@ describeSpec('Limbo Documents:', [], () => {
934934
const doc2 = doc('collection2/doc', 1000, { key: 2 });
935935
const query2 = query('collection2');
936936
const filteredQuery2 = query('collection2', filter('key', '==', 2));
937+
const filteredQuery3 = query('collection2', filter('key', '>=', 2));
937938

938939
return (
939940
spec()
940941
.withGCEnabled(false)
941942
.withMaxConcurrentLimboResolutions(1)
942943

943944
// Max out the number of active limbo resolutions.
944-
.userListens(filteredQuery1)
945-
.watchAcksFull(filteredQuery1, 1000, doc1)
946-
.expectEvents(filteredQuery1, { added: [doc1] })
947-
.userUnlistens(filteredQuery1)
948945
.userListens(query1)
949-
.expectEvents(query1, { added: [doc1], fromCache: true })
950-
.watchAcksFull(query1, 1001)
946+
.watchAcksFull(query1, 1000, doc1)
947+
.expectEvents(query1, { added: [doc1] })
948+
.userUnlistens(query1)
949+
.userListens(filteredQuery1)
950+
.expectEvents(filteredQuery1, { added: [doc1], fromCache: true })
951+
.watchAcksFull(filteredQuery1, 1001)
951952
.expectLimboDocs(doc1.key)
952953

953-
// Enqueue a limbo resolution from another query.
954+
// Enqueue a limbo resolution for doc2.
955+
.userListens(query2)
956+
.watchAcksFull(query2, 1002, doc2)
957+
.expectEvents(query2, { added: [doc2] })
958+
.userUnlistens(query2)
954959
.userListens(filteredQuery2)
955-
.watchAcksFull(filteredQuery2, 1002, doc2)
956-
.expectEvents(filteredQuery2, { added: [doc2] })
960+
.expectEvents(filteredQuery2, { added: [doc2], fromCache: true })
961+
.watchAcksFull(filteredQuery2, 1003)
962+
.expectLimboDocs(doc1.key)
963+
.expectEnqueuedLimboDocs(doc2.key)
964+
965+
// Start another query that puts doc2 into limbo again.
966+
.userListens(filteredQuery3)
967+
.expectEvents(filteredQuery3, { added: [doc2], fromCache: true })
968+
.watchAcksFull(filteredQuery3, 1004)
969+
.expectLimboDocs(doc1.key)
970+
.expectEnqueuedLimboDocs(doc2.key)
971+
972+
// Stop one of the queries that enqueued a limbo resolution for doc2;
973+
// verify that doc2 is not removed from the limbo resolution queue.
974+
.userUnlistens(filteredQuery3)
975+
.expectLimboDocs(doc1.key)
976+
.expectEnqueuedLimboDocs(doc2.key)
977+
978+
// Stop the other query that enqueued a limbo resolution for doc2;
979+
// verify that doc2 *is* removed from the limbo resolution queue.
957980
.userUnlistens(filteredQuery2)
981+
.expectLimboDocs(doc1.key)
982+
.expectEnqueuedLimboDocs()
983+
);
984+
}
985+
);
986+
987+
specTest(
988+
'A limbo resolution for a document should not be started if one is already active',
989+
[],
990+
() => {
991+
const doc1 = doc('collection/doc', 1000, { key: 1 });
992+
const query1 = query('collection');
993+
const filteredQuery1 = query('collection', filter('key', '==', 1));
994+
const filteredQuery2 = query('collection', filter('key', '>=', 1));
995+
996+
return (
997+
spec()
998+
.withGCEnabled(false)
999+
1000+
// Start a limbo resolution listen for a document.
1001+
.userListens(query1)
1002+
.watchAcksFull(query1, 1000, doc1)
1003+
.expectEvents(query1, { added: [doc1] })
1004+
.userUnlistens(query1)
1005+
.userListens(filteredQuery1)
1006+
.expectEvents(filteredQuery1, { added: [doc1], fromCache: true })
1007+
.watchAcksFull(filteredQuery1, 1001)
1008+
.expectLimboDocs(doc1.key)
1009+
.expectEnqueuedLimboDocs()
1010+
1011+
// Put the same document into limbo in a different query.
1012+
.userListens(filteredQuery2)
1013+
.expectEvents(filteredQuery2, { added: [doc1], fromCache: true })
1014+
.watchAcksFull(filteredQuery2, 1002)
1015+
.expectLimboDocs(doc1.key)
1016+
.expectEnqueuedLimboDocs()
1017+
);
1018+
}
1019+
);
1020+
1021+
specTest(
1022+
'A limbo resolution for a document should not be enqueued if one is already enqueued',
1023+
[],
1024+
() => {
1025+
const doc1 = doc('collection1/doc1', 1000, { key: 1 });
1026+
const query1 = query('collection1');
1027+
const filteredQuery1 = query('collection1', filter('key', '==', 1));
1028+
const doc2 = doc('collection2/doc2', 1000, { key: 2 });
1029+
const query2 = query('collection2');
1030+
const filteredQuery2 = query('collection2', filter('key', '==', 2));
1031+
const filteredQuery3 = query('collection2', filter('key', '>=', 2));
1032+
1033+
return (
1034+
spec()
1035+
.withGCEnabled(false)
1036+
.withMaxConcurrentLimboResolutions(1)
1037+
1038+
// Max out the number of active limbo resolutions.
1039+
.userListens(query1)
1040+
.watchAcksFull(query1, 1000, doc1)
1041+
.expectEvents(query1, { added: [doc1] })
1042+
.userUnlistens(query1)
1043+
.userListens(filteredQuery1)
1044+
.expectEvents(filteredQuery1, { added: [doc1], fromCache: true })
1045+
.watchAcksFull(filteredQuery1, 1001)
1046+
.expectLimboDocs(doc1.key)
1047+
1048+
// Start a limbo resolution listen for a different document.
9581049
.userListens(query2)
959-
.expectEvents(query2, { added: [doc2], fromCache: true })
960-
.watchAcksFull(query2, 1003)
1050+
.watchAcksFull(query2, 1002, doc2)
1051+
.expectEvents(query2, { added: [doc2] })
1052+
.userUnlistens(query2)
1053+
.userListens(filteredQuery2)
1054+
.expectEvents(filteredQuery2, { added: [doc2], fromCache: true })
1055+
.watchAcksFull(filteredQuery2, 1003)
9611056
.expectLimboDocs(doc1.key)
9621057
.expectEnqueuedLimboDocs(doc2.key)
9631058

964-
// Stop the other query and ensure that the enqueued limbo resolution
965-
// is removed.
966-
.userUnlistens(query2)
1059+
// Put the the "different" document into limbo in a different query
1060+
// and verify that it's not added to the limbo resolution queue a
1061+
// second time.
1062+
.userListens(filteredQuery3)
1063+
.expectEvents(filteredQuery3, { added: [doc2], fromCache: true })
1064+
.watchAcksFull(filteredQuery3, 1004)
9671065
.expectLimboDocs(doc1.key)
968-
.expectEnqueuedLimboDocs()
1066+
.expectEnqueuedLimboDocs(doc2.key)
9691067
);
9701068
}
9711069
);

0 commit comments

Comments
 (0)