diff --git a/firebase-firestore/src/test/resources/json/listen_spec_test.json b/firebase-firestore/src/test/resources/json/listen_spec_test.json index 0776aedbb9a..6a3481ff103 100644 --- a/firebase-firestore/src/test/resources/json/listen_spec_test.json +++ b/firebase-firestore/src/test/resources/json/listen_spec_test.json @@ -541,6 +541,164 @@ } ] }, + "Doesn't raise 'hasPendingWrites' for deletes": { + "describeName": "Listens:", + "itName": "Doesn't raise 'hasPendingWrites' for deletes", + "tags": [], + "config": { + "useGarbageCollection": true, + "numClients": 1 + }, + "steps": [ + { + "userListen": [ + 2, + { + "path": "collection", + "filters": [], + "orderBys": [] + } + ], + "stateExpect": { + "activeTargets": { + "2": { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "resumeToken": "" + } + } + } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + { + "key": "collection/a", + "version": 0, + "value": { + "key": "a" + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": false + } + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "watchSnapshot": { + "version": 1000, + "targetIds": [] + }, + "expect": [ + { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "added": [ + { + "key": "collection/a", + "version": 0, + "value": { + "key": "a" + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": false + } + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false + } + ] + }, + { + "userDelete": "collection/a", + "expect": [ + { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "removed": [ + { + "key": "collection/a", + "version": 0, + "value": { + "key": "a" + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": false + } + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false + } + ] + }, + { + "writeAck": { + "version": 2000 + }, + "stateExpect": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/a" + ], + "rejectedDocs": [] + } + } + }, + { + "watchEntity": { + "docs": [ + { + "key": "collection/a", + "version": 2000, + "value": null + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchSnapshot": { + "version": 2000, + "targetIds": [] + } + } + ] + }, "Ensure correct query results with latency-compensated deletes": { "describeName": "Listens:", "itName": "Ensure correct query results with latency-compensated deletes", @@ -2838,7 +2996,7 @@ "docs": [ { "key": "collection/a", - "version": 4000, + "version": 3000, "value": { "v": "3" }, diff --git a/firebase-firestore/src/test/resources/json/offline_spec_test.json b/firebase-firestore/src/test/resources/json/offline_spec_test.json index 864d4da410e..6dc71cfeada 100644 --- a/firebase-firestore/src/test/resources/json/offline_spec_test.json +++ b/firebase-firestore/src/test/resources/json/offline_spec_test.json @@ -30,15 +30,6 @@ } } }, - { - "watchStreamClose": { - "error": { - "code": 14, - "message": "Simulated Backend Error" - }, - "runBackoffTimer": true - } - }, { "watchStreamClose": { "error": { @@ -125,15 +116,6 @@ "runBackoffTimer": true } }, - { - "watchStreamClose": { - "error": { - "code": 14, - "message": "Simulated Backend Error" - }, - "runBackoffTimer": true - } - }, { "watchStreamClose": { "error": { @@ -209,15 +191,6 @@ } } }, - { - "watchStreamClose": { - "error": { - "code": 14, - "message": "Simulated Backend Error" - }, - "runBackoffTimer": true - } - }, { "watchStreamClose": { "error": { @@ -283,15 +256,6 @@ } } }, - { - "watchStreamClose": { - "error": { - "code": 14, - "message": "Simulated Backend Error" - }, - "runBackoffTimer": true - } - }, { "watchStreamClose": { "error": { @@ -431,15 +395,6 @@ } } }, - { - "watchStreamClose": { - "error": { - "code": 14, - "message": "Simulated Backend Error" - }, - "runBackoffTimer": true - } - }, { "watchStreamClose": { "error": { @@ -689,15 +644,6 @@ "runBackoffTimer": true } }, - { - "watchStreamClose": { - "error": { - "code": 14, - "message": "Simulated Backend Error" - }, - "runBackoffTimer": true - } - }, { "watchAck": [ 2 @@ -992,15 +938,6 @@ } } }, - { - "watchStreamClose": { - "error": { - "code": 14, - "message": "Simulated Backend Error" - }, - "runBackoffTimer": true - } - }, { "watchStreamClose": { "error": { @@ -1159,7 +1096,9 @@ "Queries return from cache when network disabled": { "describeName": "Offline:", "itName": "Queries return from cache when network disabled", - "tags": ["eager-gc"], + "tags": [ + "eager-gc" + ], "config": { "useGarbageCollection": true, "numClients": 1 diff --git a/firebase-firestore/src/test/resources/json/remote_store_spec_test.json b/firebase-firestore/src/test/resources/json/remote_store_spec_test.json index ab6c35ea2c5..57e9a2cd6f1 100644 --- a/firebase-firestore/src/test/resources/json/remote_store_spec_test.json +++ b/firebase-firestore/src/test/resources/json/remote_store_spec_test.json @@ -555,7 +555,19 @@ "message": "Simulated Backend Error" }, "runBackoffTimer": true - } + }, + "expect": [ + { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false + } + ] }, { "watchAck": [ @@ -665,6 +677,18 @@ }, "runBackoffTimer": false }, + "expect": [ + { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false + } + ], "stateExpect": { "activeTargets": {} } diff --git a/firebase-firestore/src/test/resources/json/write_spec_test.json b/firebase-firestore/src/test/resources/json/write_spec_test.json index 4b83703be0b..2438f21e61e 100644 --- a/firebase-firestore/src/test/resources/json/write_spec_test.json +++ b/firebase-firestore/src/test/resources/json/write_spec_test.json @@ -506,9 +506,518 @@ } ] }, + "Raises snapshot with 'hasPendingWrites' for unacknowledged write": { + "describeName": "Writes:", + "itName": "Raises snapshot with 'hasPendingWrites' for unacknowledged write", + "tags": [], + "config": { + "useGarbageCollection": false, + "numClients": 1 + }, + "steps": [ + { + "userSet": [ + "collection/doc", + { + "v": 1 + } + ] + }, + { + "userListen": [ + 2, + { + "path": "collection", + "filters": [], + "orderBys": [] + } + ], + "stateExpect": { + "activeTargets": { + "2": { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "resumeToken": "" + } + } + }, + "expect": [ + { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "added": [ + { + "key": "collection/doc", + "version": 0, + "value": { + "v": 1 + }, + "options": { + "hasLocalMutations": true, + "hasCommittedMutations": false + } + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true + } + ] + } + ] + }, + "Doesn't raise 'hasPendingWrites' for committed write and new listen": { + "describeName": "Writes:", + "itName": "Doesn't raise 'hasPendingWrites' for committed write and new listen", + "tags": [], + "config": { + "useGarbageCollection": false, + "numClients": 1 + }, + "steps": [ + { + "userSet": [ + "collection/doc", + { + "v": 1 + } + ] + }, + { + "writeAck": { + "version": 1000 + }, + "stateExpect": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/doc" + ], + "rejectedDocs": [] + } + } + }, + { + "userListen": [ + 2, + { + "path": "collection", + "filters": [], + "orderBys": [] + } + ], + "stateExpect": { + "activeTargets": { + "2": { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "resumeToken": "" + } + } + }, + "expect": [ + { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "added": [ + { + "key": "collection/doc", + "version": 1000, + "value": { + "v": 1 + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": true + } + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false + } + ] + } + ] + }, + "Doesn't raise event for document with pending patch": { + "describeName": "Writes:", + "itName": "Doesn't raise event for document with pending patch", + "tags": [], + "config": { + "useGarbageCollection": false, + "numClients": 1 + }, + "steps": [ + { + "userListen": [ + 2, + { + "path": "collection", + "filters": [], + "orderBys": [] + } + ], + "stateExpect": { + "activeTargets": { + "2": { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "resumeToken": "" + } + } + } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-250" + ] + }, + { + "watchSnapshot": { + "version": 250, + "targetIds": [] + }, + "expect": [ + { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false + } + ] + }, + { + "userPatch": [ + "collection/doc", + { + "v": 2 + } + ] + }, + { + "writeAck": { + "version": 1000 + }, + "stateExpect": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/doc" + ], + "rejectedDocs": [] + } + } + }, + { + "watchEntity": { + "docs": [ + { + "key": "collection/doc", + "version": 500, + "value": { + "v": 1 + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": false + } + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchSnapshot": { + "version": 500, + "targetIds": [] + } + }, + { + "watchEntity": { + "docs": [ + { + "key": "collection/doc", + "version": 1000, + "value": { + "v": 2 + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": false + } + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchSnapshot": { + "version": 1000, + "targetIds": [] + }, + "expect": [ + { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "added": [ + { + "key": "collection/doc", + "version": 1000, + "value": { + "v": 2 + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": false + } + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false + } + ] + } + ] + }, "Cache will not keep data for an outdated write ack": { "describeName": "Writes:", - "itName": "Cache will not keep data for an outdated write ack", + "itName": "Cache will not keep data for an outdated write ack", + "tags": [], + "config": { + "useGarbageCollection": true, + "numClients": 1 + }, + "steps": [ + { + "userListen": [ + 2, + { + "path": "collection/key", + "filters": [], + "orderBys": [] + } + ], + "stateExpect": { + "activeTargets": { + "2": { + "query": { + "path": "collection/key", + "filters": [], + "orderBys": [] + }, + "resumeToken": "" + } + } + } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + { + "key": "collection/key", + "version": 1000, + "value": { + "v": 1 + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": false + } + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "watchSnapshot": { + "version": 1000, + "targetIds": [] + }, + "expect": [ + { + "query": { + "path": "collection/key", + "filters": [], + "orderBys": [] + }, + "added": [ + { + "key": "collection/key", + "version": 1000, + "value": { + "v": 1 + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": false + } + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false + } + ] + }, + { + "userSet": [ + "collection/key", + { + "v": 2 + } + ], + "expect": [ + { + "query": { + "path": "collection/key", + "filters": [], + "orderBys": [] + }, + "modified": [ + { + "key": "collection/key", + "version": 1000, + "value": { + "v": 2 + }, + "options": { + "hasLocalMutations": true, + "hasCommittedMutations": false + } + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": true + } + ] + }, + { + "watchEntity": { + "docs": [ + { + "key": "collection/key", + "version": 10000, + "value": { + "v": 3 + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": false + } + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchSnapshot": { + "version": 10000, + "targetIds": [] + } + }, + { + "writeAck": { + "version": 2000 + }, + "stateExpect": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/key" + ], + "rejectedDocs": [] + } + }, + "expect": [ + { + "query": { + "path": "collection/key", + "filters": [], + "orderBys": [] + }, + "modified": [ + { + "key": "collection/key", + "version": 10000, + "value": { + "v": 3 + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": false + } + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false + } + ] + } + ] + }, + "Cache raises correct event if write is acked before watch delivers it": { + "describeName": "Writes:", + "itName": "Cache raises correct event if write is acked before watch delivers it", "tags": [], "config": { "useGarbageCollection": true, @@ -634,14 +1143,27 @@ } ] }, + { + "writeAck": { + "version": 2000 + }, + "stateExpect": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/key" + ], + "rejectedDocs": [] + } + } + }, { "watchEntity": { "docs": [ { "key": "collection/key", - "version": 10000, + "version": 2000, "value": { - "v": 3 + "v": 2 }, "options": { "hasLocalMutations": false, @@ -656,21 +1178,8 @@ }, { "watchSnapshot": { - "version": 10000, + "version": 2000, "targetIds": [] - } - }, - { - "writeAck": { - "version": 2000 - }, - "stateExpect": { - "userCallbacks": { - "acknowledgedDocs": [ - "collection/key" - ], - "rejectedDocs": [] - } }, "expect": [ { @@ -679,12 +1188,12 @@ "filters": [], "orderBys": [] }, - "modified": [ + "metadata": [ { "key": "collection/key", - "version": 10000, + "version": 2000, "value": { - "v": 3 + "v": 2 }, "options": { "hasLocalMutations": false, @@ -700,9 +1209,9 @@ } ] }, - "Cache raises correct event if write is acked before watch delivers it": { + "Cache will hold local write until watch catches up": { "describeName": "Writes:", - "itName": "Cache raises correct event if write is acked before watch delivers it", + "itName": "Cache will hold local write until watch catches up", "tags": [], "config": { "useGarbageCollection": true, @@ -713,7 +1222,7 @@ "userListen": [ 2, { - "path": "collection/key", + "path": "collection", "filters": [], "orderBys": [] } @@ -722,7 +1231,7 @@ "activeTargets": { "2": { "query": { - "path": "collection/key", + "path": "collection", "filters": [], "orderBys": [] }, @@ -772,7 +1281,7 @@ "expect": [ { "query": { - "path": "collection/key", + "path": "collection", "filters": [], "orderBys": [] }, @@ -799,13 +1308,13 @@ "userSet": [ "collection/key", { - "v": 2 + "v": 3 } ], "expect": [ { "query": { - "path": "collection/key", + "path": "collection", "filters": [], "orderBys": [] }, @@ -814,7 +1323,7 @@ "key": "collection/key", "version": 1000, "value": { - "v": 2 + "v": 3 }, "options": { "hasLocalMutations": true, @@ -830,7 +1339,7 @@ }, { "writeAck": { - "version": 2000 + "version": 3000 }, "stateExpect": { "userCallbacks": { @@ -865,20 +1374,70 @@ "watchSnapshot": { "version": 2000, "targetIds": [] + } + }, + { + "watchEntity": { + "docs": [ + { + "key": "collection/b", + "version": 3000, + "value": { + "doc": "b" + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": false + } + }, + { + "key": "collection/key", + "version": 3000, + "value": { + "v": 3 + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": false + } + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchSnapshot": { + "version": 3000, + "targetIds": [] }, "expect": [ { "query": { - "path": "collection/key", + "path": "collection", "filters": [], "orderBys": [] }, + "added": [ + { + "key": "collection/b", + "version": 3000, + "value": { + "doc": "b" + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": false + } + } + ], "metadata": [ { "key": "collection/key", - "version": 2000, + "version": 3000, "value": { - "v": 2 + "v": 3 }, "options": { "hasLocalMutations": false, @@ -894,15 +1453,23 @@ } ] }, - "Cache will hold local write until watch catches up": { + "Local patch is applied to query until watch catches up": { "describeName": "Writes:", - "itName": "Cache will hold local write until watch catches up", + "itName": "Local patch is applied to query until watch catches up", "tags": [], "config": { - "useGarbageCollection": true, + "useGarbageCollection": false, "numClients": 1 }, "steps": [ + { + "userSet": [ + "collection/doc", + { + "local": 1 + } + ] + }, { "userListen": [ 2, @@ -923,6 +1490,44 @@ "resumeToken": "" } } + }, + "expect": [ + { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "added": [ + { + "key": "collection/doc", + "version": 0, + "value": { + "local": 1 + }, + "options": { + "hasLocalMutations": true, + "hasCommittedMutations": false + } + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true + } + ] + }, + { + "writeAck": { + "version": 1000 + }, + "stateExpect": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/doc" + ], + "rejectedDocs": [] + } } }, { @@ -934,10 +1539,11 @@ "watchEntity": { "docs": [ { - "key": "collection/key", - "version": 1000, + "key": "collection/doc", + "version": 2000, "value": { - "v": 1 + "local": 1, + "remote": 2 }, "options": { "hasLocalMutations": false, @@ -955,12 +1561,12 @@ [ 2 ], - "resume-token-1000" + "resume-token-2000" ] }, { "watchSnapshot": { - "version": 1000, + "version": 2000, "targetIds": [] }, "expect": [ @@ -970,12 +1576,13 @@ "filters": [], "orderBys": [] }, - "added": [ + "modified": [ { - "key": "collection/key", - "version": 1000, + "key": "collection/doc", + "version": 2000, "value": { - "v": 1 + "local": 1, + "remote": 2 }, "options": { "hasLocalMutations": false, @@ -990,10 +1597,10 @@ ] }, { - "userSet": [ - "collection/key", + "userPatch": [ + "collection/doc", { - "v": 3 + "local": 5 } ], "expect": [ @@ -1005,10 +1612,11 @@ }, "modified": [ { - "key": "collection/key", - "version": 1000, + "key": "collection/doc", + "version": 2000, "value": { - "v": 3 + "local": 5, + "remote": 2 }, "options": { "hasLocalMutations": true, @@ -1024,12 +1632,12 @@ }, { "writeAck": { - "version": 3000 + "version": 5000 }, "stateExpect": { "userCallbacks": { "acknowledgedDocs": [ - "collection/key" + "collection/doc" ], "rejectedDocs": [] } @@ -1039,14 +1647,15 @@ "watchEntity": { "docs": [ { - "key": "collection/key", - "version": 2000, + "key": "collection/doc", + "version": 3000, "value": { - "v": 2 + "local": 1, + "remote": 3 }, "options": { "hasLocalMutations": false, - "hasCommittedMutations": false + "hasCommittedMutations": true } } ], @@ -1057,7 +1666,7 @@ }, { "watchSnapshot": { - "version": 2000, + "version": 3000, "targetIds": [] } }, @@ -1065,21 +1674,38 @@ "watchEntity": { "docs": [ { - "key": "collection/b", - "version": 3000, + "key": "collection/doc", + "version": 4000, "value": { - "doc": "b" + "local": 1, + "remote": 4 }, "options": { "hasLocalMutations": false, - "hasCommittedMutations": false + "hasCommittedMutations": true } - }, + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchSnapshot": { + "version": 4000, + "targetIds": [] + } + }, + { + "watchEntity": { + "docs": [ { - "key": "collection/key", - "version": 3000, + "key": "collection/doc", + "version": 5000, "value": { - "v": 3 + "local": 5, + "remote": 5 }, "options": { "hasLocalMutations": false, @@ -1094,7 +1720,7 @@ }, { "watchSnapshot": { - "version": 3000, + "version": 5000, "targetIds": [] }, "expect": [ @@ -1104,25 +1730,13 @@ "filters": [], "orderBys": [] }, - "added": [ - { - "key": "collection/b", - "version": 3000, - "value": { - "doc": "b" - }, - "options": { - "hasLocalMutations": false, - "hasCommittedMutations": false - } - } - ], - "metadata": [ + "modified": [ { - "key": "collection/key", - "version": 3000, + "key": "collection/doc", + "version": 5000, "value": { - "v": 3 + "local": 5, + "remote": 5 }, "options": { "hasLocalMutations": false, @@ -4041,9 +4655,9 @@ } ] }, - "Held writes are not re-sent.": { + "Writes are not re-sent.": { "describeName": "Writes:", - "itName": "Held writes are not re-sent.", + "itName": "Writes are not re-sent.", "tags": [], "config": { "useGarbageCollection": true, @@ -4278,9 +4892,9 @@ } ] }, - "Held writes are not re-sent after disable/enable network.": { + "Writes are not re-sent after disable/enable network.": { "describeName": "Writes:", - "itName": "Held writes are not re-sent after disable/enable network.", + "itName": "Writes are not re-sent after disable/enable network.", "tags": [], "config": { "useGarbageCollection": true, @@ -4497,13 +5111,13 @@ } ] }, - "Held writes are released when there are no queries left.": { + "Writes are released when there are no queries left": { "describeName": "Writes:", - "itName": "Held writes are released when there are no queries left.", + "itName": "Writes are released when there are no queries left", "tags": [ "eager-gc" ], - "comment": "This test expects a new target id for a new listen, but without eager gc, the same target id is reused", + "comment": "This test verifies that committed mutations are eligible for garbage collection on target removal", "config": { "useGarbageCollection": true, "numClients": 1 @@ -7815,23 +8429,223 @@ "hasCommittedMutations": false } } - ], - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false - } - ], + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false + } + ], + "clientIndex": 0 + }, + { + "drainQueue": true, + "stateExpect": { + "userCallbacks": { + "acknowledgedDocs": [], + "rejectedDocs": [ + "collection/a" + ] + } + }, + "expect": [ + { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "removed": [ + { + "key": "collection/a", + "version": 0, + "value": { + "v": 1 + }, + "options": { + "hasLocalMutations": true, + "hasCommittedMutations": false + } + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false + } + ], + "clientIndex": 1 + } + ] + }, + "Writes are released by primary client": { + "describeName": "Writes:", + "itName": "Writes are released by primary client", + "tags": [ + "multi-client" + ], + "config": { + "useGarbageCollection": false, + "numClients": 2 + }, + "steps": [ + { + "drainQueue": true, + "clientIndex": 0 + }, + { + "userListen": [ + 2, + { + "path": "collection", + "filters": [], + "orderBys": [] + } + ], + "stateExpect": { + "activeTargets": { + "2": { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "resumeToken": "" + } + } + }, + "clientIndex": 0 + }, + { + "watchAck": [ + 2 + ], + "clientIndex": 0 + }, + { + "watchEntity": { + "docs": [], + "targets": [ + 2 + ] + }, + "clientIndex": 0 + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-500" + ], + "clientIndex": 0 + }, + { + "watchSnapshot": { + "version": 500, + "targetIds": [] + }, + "expect": [ + { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false + } + ], + "clientIndex": 0 + }, + { + "drainQueue": true, + "clientIndex": 1 + }, + { + "userSet": [ + "collection/a", + { + "v": 1 + } + ], + "clientIndex": 1 + }, + { + "drainQueue": true, + "expect": [ + { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "added": [ + { + "key": "collection/a", + "version": 0, + "value": { + "v": 1 + }, + "options": { + "hasLocalMutations": true, + "hasCommittedMutations": false + } + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": true + } + ], + "clientIndex": 0 + }, + { + "writeAck": { + "version": 1000 + }, + "clientIndex": 0 + }, + { + "drainQueue": true, + "stateExpect": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/a" + ], + "rejectedDocs": [] + } + }, + "clientIndex": 1 + }, + { + "drainQueue": true, + "clientIndex": 0 + }, + { + "watchEntity": { + "docs": [ + { + "key": "collection/a", + "version": 1000, + "value": { + "v": 1 + }, + "options": { + "hasLocalMutations": false, + "hasCommittedMutations": false + } + } + ], + "targets": [ + 2 + ] + }, "clientIndex": 0 }, { - "drainQueue": true, - "stateExpect": { - "userCallbacks": { - "acknowledgedDocs": [], - "rejectedDocs": [ - "collection/a" - ] - } + "watchSnapshot": { + "version": 2000, + "targetIds": [] }, "expect": [ { @@ -7840,15 +8654,15 @@ "filters": [], "orderBys": [] }, - "removed": [ + "metadata": [ { "key": "collection/a", - "version": 0, + "version": 1000, "value": { "v": 1 }, "options": { - "hasLocalMutations": true, + "hasLocalMutations": false, "hasCommittedMutations": false } } @@ -7858,13 +8672,13 @@ "hasPendingWrites": false } ], - "clientIndex": 1 + "clientIndex": 0 } ] }, - "Held write is released by primary client": { + "Writes are held during primary failover": { "describeName": "Writes:", - "itName": "Held write is released by primary client", + "itName": "Writes are held during primary failover", "tags": [ "multi-client" ], @@ -7900,6 +8714,40 @@ }, "clientIndex": 0 }, + { + "userSet": [ + "collection/doc", + { + "v": 1 + } + ], + "expect": [ + { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "added": [ + { + "key": "collection/doc", + "version": 0, + "value": { + "v": 1 + }, + "options": { + "hasLocalMutations": true, + "hasCommittedMutations": false + } + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": true + } + ], + "clientIndex": 0 + }, { "watchAck": [ 2 @@ -7920,13 +8768,13 @@ [ 2 ], - "resume-token-500" + "resume-token-1000" ], "clientIndex": 0 }, { "watchSnapshot": { - "version": 500, + "version": 1000, "targetIds": [] }, "expect": [ @@ -7938,73 +8786,122 @@ }, "errorCode": 0, "fromCache": false, - "hasPendingWrites": false + "hasPendingWrites": true } ], "clientIndex": 0 }, + { + "writeAck": { + "version": 2000 + }, + "stateExpect": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/doc" + ], + "rejectedDocs": [] + } + }, + "clientIndex": 0 + }, { "drainQueue": true, "clientIndex": 1 }, { - "userSet": [ - "collection/a", - { - "v": 1 + "applyClientState": { + "primary": true + }, + "stateExpect": { + "isPrimary": true, + "activeTargets": { + "2": { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "resumeToken": "resume-token-1000" + } } - ], + }, "clientIndex": 1 }, { - "drainQueue": true, + "userListen": [ + 4, + { + "path": "collection/doc", + "filters": [], + "orderBys": [] + } + ], + "stateExpect": { + "activeTargets": { + "2": { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "resumeToken": "resume-token-1000" + }, + "4": { + "query": { + "path": "collection/doc", + "filters": [], + "orderBys": [] + }, + "resumeToken": "" + } + } + }, "expect": [ { "query": { - "path": "collection", + "path": "collection/doc", "filters": [], "orderBys": [] }, "added": [ { - "key": "collection/a", - "version": 0, + "key": "collection/doc", + "version": 2000, "value": { "v": 1 }, "options": { - "hasLocalMutations": true, - "hasCommittedMutations": false + "hasLocalMutations": false, + "hasCommittedMutations": true } } ], "errorCode": 0, - "fromCache": false, - "hasPendingWrites": true + "fromCache": true, + "hasPendingWrites": false } ], - "clientIndex": 0 - }, - { - "writeAck": { - "version": 1000 - }, - "clientIndex": 0 + "clientIndex": 1 }, { - "drainQueue": true, + "watchAck": [ + 2 + ], "clientIndex": 1 }, { - "drainQueue": true, - "clientIndex": 0 + "watchAck": [ + 4 + ], + "clientIndex": 1 }, { "watchEntity": { "docs": [ { - "key": "collection/a", - "version": 1000, + "key": "collection/doc", + "version": 2000, "value": { "v": 1 }, @@ -8015,16 +8912,78 @@ } ], "targets": [ - 2 + 2, + 4 ] }, - "clientIndex": 0 + "clientIndex": 1 + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-2000" + ], + "clientIndex": 1 + }, + { + "watchCurrent": [ + [ + 4 + ], + "resume-token-2000" + ], + "clientIndex": 1 }, { "watchSnapshot": { "version": 2000, "targetIds": [] }, + "expect": [ + { + "query": { + "path": "collection/doc", + "filters": [], + "orderBys": [] + }, + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false + } + ], + "clientIndex": 1 + }, + { + "drainQueue": true, + "stateExpect": { + "activeTargets": { + "2": { + "query": { + "path": "collection", + "filters": [], + "orderBys": [] + }, + "resumeToken": "" + }, + "4": { + "query": { + "path": "collection/doc", + "filters": [], + "orderBys": [] + }, + "resumeToken": "" + } + } + }, + "clientIndex": 0 + }, + { + "runTimer": "client_metadata_refresh", + "stateExpect": { + "isPrimary": false + }, "expect": [ { "query": { @@ -8034,8 +8993,8 @@ }, "metadata": [ { - "key": "collection/a", - "version": 1000, + "key": "collection/doc", + "version": 2000, "value": { "v": 1 }, @@ -8051,18 +9010,6 @@ } ], "clientIndex": 0 - }, - { - "drainQueue": true, - "stateExpect": { - "userCallbacks": { - "acknowledgedDocs": [ - "collection/a" - ], - "rejectedDocs": [] - } - }, - "clientIndex": 1 } ] },