diff --git a/Firestore/Example/Tests/SpecTests/json/listen_spec_test.json b/Firestore/Example/Tests/SpecTests/json/listen_spec_test.json index 1af1ab6594a..193d40005b5 100644 --- a/Firestore/Example/Tests/SpecTests/json/listen_spec_test.json +++ b/Firestore/Example/Tests/SpecTests/json/listen_spec_test.json @@ -2257,19 +2257,17 @@ } ] }, - "Ensure correct query results with latency-compensated deletes": { + "Empty initial snapshot is raised from cache": { "describeName": "Listens:", - "itName": "Ensure correct query results with latency-compensated deletes", + "itName": "Empty initial snapshot is raised from cache", "tags": [ + "no-ios" ], "config": { "numClients": 1, - "useGarbageCollection": true + "useGarbageCollection": false }, "steps": [ - { - "userDelete": "collection/b" - }, { "userListen": { "query": { @@ -2306,28 +2304,6 @@ { "watchEntity": { "docs": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "a": true - }, - "version": 1000 - }, - { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "b": true - }, - "version": 1000 - } ], "targets": [ 2 @@ -2350,19 +2326,6 @@ }, "expectedSnapshotEvents": [ { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "a": true - }, - "version": 1000 - } - ], "errorCode": 0, "fromCache": false, "hasPendingWrites": false, @@ -2376,42 +2339,48 @@ } ] }, + { + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, { "userListen": { "query": { "filters": [ ], - "limit": 10, - "limitType": "LimitToFirst", "orderBys": [ ], "path": "collection" }, - "targetId": 4 + "targetId": 2 }, "expectedSnapshotEvents": [ { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "a": true - }, - "version": 1000 - } - ], "errorCode": 0, "fromCache": true, "hasPendingWrites": false, "query": { "filters": [ ], - "limit": 10, - "limitType": "LimitToFirst", "orderBys": [ ], "path": "collection" @@ -2430,38 +2399,73 @@ "path": "collection" } ], - "resumeToken": "" - }, - "4": { - "queries": [ - { - "filters": [ - ], - "limit": 10, - "limitType": "LimitToFirst", - "orderBys": [ - ], - "path": "collection" - } - ], - "resumeToken": "" + "resumeToken": "resume-token-1000" } } } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-2000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + }, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] } ] }, - "Ignores update from inactive target": { + "Empty initial snapshot is raised from cache in multiple tabs": { "describeName": "Listens:", - "itName": "Ignores update from inactive target", + "itName": "Empty initial snapshot is raised from cache in multiple tabs", "tags": [ + "multi-client" ], "config": { - "numClients": 1, + "numClients": 2, "useGarbageCollection": false }, "steps": [ { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, "userListen": { "query": { "filters": [ @@ -2490,24 +2494,15 @@ } }, { + "clientIndex": 0, "watchAck": [ 2 ] }, { + "clientIndex": 0, "watchEntity": { "docs": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 - } ], "targets": [ 2 @@ -2515,6 +2510,7 @@ } }, { + "clientIndex": 0, "watchCurrent": [ [ 2 @@ -2523,6 +2519,7 @@ ] }, { + "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], @@ -2530,19 +2527,6 @@ }, "expectedSnapshotEvents": [ { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 - } - ], "errorCode": 0, "fromCache": false, "hasPendingWrites": false, @@ -2557,6 +2541,7 @@ ] }, { + "clientIndex": 0, "userUnlisten": [ 2, { @@ -2573,33 +2558,7 @@ } }, { - "watchEntity": { - "docs": [ - { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "b" - }, - "version": 2000 - } - ], - "targets": [ - 2 - ] - } - }, - { - "watchSnapshot": { - "targetIds": [ - ], - "version": 2000 - } - }, - { + "clientIndex": 0, "watchRemove": { "targetIds": [ 2 @@ -2607,6 +2566,11 @@ } }, { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, "userListen": { "query": { "filters": [ @@ -2619,19 +2583,6 @@ }, "expectedSnapshotEvents": [ { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 - } - ], "errorCode": 0, "fromCache": true, "hasPendingWrites": false, @@ -2656,36 +2607,103 @@ "path": "collection" } ], - "resumeToken": "resume-token-1000" + "resumeToken": "" } } } - } - ] - }, - "Individual (deleted) documents cannot revert": { - "describeName": "Listens:", - "itName": "Individual (deleted) documents cannot revert", - "tags": [ - ], - "config": { - "numClients": 1, - "useGarbageCollection": false - }, - "steps": [ + }, { - "userListen": { - "query": { - "filters": [ - [ - "visible", - "==", - true - ] - ], - "orderBys": [ - ], - "path": "collection" + "clientIndex": 0, + "drainQueue": true, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "resume-token-1000" + } + } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-2000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + } + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + } + ] + }, + "Empty-due-to-delete initial snapshot is raised from cache": { + "describeName": "Listens:", + "itName": "Empty-due-to-delete initial snapshot is raised from cache", + "tags": [ + "no-ios" + ], + "config": { + "numClients": 1, + "useGarbageCollection": false + }, + "steps": [ + { + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" }, "targetId": 2 }, @@ -2695,11 +2713,6 @@ "queries": [ { "filters": [ - [ - "visible", - "==", - true - ] ], "orderBys": [ ], @@ -2726,8 +2739,7 @@ "hasLocalMutations": false }, "value": { - "v": "v1000", - "visible": true + "v": 1 }, "version": 1000 } @@ -2761,8 +2773,7 @@ "hasLocalMutations": false }, "value": { - "v": "v1000", - "visible": true + "v": 1 }, "version": 1000 } @@ -2772,11 +2783,6 @@ "hasPendingWrites": false, "query": { "filters": [ - [ - "visible", - "==", - true - ] ], "orderBys": [ ], @@ -2790,11 +2796,6 @@ 2, { "filters": [ - [ - "visible", - "==", - true - ] ], "orderBys": [ ], @@ -2813,6 +2814,9 @@ ] } }, + { + "userDelete": "collection/a" + }, { "userListen": { "query": { @@ -2822,24 +2826,10 @@ ], "path": "collection" }, - "targetId": 4 + "targetId": 2 }, "expectedSnapshotEvents": [ { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "v": "v1000", - "visible": true - }, - "version": 1000 - } - ], "errorCode": 0, "fromCache": true, "hasPendingWrites": false, @@ -2854,7 +2844,53 @@ ], "expectedState": { "activeTargets": { - "4": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "resume-token-1000" + } + } + } + } + ] + }, + "Empty-due-to-delete initial snapshot is raised from cache in multiple tabs": { + "describeName": "Listens:", + "itName": "Empty-due-to-delete initial snapshot is raised from cache in multiple tabs", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 2, + "useGarbageCollection": false + }, + "steps": [ + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { "queries": [ { "filters": [ @@ -2870,51 +2906,51 @@ } }, { + "clientIndex": 0, "watchAck": [ - 4 + 2 ] }, { + "clientIndex": 0, "watchEntity": { "docs": [ { "key": "collection/a", - "value": null, - "version": 3000 + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "v": 1 + }, + "version": 1000 } ], - "removedTargets": [ - 4 + "targets": [ + 2 ] } }, { + "clientIndex": 0, "watchCurrent": [ [ - 4 + 2 ], - "resume-token-4000" + "resume-token-1000" ] }, { + "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], - "version": 4000 + "version": 1000 }, "expectedSnapshotEvents": [ { - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - }, - "removed": [ + "added": [ { "key": "collection/a", "options": { @@ -2922,18 +2958,28 @@ "hasLocalMutations": false }, "value": { - "v": "v1000", - "visible": true + "v": 1 }, "version": 1000 } - ] + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } } ] }, { + "clientIndex": 0, "userUnlisten": [ - 4, + 2, { "filters": [ ], @@ -2948,21 +2994,26 @@ } }, { + "clientIndex": 0, "watchRemove": { "targetIds": [ - 4 + 2 ] } }, { + "clientIndex": 0, + "userDelete": "collection/a" + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, "userListen": { "query": { "filters": [ - [ - "visible", - "==", - true - ] ], "orderBys": [ ], @@ -2970,130 +3021,43 @@ }, "targetId": 2 }, - "expectedState": { - "activeTargets": { - "2": { - "queries": [ - { - "filters": [ - [ - "visible", - "==", - true - ] - ], - "orderBys": [ - ], - "path": "collection" - } - ], - "resumeToken": "resume-token-1000" - } - } - } - }, - { - "watchAck": [ - 2 - ] - }, - { - "watchEntity": { - "docs": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "v": "v2000", - "visible": false - }, - "version": 2000 - } - ], - "removedTargets": [ - 2 - ] - } - }, - { - "watchCurrent": [ - [ - 2 - ], - "resume-token-5000" - ] - }, - { - "watchSnapshot": { - "targetIds": [ - ], - "version": 5000 - }, "expectedSnapshotEvents": [ { "errorCode": 0, - "fromCache": false, + "fromCache": true, "hasPendingWrites": false, "query": { "filters": [ - [ - "visible", - "==", - true - ] ], "orderBys": [ ], "path": "collection" } } - ] - }, - { - "userUnlisten": [ - 2, - { - "filters": [ - [ - "visible", - "==", - true - ] - ], - "orderBys": [ - ], - "path": "collection" - } ], "expectedState": { "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } } } }, { - "watchRemove": { - "targetIds": [ - 2 - ] - } - }, - { - "userListen": { - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - }, - "targetId": 4 - }, + "clientIndex": 0, + "drainQueue": true, "expectedState": { "activeTargets": { - "4": { + "2": { "queries": [ { "filters": [ @@ -3103,39 +3067,67 @@ "path": "collection" } ], - "resumeToken": "resume-token-4000" + "resumeToken": "resume-token-1000" } } } }, { + "clientIndex": 0, + "writeAck": { + "version": 2000 + }, + "expectedState": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/a" + ], + "rejectedDocs": [ + ] + } + } + }, + { + "clientIndex": 0, "watchAck": [ - 4 + 2 ] }, { + "clientIndex": 0, "watchEntity": { "docs": [ + { + "key": "collection/a", + "value": null, + "version": 2000 + } ], "targets": [ - 4 + 2 ] } }, { + "clientIndex": 0, "watchCurrent": [ [ - 4 + 2 ], - "resume-token-6000" + "resume-token-2000" ] }, { + "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], - "version": 6000 - }, + "version": 2000 + } + }, + { + "clientIndex": 1, + "drainQueue": true, "expectedSnapshotEvents": [ { "errorCode": 0, @@ -3153,25 +3145,23 @@ } ] }, - "Individual documents cannot revert": { + "Ensure correct query results with latency-compensated deletes": { "describeName": "Listens:", - "itName": "Individual documents cannot revert", + "itName": "Ensure correct query results with latency-compensated deletes", "tags": [ ], "config": { "numClients": 1, - "useGarbageCollection": false + "useGarbageCollection": true }, "steps": [ + { + "userDelete": "collection/b" + }, { "userListen": { "query": { "filters": [ - [ - "visible", - "==", - true - ] ], "orderBys": [ ], @@ -3185,11 +3175,6 @@ "queries": [ { "filters": [ - [ - "visible", - "==", - true - ] ], "orderBys": [ ], @@ -3216,8 +3201,18 @@ "hasLocalMutations": false }, "value": { - "v": "v1000", - "visible": true + "a": true + }, + "version": 1000 + }, + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "b": true }, "version": 1000 } @@ -3251,8 +3246,7 @@ "hasLocalMutations": false }, "value": { - "v": "v1000", - "visible": true + "a": true }, "version": 1000 } @@ -3262,11 +3256,6 @@ "hasPendingWrites": false, "query": { "filters": [ - [ - "visible", - "==", - true - ] ], "orderBys": [ ], @@ -3275,39 +3264,13 @@ } ] }, - { - "userUnlisten": [ - 2, - { - "filters": [ - [ - "visible", - "==", - true - ] - ], - "orderBys": [ - ], - "path": "collection" - } - ], - "expectedState": { - "activeTargets": { - } - } - }, - { - "watchRemove": { - "targetIds": [ - 2 - ] - } - }, { "userListen": { "query": { "filters": [ ], + "limit": 10, + "limitType": "LimitToFirst", "orderBys": [ ], "path": "collection" @@ -3324,8 +3287,7 @@ "hasLocalMutations": false }, "value": { - "v": "v1000", - "visible": true + "a": true }, "version": 1000 } @@ -3336,6 +3298,8 @@ "query": { "filters": [ ], + "limit": 10, + "limitType": "LimitToFirst", "orderBys": [ ], "path": "collection" @@ -3344,11 +3308,25 @@ ], "expectedState": { "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + }, "4": { "queries": [ { "filters": [ ], + "limit": 10, + "limitType": "LimitToFirst", "orderBys": [ ], "path": "collection" @@ -3358,10 +3336,50 @@ } } } - }, + } + ] + }, + "Ignores update from inactive target": { + "describeName": "Listens:", + "itName": "Ignores update from inactive target", + "tags": [ + ], + "config": { + "numClients": 1, + "useGarbageCollection": false + }, + "steps": [ { - "watchAck": [ - 4 + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "watchAck": [ + 2 ] }, { @@ -3374,37 +3392,33 @@ "hasLocalMutations": false }, "value": { - "v": "v3000", - "visible": false + "key": "a" }, - "version": 3000 + "version": 1000 } ], "targets": [ - 4 + 2 ] } }, { "watchCurrent": [ [ - 4 + 2 ], - "resume-token-4000" + "resume-token-1000" ] }, { "watchSnapshot": { "targetIds": [ ], - "version": 4000 + "version": 1000 }, "expectedSnapshotEvents": [ { - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "modified": [ + "added": [ { "key": "collection/a", "options": { @@ -3412,12 +3426,14 @@ "hasLocalMutations": false }, "value": { - "v": "v3000", - "visible": false + "key": "a" }, - "version": 3000 + "version": 1000 } ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, "query": { "filters": [ ], @@ -3430,7 +3446,7 @@ }, { "userUnlisten": [ - 4, + 2, { "filters": [ ], @@ -3444,13 +3460,107 @@ } } }, + { + "watchEntity": { + "docs": [ + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "b" + }, + "version": 2000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + } + }, { "watchRemove": { "targetIds": [ - 4 + 2 ] } }, + { + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "resume-token-1000" + } + } + } + } + ] + }, + "Individual (deleted) documents cannot revert": { + "describeName": "Listens:", + "itName": "Individual (deleted) documents cannot revert", + "tags": [ + ], + "config": { + "numClients": 1, + "useGarbageCollection": false + }, + "steps": [ { "userListen": { "query": { @@ -3484,7 +3594,7 @@ "path": "collection" } ], - "resumeToken": "resume-token-1000" + "resumeToken": "" } } } @@ -3504,13 +3614,13 @@ "hasLocalMutations": false }, "value": { - "v": "v2000", - "visible": false + "v": "v1000", + "visible": true }, - "version": 2000 + "version": 1000 } ], - "removedTargets": [ + "targets": [ 2 ] } @@ -3520,17 +3630,31 @@ [ 2 ], - "resume-token-5000" + "resume-token-1000" ] }, { "watchSnapshot": { "targetIds": [ ], - "version": 5000 + "version": 1000 }, "expectedSnapshotEvents": [ { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "v": "v1000", + "visible": true + }, + "version": 1000 + } + ], "errorCode": 0, "fromCache": false, "hasPendingWrites": false, @@ -3598,10 +3722,10 @@ "hasLocalMutations": false }, "value": { - "v": "v3000", - "visible": false + "v": "v1000", + "visible": true }, - "version": 3000 + "version": 1000 } ], "errorCode": 0, @@ -3628,7 +3752,7 @@ "path": "collection" } ], - "resumeToken": "resume-token-4000" + "resumeToken": "" } } } @@ -3641,8 +3765,13 @@ { "watchEntity": { "docs": [ + { + "key": "collection/a", + "value": null, + "version": 3000 + } ], - "targets": [ + "removedTargets": [ 4 ] } @@ -3652,14 +3781,14 @@ [ 4 ], - "resume-token-6000" + "resume-token-4000" ] }, { "watchSnapshot": { "targetIds": [ ], - "version": 6000 + "version": 4000 }, "expectedSnapshotEvents": [ { @@ -3672,67 +3801,91 @@ "orderBys": [ ], "path": "collection" - } + }, + "removed": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "v": "v1000", + "visible": true + }, + "version": 1000 + } + ] } ] - } - ] - }, - "Listen is established in new primary tab": { - "describeName": "Listens:", - "itName": "Listen is established in new primary tab", - "tags": [ - "multi-client" - ], - "config": { - "numClients": 3, - "useGarbageCollection": false - }, - "steps": [ - { - "clientIndex": 0, - "drainQueue": true, - "expectedState": { - "isPrimary": true - } }, { - "clientIndex": 0, - "userListen": { - "query": { + "userUnlisten": [ + 4, + { "filters": [ ], "orderBys": [ ], "path": "collection" - }, - "targetId": 2 - }, + } + ], "expectedState": { "activeTargets": { - "2": { - "queries": [ - { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" + } + } + }, + { + "watchRemove": { + "targetIds": [ + 4 + ] + } + }, + { + "userListen": { + "query": { + "filters": [ + [ + "visible", + "==", + true + ] + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + [ + "visible", + "==", + true + ] + ], + "orderBys": [ + ], + "path": "collection" } ], - "resumeToken": "" + "resumeToken": "resume-token-1000" } } } }, { - "clientIndex": 0, "watchAck": [ 2 ] }, { - "clientIndex": 0, "watchEntity": { "docs": [ { @@ -3742,52 +3895,43 @@ "hasLocalMutations": false }, "value": { - "key": "a" + "v": "v2000", + "visible": false }, - "version": 1000 + "version": 2000 } ], - "targets": [ + "removedTargets": [ 2 ] } }, { - "clientIndex": 0, "watchCurrent": [ [ 2 ], - "resume-token-1000" + "resume-token-5000" ] }, { - "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], - "version": 1000 + "version": 5000 }, "expectedSnapshotEvents": [ { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 - } - ], "errorCode": 0, "fromCache": false, "hasPendingWrites": false, "query": { "filters": [ + [ + "visible", + "==", + true + ] ], "orderBys": [ ], @@ -3797,15 +3941,34 @@ ] }, { - "clientIndex": 1, - "drainQueue": true + "userUnlisten": [ + 2, + { + "filters": [ + [ + "visible", + "==", + true + ] + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } }, { - "clientIndex": 2, - "drainQueue": true + "watchRemove": { + "targetIds": [ + 2 + ] + } }, { - "clientIndex": 2, "userListen": { "query": { "filters": [ @@ -3814,38 +3977,11 @@ ], "path": "collection" }, - "targetId": 2 + "targetId": 4 }, - "expectedSnapshotEvents": [ - { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 - } - ], - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } - ], "expectedState": { "activeTargets": { - "2": { + "4": { "queries": [ { "filters": [ @@ -3855,72 +3991,123 @@ "path": "collection" } ], - "resumeToken": "" + "resumeToken": "resume-token-4000" } } } }, { - "clientIndex": 0, - "drainQueue": true + "watchAck": [ + 4 + ] }, { - "clientIndex": 0, - "shutdown": true, - "expectedState": { - "activeLimboDocs": [ + "watchEntity": { + "docs": [ ], - "activeTargets": { - }, - "enqueuedLimboDocs": [ + "targets": [ + 4 ] } }, { - "clientIndex": 1, - "drainQueue": true + "watchCurrent": [ + [ + 4 + ], + "resume-token-6000" + ] }, { - "clientIndex": 1, - "runTimer": "client_metadata_refresh", + "watchSnapshot": { + "targetIds": [ + ], + "version": 6000 + }, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + } + ] + }, + "Individual documents cannot revert": { + "describeName": "Listens:", + "itName": "Individual documents cannot revert", + "tags": [ + ], + "config": { + "numClients": 1, + "useGarbageCollection": false + }, + "steps": [ + { + "userListen": { + "query": { + "filters": [ + [ + "visible", + "==", + true + ] + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, "expectedState": { "activeTargets": { "2": { "queries": [ { "filters": [ + [ + "visible", + "==", + true + ] ], "orderBys": [ ], "path": "collection" } ], - "resumeToken": "resume-token-1000" + "resumeToken": "" } - }, - "isPrimary": true + } } }, { - "clientIndex": 1, "watchAck": [ 2 ] }, { - "clientIndex": 1, "watchEntity": { "docs": [ { - "key": "collection/b", + "key": "collection/a", "options": { "hasCommittedMutations": false, "hasLocalMutations": false }, "value": { - "key": "b" + "v": "v1000", + "visible": true }, - "version": 2000 + "version": 1000 } ], "targets": [ @@ -3929,38 +4116,33 @@ } }, { - "clientIndex": 1, "watchCurrent": [ [ 2 ], - "resume-token-2000" + "resume-token-1000" ] }, { - "clientIndex": 1, "watchSnapshot": { "targetIds": [ ], - "version": 2000 - } - }, - { - "clientIndex": 2, - "drainQueue": true, + "version": 1000 + }, "expectedSnapshotEvents": [ { "added": [ { - "key": "collection/b", + "key": "collection/a", "options": { "hasCommittedMutations": false, "hasLocalMutations": false }, "value": { - "key": "b" + "v": "v1000", + "visible": true }, - "version": 2000 + "version": 1000 } ], "errorCode": 0, @@ -3968,6 +4150,11 @@ "hasPendingWrites": false, "query": { "filters": [ + [ + "visible", + "==", + true + ] ], "orderBys": [ ], @@ -3975,33 +4162,36 @@ } } ] - } - ] - }, - "Listen is established in newly started primary": { - "describeName": "Listens:", - "itName": "Listen is established in newly started primary", - "tags": [ - "multi-client" - ], - "config": { - "numClients": 3, - "useGarbageCollection": false - }, - "steps": [ + }, { - "clientIndex": 0, - "drainQueue": true, + "userUnlisten": [ + 2, + { + "filters": [ + [ + "visible", + "==", + true + ] + ], + "orderBys": [ + ], + "path": "collection" + } + ], "expectedState": { - "isPrimary": true + "activeTargets": { + } } }, { - "clientIndex": 1, - "drainQueue": true + "watchRemove": { + "targetIds": [ + 2 + ] + } }, { - "clientIndex": 1, "userListen": { "query": { "filters": [ @@ -4010,31 +4200,39 @@ ], "path": "collection" }, - "targetId": 2 + "targetId": 4 }, - "expectedState": { - "activeTargets": { - "2": { - "queries": [ - { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "v": "v1000", + "visible": true + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ ], - "resumeToken": "" + "orderBys": [ + ], + "path": "collection" } } - } - }, - { - "clientIndex": 0, - "drainQueue": true, + ], "expectedState": { "activeTargets": { - "2": { + "4": { "queries": [ { "filters": [ @@ -4050,13 +4248,11 @@ } }, { - "clientIndex": 0, "watchAck": [ - 2 + 4 ] }, { - "clientIndex": 0, "watchEntity": { "docs": [ { @@ -4066,39 +4262,37 @@ "hasLocalMutations": false }, "value": { - "key": "a" + "v": "v3000", + "visible": false }, - "version": 1000 + "version": 3000 } ], "targets": [ - 2 + 4 ] } }, { - "clientIndex": 0, "watchCurrent": [ [ - 2 + 4 ], - "resume-token-1000" + "resume-token-4000" ] }, { - "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], - "version": 1000 - } - }, - { - "clientIndex": 1, - "drainQueue": true, + "version": 4000 + }, "expectedSnapshotEvents": [ { - "added": [ + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "modified": [ { "key": "collection/a", "options": { @@ -4106,14 +4300,12 @@ "hasLocalMutations": false }, "value": { - "key": "a" + "v": "v3000", + "visible": false }, - "version": 1000 + "version": 3000 } ], - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, "query": { "filters": [ ], @@ -4125,30 +4317,55 @@ ] }, { - "clientIndex": 0, - "drainQueue": true - }, - { - "clientIndex": 0, - "shutdown": true, + "userUnlisten": [ + 4, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], "expectedState": { - "activeLimboDocs": [ - ], "activeTargets": { - }, - "enqueuedLimboDocs": [ + } + } + }, + { + "watchRemove": { + "targetIds": [ + 4 ] } }, { - "clientIndex": 2, - "drainQueue": true, + "userListen": { + "query": { + "filters": [ + [ + "visible", + "==", + true + ] + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, "expectedState": { "activeTargets": { "2": { "queries": [ { "filters": [ + [ + "visible", + "==", + true + ] ], "orderBys": [ ], @@ -4157,77 +4374,61 @@ ], "resumeToken": "resume-token-1000" } - }, - "isPrimary": true + } } }, { - "clientIndex": 2, "watchAck": [ 2 ] }, { - "clientIndex": 2, "watchEntity": { "docs": [ { - "key": "collection/b", + "key": "collection/a", "options": { "hasCommittedMutations": false, "hasLocalMutations": false }, "value": { - "key": "b" + "v": "v2000", + "visible": false }, "version": 2000 } ], - "targets": [ + "removedTargets": [ 2 ] } }, { - "clientIndex": 2, "watchCurrent": [ [ 2 ], - "resume-token-2000" + "resume-token-5000" ] }, { - "clientIndex": 2, "watchSnapshot": { "targetIds": [ ], - "version": 2000 - } - }, - { - "clientIndex": 1, - "drainQueue": true, + "version": 5000 + }, "expectedSnapshotEvents": [ { - "added": [ - { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "b" - }, - "version": 2000 - } - ], "errorCode": 0, "fromCache": false, "hasPendingWrites": false, "query": { "filters": [ + [ + "visible", + "==", + true + ] ], "orderBys": [ ], @@ -4235,46 +4436,77 @@ } } ] - } - ] - }, - "Listen is re-listened to after primary tab failover": { - "describeName": "Listens:", - "itName": "Listen is re-listened to after primary tab failover", - "tags": [ - "multi-client" - ], - "config": { - "numClients": 3, - "useGarbageCollection": false - }, - "steps": [ - { - "clientIndex": 0, - "drainQueue": true, - "expectedState": { - "isPrimary": true - } - }, - { - "clientIndex": 1, - "drainQueue": true }, { - "clientIndex": 1, - "userListen": { - "query": { + "userUnlisten": [ + 2, + { "filters": [ + [ + "visible", + "==", + true + ] ], "orderBys": [ ], "path": "collection" - }, - "targetId": 2 - }, - "expectedState": { + } + ], + "expectedState": { "activeTargets": { - "2": { + } + } + }, + { + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, + { + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 4 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "v": "v3000", + "visible": false + }, + "version": 3000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + "4": { "queries": [ { "filters": [ @@ -4284,14 +4516,86 @@ "path": "collection" } ], - "resumeToken": "" + "resumeToken": "resume-token-4000" } } } }, + { + "watchAck": [ + 4 + ] + }, + { + "watchEntity": { + "docs": [ + ], + "targets": [ + 4 + ] + } + }, + { + "watchCurrent": [ + [ + 4 + ], + "resume-token-6000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 6000 + }, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + } + ] + }, + "Listen is established in new primary tab": { + "describeName": "Listens:", + "itName": "Listen is established in new primary tab", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 3, + "useGarbageCollection": false + }, + "steps": [ { "clientIndex": 0, "drainQueue": true, + "expectedState": { + "isPrimary": true + } + }, + { + "clientIndex": 0, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, "expectedState": { "activeTargets": { "2": { @@ -4351,11 +4655,7 @@ "targetIds": [ ], "version": 1000 - } - }, - { - "clientIndex": 1, - "drainQueue": true, + }, "expectedSnapshotEvents": [ { "added": [ @@ -4384,6 +4684,10 @@ } ] }, + { + "clientIndex": 1, + "drainQueue": true + }, { "clientIndex": 2, "drainQueue": true @@ -4527,34 +4831,7 @@ "targetIds": [ ], "version": 2000 - }, - "expectedSnapshotEvents": [ - { - "added": [ - { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "b" - }, - "version": 2000 - } - ], - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } - ] + } }, { "clientIndex": 2, @@ -4589,17 +4866,30 @@ } ] }, - "Listens are reestablished after network disconnect": { + "Listen is established in newly started primary": { "describeName": "Listens:", - "itName": "Listens are reestablished after network disconnect", + "itName": "Listen is established in newly started primary", "tags": [ + "multi-client" ], "config": { - "numClients": 1, - "useGarbageCollection": true + "numClients": 3, + "useGarbageCollection": false }, "steps": [ { + "clientIndex": 0, + "drainQueue": true, + "expectedState": { + "isPrimary": true + } + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, "userListen": { "query": { "filters": [ @@ -4624,16 +4914,37 @@ ], "resumeToken": "" } - }, - "watchStreamRequestCount": 1 + } + } + }, + { + "clientIndex": 0, + "drainQueue": true, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } } }, { + "clientIndex": 0, "watchAck": [ 2 ] }, { + "clientIndex": 0, "watchEntity": { "docs": [ { @@ -4654,6 +4965,7 @@ } }, { + "clientIndex": 0, "watchCurrent": [ [ 2 @@ -4662,11 +4974,16 @@ ] }, { + "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], "version": 1000 - }, + } + }, + { + "clientIndex": 1, + "drainQueue": true, "expectedSnapshotEvents": [ { "added": [ @@ -4696,21 +5013,12 @@ ] }, { - "enableNetwork": false, - "expectedSnapshotEvents": [ - { - "errorCode": 0, - "fromCache": true, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } - ], + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "shutdown": true, "expectedState": { "activeLimboDocs": [ ], @@ -4721,7 +5029,8 @@ } }, { - "enableNetwork": true, + "clientIndex": 2, + "drainQueue": true, "expectedState": { "activeTargets": { "2": { @@ -4737,15 +5046,17 @@ "resumeToken": "resume-token-1000" } }, - "watchStreamRequestCount": 2 + "isPrimary": true } }, { + "clientIndex": 2, "watchAck": [ 2 ] }, { + "clientIndex": 2, "watchEntity": { "docs": [ { @@ -4766,6 +5077,7 @@ } }, { + "clientIndex": 2, "watchCurrent": [ [ 2 @@ -4774,13 +5086,18 @@ ] }, { + "clientIndex": 2, "watchSnapshot": { "targetIds": [ ], "version": 2000 - }, - "expectedSnapshotEvents": [ - { + } + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { "added": [ { "key": "collection/b", @@ -4809,9 +5126,9 @@ } ] }, - "Mirror queries from different secondary client": { + "Listen is re-listened to after primary tab failover": { "describeName": "Listens:", - "itName": "Mirror queries from different secondary client", + "itName": "Listen is re-listened to after primary tab failover", "tags": [ "multi-client" ], @@ -4822,76 +5139,22 @@ "steps": [ { "clientIndex": 0, - "drainQueue": true - }, - { - "applyClientState": { - "visibility": "visible" - }, - "clientIndex": 0 - }, - { - "clientIndex": 1, - "drainQueue": true - }, - { - "clientIndex": 1, - "userListen": { - "query": { - "filters": [ - ], - "limit": 2, - "limitType": "LimitToFirst", - "orderBys": [ - [ - "val", - "asc" - ] - ], - "path": "collection" - }, - "targetId": 2 - }, + "drainQueue": true, "expectedState": { - "activeTargets": { - "2": { - "queries": [ - { - "filters": [ - ], - "limit": 2, - "limitType": "LimitToFirst", - "orderBys": [ - [ - "val", - "asc" - ] - ], - "path": "collection" - } - ], - "resumeToken": "" - } - } + "isPrimary": true } }, { - "clientIndex": 2, + "clientIndex": 1, "drainQueue": true }, { - "clientIndex": 2, + "clientIndex": 1, "userListen": { "query": { "filters": [ ], - "limit": 2, - "limitType": "LimitToLast", "orderBys": [ - [ - "val", - "desc" - ] ], "path": "collection" }, @@ -4904,13 +5167,7 @@ { "filters": [ ], - "limit": 2, - "limitType": "LimitToLast", "orderBys": [ - [ - "val", - "desc" - ] ], "path": "collection" } @@ -4930,26 +5187,7 @@ { "filters": [ ], - "limit": 2, - "limitType": "LimitToLast", - "orderBys": [ - [ - "val", - "desc" - ] - ], - "path": "collection" - }, - { - "filters": [ - ], - "limit": 2, - "limitType": "LimitToFirst", "orderBys": [ - [ - "val", - "asc" - ] ], "path": "collection" } @@ -4976,18 +5214,7 @@ "hasLocalMutations": false }, "value": { - "val": 0 - }, - "version": 1000 - }, - { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "val": 1 + "key": "a" }, "version": 1000 } @@ -5027,18 +5254,7 @@ "hasLocalMutations": false }, "value": { - "val": 0 - }, - "version": 1000 - }, - { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "val": 1 + "key": "a" }, "version": 1000 } @@ -5049,13 +5265,7 @@ "query": { "filters": [ ], - "limit": 2, - "limitType": "LimitToFirst", "orderBys": [ - [ - "val", - "asc" - ] ], "path": "collection" } @@ -5064,21 +5274,23 @@ }, { "clientIndex": 2, - "drainQueue": true, + "drainQueue": true + }, + { + "clientIndex": 2, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, "expectedSnapshotEvents": [ { "added": [ - { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "val": 1 - }, - "version": 1000 - }, { "key": "collection/a", "options": { @@ -5086,7 +5298,7 @@ "hasLocalMutations": false }, "value": { - "val": 0 + "key": "a" }, "version": 1000 } @@ -5097,45 +5309,52 @@ "query": { "filters": [ ], - "limit": 2, - "limitType": "LimitToLast", "orderBys": [ - [ - "val", - "desc" - ] ], "path": "collection" } } - ] - }, - { - "clientIndex": 2, - "userUnlisten": [ - 2, - { - "filters": [ - ], - "limit": 2, - "limitType": "LimitToLast", - "orderBys": [ - [ - "val", - "desc" - ] - ], - "path": "collection" - } ], "expectedState": { "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } } } }, { "clientIndex": 0, - "drainQueue": true, + "drainQueue": true + }, + { + "clientIndex": 0, + "shutdown": true, + "expectedState": { + "activeLimboDocs": [ + ], + "activeTargets": { + }, + "enqueuedLimboDocs": [ + ] + } + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "runTimer": "client_metadata_refresh", "expectedState": { "activeTargets": { "2": { @@ -5143,34 +5362,35 @@ { "filters": [ ], - "limit": 2, - "limitType": "LimitToFirst", "orderBys": [ - [ - "val", - "asc" - ] ], "path": "collection" } ], - "resumeToken": "" + "resumeToken": "resume-token-1000" } - } + }, + "isPrimary": true } }, { - "clientIndex": 0, + "clientIndex": 1, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 1, "watchEntity": { "docs": [ { - "key": "collection/c", + "key": "collection/b", "options": { "hasCommittedMutations": false, "hasLocalMutations": false }, "value": { - "val": 0 + "key": "b" }, "version": 2000 } @@ -5181,20 +5401,688 @@ } }, { - "clientIndex": 0, - "watchSnapshot": { - "targetIds": [ + "clientIndex": 1, + "watchCurrent": [ + [ + 2 ], - "version": 2000 - } + "resume-token-2000" + ] }, { "clientIndex": 1, - "drainQueue": true, - "expectedSnapshotEvents": [ - { - "added": [ - { + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "b" + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 2, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "b" + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + } + ] + }, + "Listens are reestablished after network disconnect": { + "describeName": "Listens:", + "itName": "Listens are reestablished after network disconnect", + "tags": [ + ], + "config": { + "numClients": 1, + "useGarbageCollection": true + }, + "steps": [ + { + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + }, + "watchStreamRequestCount": 1 + } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "enableNetwork": false, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeLimboDocs": [ + ], + "activeTargets": { + }, + "enqueuedLimboDocs": [ + ] + } + }, + { + "enableNetwork": true, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "resume-token-1000" + } + }, + "watchStreamRequestCount": 2 + } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "b" + }, + "version": 2000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-2000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "b" + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + } + ] + }, + "Mirror queries from different secondary client": { + "describeName": "Listens:", + "itName": "Mirror queries from different secondary client", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 3, + "useGarbageCollection": false + }, + "steps": [ + { + "clientIndex": 0, + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userListen": { + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "val", + "asc" + ] + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "val", + "asc" + ] + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 2, + "drainQueue": true + }, + { + "clientIndex": 2, + "userListen": { + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "val", + "desc" + ] + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "val", + "desc" + ] + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "drainQueue": true, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "val", + "desc" + ] + ], + "path": "collection" + }, + { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "val", + "asc" + ] + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "val": 0 + }, + "version": 1000 + }, + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "val": 1 + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + } + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "val": 0 + }, + "version": 1000 + }, + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "val": 1 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "val", + "asc" + ] + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 2, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "val": 1 + }, + "version": 1000 + }, + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "val": 0 + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "val", + "desc" + ] + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 2, + "userUnlisten": [ + 2, + { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToLast", + "orderBys": [ + [ + "val", + "desc" + ] + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "drainQueue": true, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "limit": 2, + "limitType": "LimitToFirst", + "orderBys": [ + [ + "val", + "asc" + ] + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "val": 0 + }, + "version": 2000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + } + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { "key": "collection/c", "options": { "hasCommittedMutations": false, @@ -6414,16 +7302,294 @@ { "clientIndex": 0, "drainQueue": true, - "expectedState": { - "activeTargets": { + "expectedState": { + "activeTargets": { + } + } + } + ] + }, + "New client becomes primary if no client has its network enabled": { + "describeName": "Listens:", + "itName": "New client becomes primary if no client has its network enabled", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 3, + "useGarbageCollection": false + }, + "steps": [ + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "enableNetwork": false, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeLimboDocs": [ + ], + "activeTargets": { + }, + "enqueuedLimboDocs": [ + ] + } + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 2, + "drainQueue": true, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "resume-token-1000" + } + }, + "isPrimary": true + } + }, + { + "clientIndex": 2, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 2, + "watchEntity": { + "docs": [ + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 2, + "watchCurrent": [ + [ + 2 + ], + "resume-token-2000" + ] + }, + { + "clientIndex": 2, + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + } + }, + { + "clientIndex": 0, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } } - } + ] + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] } ] }, - "New client becomes primary if no client has its network enabled": { + "New client uses existing online state": { "describeName": "Listens:", - "itName": "New client becomes primary if no client has its network enabled", + "itName": "New client uses existing online state", "tags": [ "multi-client" ], @@ -6516,6 +7682,18 @@ "clientIndex": 1, "drainQueue": true }, + { + "clientIndex": 1, + "enableNetwork": false, + "expectedState": { + "activeLimboDocs": [ + ], + "activeTargets": { + }, + "enqueuedLimboDocs": [ + ] + } + }, { "clientIndex": 1, "userListen": { @@ -6590,8 +7768,21 @@ } }, { - "clientIndex": 1, - "drainQueue": true, + "clientIndex": 2, + "drainQueue": true + }, + { + "clientIndex": 2, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, "expectedSnapshotEvents": [ { "errorCode": 0, @@ -6605,11 +7796,7 @@ "path": "collection" } } - ] - }, - { - "clientIndex": 2, - "drainQueue": true, + ], "expectedState": { "activeTargets": { "2": { @@ -6622,52 +7809,27 @@ "path": "collection" } ], - "resumeToken": "resume-token-1000" + "resumeToken": "" } - }, - "isPrimary": true - } - }, - { - "clientIndex": 2, - "watchAck": [ - 2 - ] - }, - { - "clientIndex": 2, - "watchEntity": { - "docs": [ - ], - "targets": [ - 2 - ] + } } }, { "clientIndex": 2, - "watchCurrent": [ - [ - 2 - ], - "resume-token-2000" - ] - }, - { - "clientIndex": 2, - "watchSnapshot": { - "targetIds": [ - ], - "version": 2000 - } - }, - { - "clientIndex": 0, - "drainQueue": true, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, "expectedSnapshotEvents": [ { "errorCode": 0, - "fromCache": false, + "fromCache": true, "hasPendingWrites": false, "query": { "filters": [ @@ -6677,36 +7839,34 @@ "path": "collection" } } - ] - }, - { - "clientIndex": 1, - "drainQueue": true, - "expectedSnapshotEvents": [ - { - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ + ], + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } ], - "path": "collection" + "resumeToken": "" } } - ] + } } ] }, - "New client uses existing online state": { + "Offline state doesn't persist if primary is shut down": { "describeName": "Listens:", - "itName": "New client uses existing online state", + "itName": "Offline state doesn't persist if primary is shut down", "tags": [ "multi-client" ], "config": { - "numClients": 3, + "numClients": 2, "useGarbageCollection": false }, "steps": [ @@ -6745,40 +7905,11 @@ }, { "clientIndex": 0, - "watchAck": [ - 2 - ] - }, - { - "clientIndex": 0, - "watchEntity": { - "docs": [ - ], - "targets": [ - 2 - ] - } - }, - { - "clientIndex": 0, - "watchCurrent": [ - [ - 2 - ], - "resume-token-1000" - ] - }, - { - "clientIndex": 0, - "watchSnapshot": { - "targetIds": [ - ], - "version": 1000 - }, + "enableNetwork": false, "expectedSnapshotEvents": [ { "errorCode": 0, - "fromCache": false, + "fromCache": true, "hasPendingWrites": false, "query": { "filters": [ @@ -6788,15 +7919,19 @@ "path": "collection" } } - ] - }, - { - "clientIndex": 1, - "drainQueue": true + ], + "expectedState": { + "activeLimboDocs": [ + ], + "activeTargets": { + }, + "enqueuedLimboDocs": [ + ] + } }, { - "clientIndex": 1, - "enableNetwork": false, + "clientIndex": 0, + "shutdown": true, "expectedState": { "activeLimboDocs": [ ], @@ -6808,6 +7943,51 @@ }, { "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + } + ] + }, + "Omits global resume tokens for a short while": { + "describeName": "Listens:", + "itName": "Omits global resume tokens for a short while", + "tags": [ + "durable-persistence" + ], + "config": { + "numClients": 1, + "useGarbageCollection": false + }, + "steps": [ + { "userListen": { "query": { "filters": [ @@ -6818,20 +7998,6 @@ }, "targetId": 2 }, - "expectedSnapshotEvents": [ - { - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } - ], "expectedState": { "activeTargets": { "2": { @@ -6850,16 +8016,61 @@ } }, { - "clientIndex": 0, - "drainQueue": true + "watchAck": [ + 2 + ] }, { - "clientIndex": 0, - "enableNetwork": false, + "watchEntity": { + "docs": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, "expectedSnapshotEvents": [ { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], "errorCode": 0, - "fromCache": true, + "fromCache": false, "hasPendingWrites": false, "query": { "filters": [ @@ -6869,7 +8080,18 @@ "path": "collection" } } - ], + ] + }, + { + "watchSnapshot": { + "resumeToken": "resume-token-2000", + "targetIds": [ + ], + "version": 2000 + } + }, + { + "restart": true, "expectedState": { "activeLimboDocs": [ ], @@ -6880,11 +8102,6 @@ } }, { - "clientIndex": 2, - "drainQueue": true - }, - { - "clientIndex": 2, "userListen": { "query": { "filters": [ @@ -6897,6 +8114,19 @@ }, "expectedSnapshotEvents": [ { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], "errorCode": 0, "fromCache": true, "hasPendingWrites": false, @@ -6921,27 +8151,34 @@ "path": "collection" } ], - "resumeToken": "" + "resumeToken": "resume-token-1000" } } } }, { - "clientIndex": 2, - "userListen": { - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - }, - "targetId": 2 + "watchAck": [ + 2 + ] + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-3000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 3000 }, "expectedSnapshotEvents": [ { "errorCode": 0, - "fromCache": true, + "fromCache": false, "hasPendingWrites": false, "query": { "filters": [ @@ -6951,43 +8188,22 @@ "path": "collection" } } - ], - "expectedState": { - "activeTargets": { - "2": { - "queries": [ - { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - ], - "resumeToken": "" - } - } - } + ] } ] }, - "Offline state doesn't persist if primary is shut down": { + "Persists global resume tokens if the snapshot is old enough": { "describeName": "Listens:", - "itName": "Offline state doesn't persist if primary is shut down", + "itName": "Persists global resume tokens if the snapshot is old enough", "tags": [ - "multi-client" + "durable-persistence" ], "config": { - "numClients": 2, + "numClients": 1, "useGarbageCollection": false }, "steps": [ { - "clientIndex": 0, - "drainQueue": true - }, - { - "clientIndex": 0, "userListen": { "query": { "filters": [ @@ -7016,12 +8232,61 @@ } }, { - "clientIndex": 0, - "enableNetwork": false, + "watchAck": [ + 2 + ] + }, + { + "watchEntity": { + "docs": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, "expectedSnapshotEvents": [ { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], "errorCode": 0, - "fromCache": true, + "fromCache": false, "hasPendingWrites": false, "query": { "filters": [ @@ -7031,19 +8296,18 @@ "path": "collection" } } - ], - "expectedState": { - "activeLimboDocs": [ + ] + }, + { + "watchSnapshot": { + "resumeToken": "resume-token-minutes-later", + "targetIds": [ ], - "activeTargets": { - }, - "enqueuedLimboDocs": [ - ] + "version": 300001000 } }, { - "clientIndex": 0, - "shutdown": true, + "restart": true, "expectedState": { "activeLimboDocs": [ ], @@ -7054,11 +8318,6 @@ } }, { - "clientIndex": 1, - "drainQueue": true - }, - { - "clientIndex": 1, "userListen": { "query": { "filters": [ @@ -7069,6 +8328,33 @@ }, "targetId": 2 }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], "expectedState": { "activeTargets": { "2": { @@ -7081,18 +8367,51 @@ "path": "collection" } ], - "resumeToken": "" + "resumeToken": "resume-token-minutes-later" } } } + }, + { + "watchAck": [ + 2 + ] + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-even-later" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 300002000 + }, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] } ] }, - "Omits global resume tokens for a short while": { + "Persists global resume tokens on unlisten": { "describeName": "Listens:", - "itName": "Omits global resume tokens for a short while", + "itName": "Persists global resume tokens on unlisten", "tags": [ - "durable-persistence" ], "config": { "numClients": 1, @@ -7203,13 +8522,25 @@ } }, { - "restart": true, + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], "expectedState": { - "activeLimboDocs": [ - ], "activeTargets": { - }, - "enqueuedLimboDocs": [ + } + } + }, + { + "watchRemove": { + "targetIds": [ + 2 ] } }, @@ -7263,7 +8594,7 @@ "path": "collection" } ], - "resumeToken": "resume-token-1000" + "resumeToken": "resume-token-2000" } } } @@ -7304,11 +8635,10 @@ } ] }, - "Persists global resume tokens if the snapshot is old enough": { + "Persists resume token sent with target": { "describeName": "Listens:", - "itName": "Persists global resume tokens if the snapshot is old enough", + "itName": "Persists resume token sent with target", "tags": [ - "durable-persistence" ], "config": { "numClients": 1, @@ -7348,6 +8678,44 @@ 2 ] }, + { + "watchEntity": { + "docs": [ + ], + "targets": [ + 2 + ] + } + }, + { + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, { "watchEntity": { "docs": [ @@ -7360,7 +8728,7 @@ "value": { "key": "a" }, - "version": 1000 + "version": 2000 } ], "targets": [ @@ -7369,18 +8737,19 @@ } }, { - "watchCurrent": [ - [ + "watchSnapshot": { + "resumeToken": "resume-token-2000", + "targetIds": [ 2 ], - "resume-token-1000" - ] + "version": 2000 + } }, { "watchSnapshot": { "targetIds": [ ], - "version": 1000 + "version": 2000 }, "expectedSnapshotEvents": [ { @@ -7394,7 +8763,7 @@ "value": { "key": "a" }, - "version": 1000 + "version": 2000 } ], "errorCode": 0, @@ -7411,21 +8780,25 @@ ] }, { - "watchSnapshot": { - "resumeToken": "resume-token-minutes-later", - "targetIds": [ - ], - "version": 300001000 + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } } }, { - "restart": true, - "expectedState": { - "activeLimboDocs": [ - ], - "activeTargets": { - }, - "enqueuedLimboDocs": [ + "watchRemove": { + "targetIds": [ + 2 ] } }, @@ -7452,7 +8825,7 @@ "value": { "key": "a" }, - "version": 1000 + "version": 2000 } ], "errorCode": 0, @@ -7479,7 +8852,7 @@ "path": "collection" } ], - "resumeToken": "resume-token-minutes-later" + "resumeToken": "resume-token-2000" } } } @@ -7489,19 +8862,28 @@ 2 ] }, + { + "watchEntity": { + "docs": [ + ], + "targets": [ + 2 + ] + } + }, { "watchCurrent": [ [ 2 ], - "resume-token-even-later" + "resume-token-3000" ] }, { "watchSnapshot": { "targetIds": [ ], - "version": 300002000 + "version": 3000 }, "expectedSnapshotEvents": [ { @@ -7520,27 +8902,106 @@ } ] }, - "Persists global resume tokens on unlisten": { + "Previous primary immediately regains primary lease": { "describeName": "Listens:", - "itName": "Persists global resume tokens on unlisten", + "itName": "Previous primary immediately regains primary lease", "tags": [ + "multi-client" ], "config": { - "numClients": 1, + "numClients": 2, "useGarbageCollection": false }, "steps": [ { - "userListen": { - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - }, - "targetId": 2 + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "applyClientState": { + "primary": true }, + "clientIndex": 1, "expectedState": { "activeTargets": { "2": { @@ -7553,17 +9014,20 @@ "path": "collection" } ], - "resumeToken": "" + "resumeToken": "resume-token-1000" } - } + }, + "isPrimary": true } }, { + "clientIndex": 1, "watchAck": [ 2 ] }, { + "clientIndex": 1, "watchEntity": { "docs": [ { @@ -7575,7 +9039,7 @@ "value": { "key": "a" }, - "version": 1000 + "version": 2000 } ], "targets": [ @@ -7584,89 +9048,44 @@ } }, { + "clientIndex": 1, "watchCurrent": [ [ 2 ], - "resume-token-1000" - ] - }, - { - "watchSnapshot": { - "targetIds": [ - ], - "version": 1000 - }, - "expectedSnapshotEvents": [ - { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 - } - ], - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } + "resume-token-2000" ] }, { + "clientIndex": 1, "watchSnapshot": { - "resumeToken": "resume-token-2000", "targetIds": [ ], "version": 2000 } }, { - "userUnlisten": [ - 2, - { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - ], + "clientIndex": 1, + "shutdown": true, "expectedState": { + "activeLimboDocs": [ + ], "activeTargets": { - } + }, + "enqueuedLimboDocs": [ + ] } }, { - "watchRemove": { - "targetIds": [ - 2 - ] + "clientIndex": 0, + "drainQueue": true, + "expectedState": { + "isPrimary": true } }, { - "userListen": { - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - }, - "targetId": 2 - }, + "clientIndex": 0, + "runTimer": "client_metadata_refresh", "expectedSnapshotEvents": [ { "added": [ @@ -7679,11 +9098,11 @@ "value": { "key": "a" }, - "version": 1000 + "version": 2000 } ], "errorCode": 0, - "fromCache": true, + "fromCache": false, "hasPendingWrites": false, "query": { "filters": [ @@ -7708,56 +9127,36 @@ ], "resumeToken": "resume-token-2000" } - } + }, + "isPrimary": true } - }, - { - "watchAck": [ - 2 - ] - }, - { - "watchCurrent": [ - [ - 2 - ], - "resume-token-3000" - ] - }, - { - "watchSnapshot": { - "targetIds": [ - ], - "version": 3000 - }, - "expectedSnapshotEvents": [ - { - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } - ] } ] }, - "Persists resume token sent with target": { + "Query bounces between primaries": { "describeName": "Listens:", - "itName": "Persists resume token sent with target", + "itName": "Query bounces between primaries", "tags": [ + "multi-client" ], "config": { - "numClients": 1, + "numClients": 3, "useGarbageCollection": false }, "steps": [ { + "clientIndex": 1, + "drainQueue": true, + "expectedState": { + "isPrimary": true + } + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, "userListen": { "query": { "filters": [ @@ -7786,13 +9185,46 @@ } }, { + "clientIndex": 1, + "drainQueue": true, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 1, "watchAck": [ 2 ] }, { + "clientIndex": 1, "watchEntity": { "docs": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } ], "targets": [ 2 @@ -7800,6 +9232,7 @@ } }, { + "clientIndex": 1, "watchCurrent": [ [ 2 @@ -7808,13 +9241,31 @@ ] }, { + "clientIndex": 1, "watchSnapshot": { "targetIds": [ ], "version": 1000 - }, + } + }, + { + "clientIndex": 0, + "drainQueue": true, "expectedSnapshotEvents": [ { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], "errorCode": 0, "fromCache": false, "hasPendingWrites": false, @@ -7829,16 +9280,65 @@ ] }, { + "clientIndex": 2, + "drainQueue": true + }, + { + "applyClientState": { + "primary": true + }, + "clientIndex": 2, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "resume-token-1000" + } + }, + "isPrimary": true + } + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "runTimer": "client_metadata_refresh", + "expectedState": { + "isPrimary": false + } + }, + { + "clientIndex": 2, + "drainQueue": true + }, + { + "clientIndex": 2, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 2, "watchEntity": { "docs": [ { - "key": "collection/a", + "key": "collection/b", "options": { "hasCommittedMutations": false, "hasLocalMutations": false }, "value": { - "key": "a" + "key": "b" }, "version": 2000 } @@ -7849,31 +9349,36 @@ } }, { - "watchSnapshot": { - "resumeToken": "resume-token-2000", - "targetIds": [ + "clientIndex": 2, + "watchCurrent": [ + [ 2 ], - "version": 2000 - } + "resume-token-2000" + ] }, { + "clientIndex": 2, "watchSnapshot": { "targetIds": [ ], "version": 2000 - }, + } + }, + { + "clientIndex": 0, + "drainQueue": true, "expectedSnapshotEvents": [ { "added": [ { - "key": "collection/a", + "key": "collection/b", "options": { "hasCommittedMutations": false, "hasLocalMutations": false }, "value": { - "key": "a" + "key": "b" }, "version": 2000 } @@ -7892,66 +9397,14 @@ ] }, { - "userUnlisten": [ - 2, - { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - ], - "expectedState": { - "activeTargets": { - } - } - }, - { - "watchRemove": { - "targetIds": [ - 2 - ] - } + "clientIndex": 1, + "drainQueue": true }, { - "userListen": { - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - }, - "targetId": 2 + "applyClientState": { + "primary": true }, - "expectedSnapshotEvents": [ - { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 2000 - } - ], - "errorCode": 0, - "fromCache": true, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } - ], + "clientIndex": 1, "expectedState": { "activeTargets": { "2": { @@ -7966,17 +9419,31 @@ ], "resumeToken": "resume-token-2000" } - } + }, + "isPrimary": true } }, { + "clientIndex": 1, "watchAck": [ 2 ] }, { + "clientIndex": 1, "watchEntity": { "docs": [ + { + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "c" + }, + "version": 3000 + } ], "targets": [ 2 @@ -7984,6 +9451,7 @@ } }, { + "clientIndex": 1, "watchCurrent": [ [ 2 @@ -7992,13 +9460,31 @@ ] }, { + "clientIndex": 1, "watchSnapshot": { "targetIds": [ ], "version": 3000 - }, + } + }, + { + "clientIndex": 0, + "drainQueue": true, "expectedSnapshotEvents": [ { + "added": [ + { + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "c" + }, + "version": 3000 + } + ], "errorCode": 0, "fromCache": false, "hasPendingWrites": false, @@ -8014,9 +9500,9 @@ } ] }, - "Previous primary immediately regains primary lease": { + "Query is executed by primary client": { "describeName": "Listens:", - "itName": "Previous primary immediately regains primary lease", + "itName": "Query is executed by primary client", "tags": [ "multi-client" ], @@ -8030,7 +9516,17 @@ "drainQueue": true }, { - "clientIndex": 0, + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, "userListen": { "query": { "filters": [ @@ -8060,60 +9556,7 @@ }, { "clientIndex": 0, - "watchAck": [ - 2 - ] - }, - { - "clientIndex": 0, - "watchEntity": { - "docs": [ - ], - "targets": [ - 2 - ] - } - }, - { - "clientIndex": 0, - "watchCurrent": [ - [ - 2 - ], - "resume-token-1000" - ] - }, - { - "clientIndex": 0, - "watchSnapshot": { - "targetIds": [ - ], - "version": 1000 - }, - "expectedSnapshotEvents": [ - { - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } - ] - }, - { - "clientIndex": 1, - "drainQueue": true - }, - { - "applyClientState": { - "primary": true - }, - "clientIndex": 1, + "drainQueue": true, "expectedState": { "activeTargets": { "2": { @@ -8126,20 +9569,19 @@ "path": "collection" } ], - "resumeToken": "resume-token-1000" + "resumeToken": "" } - }, - "isPrimary": true + } } }, { - "clientIndex": 1, + "clientIndex": 0, "watchAck": [ 2 ] }, { - "clientIndex": 1, + "clientIndex": 0, "watchEntity": { "docs": [ { @@ -8147,57 +9589,29 @@ "options": { "hasCommittedMutations": false, "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 2000 - } - ], - "targets": [ - 2 - ] - } - }, - { - "clientIndex": 1, - "watchCurrent": [ - [ - 2 - ], - "resume-token-2000" - ] - }, - { - "clientIndex": 1, - "watchSnapshot": { - "targetIds": [ - ], - "version": 2000 - } - }, - { - "clientIndex": 1, - "shutdown": true, - "expectedState": { - "activeLimboDocs": [ + }, + "value": { + "key": "a" + }, + "version": 1000 + } ], - "activeTargets": { - }, - "enqueuedLimboDocs": [ + "targets": [ + 2 ] } }, { "clientIndex": 0, - "drainQueue": true, - "expectedState": { - "isPrimary": true + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 } }, { - "clientIndex": 0, - "runTimer": "client_metadata_refresh", + "clientIndex": 1, + "drainQueue": true, "expectedSnapshotEvents": [ { "added": [ @@ -8210,11 +9624,11 @@ "value": { "key": "a" }, - "version": 2000 + "version": 1000 } ], "errorCode": 0, - "fromCache": false, + "fromCache": true, "hasPendingWrites": false, "query": { "filters": [ @@ -8224,51 +9638,73 @@ "path": "collection" } } - ], - "expectedState": { - "activeTargets": { - "2": { - "queries": [ - { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } + ] + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-2000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + } + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ ], - "resumeToken": "resume-token-2000" + "orderBys": [ + ], + "path": "collection" } - }, - "isPrimary": true - } + } + ] } ] }, - "Query bounces between primaries": { + "Query is joined by primary client": { "describeName": "Listens:", - "itName": "Query bounces between primaries", + "itName": "Query is joined by primary client", "tags": [ "multi-client" ], "config": { - "numClients": 3, + "numClients": 2, "useGarbageCollection": false }, "steps": [ { - "clientIndex": 1, + "clientIndex": 0, "drainQueue": true, "expectedState": { "isPrimary": true } }, { - "clientIndex": 0, + "clientIndex": 1, "drainQueue": true }, { - "clientIndex": 0, + "clientIndex": 1, "userListen": { "query": { "filters": [ @@ -8297,7 +9733,7 @@ } }, { - "clientIndex": 1, + "clientIndex": 0, "drainQueue": true, "expectedState": { "activeTargets": { @@ -8317,13 +9753,13 @@ } }, { - "clientIndex": 1, + "clientIndex": 0, "watchAck": [ 2 ] }, { - "clientIndex": 1, + "clientIndex": 0, "watchEntity": { "docs": [ { @@ -8344,24 +9780,24 @@ } }, { - "clientIndex": 1, + "clientIndex": 0, "watchCurrent": [ [ 2 ], - "resume-token-1000" + "resume-token-100" ] }, { - "clientIndex": 1, + "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], - "version": 1000 + "version": 100 } }, { - "clientIndex": 0, + "clientIndex": 1, "drainQueue": true, "expectedSnapshotEvents": [ { @@ -8392,14 +9828,88 @@ ] }, { - "clientIndex": 2, + "clientIndex": 0, "drainQueue": true }, { - "applyClientState": { - "primary": true + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "b" + }, + "version": 2000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + } + }, + { + "clientIndex": 0, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 }, - "clientIndex": 2, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + }, + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "b" + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], "expectedState": { "activeTargets": { "2": { @@ -8412,73 +9922,69 @@ "path": "collection" } ], - "resumeToken": "resume-token-1000" + "resumeToken": "" } - }, - "isPrimary": true - } - }, - { - "clientIndex": 1, - "drainQueue": true - }, - { - "clientIndex": 1, - "runTimer": "client_metadata_refresh", - "expectedState": { - "isPrimary": false + } } }, { - "clientIndex": 2, - "drainQueue": true - }, - { - "clientIndex": 2, - "watchAck": [ - 2 - ] - }, - { - "clientIndex": 2, + "clientIndex": 0, "watchEntity": { "docs": [ { - "key": "collection/b", + "key": "collection/c", "options": { "hasCommittedMutations": false, "hasLocalMutations": false }, "value": { - "key": "b" + "key": "c" }, - "version": 2000 + "version": 3000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 3000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "c" + }, + "version": 3000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" } - ], - "targets": [ - 2 - ] - } - }, - { - "clientIndex": 2, - "watchCurrent": [ - [ - 2 - ], - "resume-token-2000" + } ] }, { - "clientIndex": 2, - "watchSnapshot": { - "targetIds": [ - ], - "version": 2000 - } - }, - { - "clientIndex": 0, + "clientIndex": 1, "drainQueue": true, "expectedSnapshotEvents": [ { @@ -8505,18 +10011,113 @@ ], "path": "collection" } + }, + { + "added": [ + { + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "c" + }, + "version": 3000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } } ] + } + ] + }, + "Query is rejected and re-listened to": { + "describeName": "Listens:", + "itName": "Query is rejected and re-listened to", + "tags": [ + ], + "config": { + "numClients": 1, + "useGarbageCollection": false + }, + "steps": [ + { + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } }, { - "clientIndex": 1, - "drainQueue": true + "watchRemove": { + "cause": { + "code": 8 + }, + "targetIds": [ + 2 + ] + }, + "expectedSnapshotEvents": [ + { + "errorCode": 8, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], + "expectedState": { + "activeTargets": { + } + } }, { - "applyClientState": { - "primary": true + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 }, - "clientIndex": 1, "expectedState": { "activeTargets": { "2": { @@ -8529,33 +10130,19 @@ "path": "collection" } ], - "resumeToken": "resume-token-2000" + "resumeToken": "" } - }, - "isPrimary": true + } } }, { - "clientIndex": 1, "watchAck": [ 2 ] }, { - "clientIndex": 1, "watchEntity": { "docs": [ - { - "key": "collection/c", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "c" - }, - "version": 3000 - } ], "targets": [ 2 @@ -8563,40 +10150,21 @@ } }, { - "clientIndex": 1, "watchCurrent": [ [ 2 ], - "resume-token-3000" + "resume-token-1000" ] }, { - "clientIndex": 1, "watchSnapshot": { "targetIds": [ ], - "version": 3000 - } - }, - { - "clientIndex": 0, - "drainQueue": true, + "version": 1000 + }, "expectedSnapshotEvents": [ { - "added": [ - { - "key": "collection/c", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "c" - }, - "version": 3000 - } - ], "errorCode": 0, "fromCache": false, "hasPendingWrites": false, @@ -8612,9 +10180,9 @@ } ] }, - "Query is executed by primary client": { + "Query is rejected and re-listened to by secondary client": { "describeName": "Listens:", - "itName": "Query is executed by primary client", + "itName": "Query is rejected and re-listened to by secondary client", "tags": [ "multi-client" ], @@ -8688,37 +10256,17 @@ }, { "clientIndex": 0, - "watchAck": [ - 2 - ] - }, - { - "clientIndex": 0, - "watchEntity": { - "docs": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 - } - ], - "targets": [ + "watchRemove": { + "cause": { + "code": 8 + }, + "targetIds": [ 2 ] - } - }, - { - "clientIndex": 0, - "watchSnapshot": { - "targetIds": [ - ], - "version": 1000 + }, + "expectedState": { + "activeTargets": { + } } }, { @@ -8726,35 +10274,83 @@ "drainQueue": true, "expectedSnapshotEvents": [ { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 - } - ], - "errorCode": 0, - "fromCache": true, + "errorCode": 8, + "fromCache": false, "hasPendingWrites": false, "query": { "filters": [ ], - "orderBys": [ + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 1, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "drainQueue": true, + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } ], - "path": "collection" + "resumeToken": "" } } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 ] }, { "clientIndex": 0, - "drainQueue": true + "watchEntity": { + "docs": [ + ], + "targets": [ + 2 + ] + } }, { "clientIndex": 0, @@ -8762,7 +10358,7 @@ [ 2 ], - "resume-token-2000" + "resume-token-1000" ] }, { @@ -8770,7 +10366,7 @@ "watchSnapshot": { "targetIds": [ ], - "version": 2000 + "version": 1000 } }, { @@ -8793,9 +10389,9 @@ } ] }, - "Query is joined by primary client": { + "Query is rejected by primary client": { "describeName": "Listens:", - "itName": "Query is joined by primary client", + "itName": "Query is rejected by primary client", "tags": [ "multi-client" ], @@ -8806,10 +10402,13 @@ "steps": [ { "clientIndex": 0, - "drainQueue": true, - "expectedState": { - "isPrimary": true - } + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 }, { "clientIndex": 1, @@ -8866,46 +10465,17 @@ }, { "clientIndex": 0, - "watchAck": [ - 2 - ] - }, - { - "clientIndex": 0, - "watchEntity": { - "docs": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 - } - ], - "targets": [ + "watchRemove": { + "cause": { + "code": 8 + }, + "targetIds": [ 2 ] - } - }, - { - "clientIndex": 0, - "watchCurrent": [ - [ - 2 - ], - "resume-token-100" - ] - }, - { - "clientIndex": 0, - "watchSnapshot": { - "targetIds": [ - ], - "version": 100 + }, + "expectedState": { + "activeTargets": { + } } }, { @@ -8913,20 +10483,7 @@ "drainQueue": true, "expectedSnapshotEvents": [ { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 - } - ], - "errorCode": 0, + "errorCode": 8, "fromCache": false, "hasPendingWrites": false, "query": { @@ -8938,42 +10495,36 @@ } } ] - }, + } + ] + }, + "Query is resumed by secondary client": { + "describeName": "Listens:", + "itName": "Query is resumed by secondary client", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 2, + "useGarbageCollection": false + }, + "steps": [ { "clientIndex": 0, "drainQueue": true }, { - "clientIndex": 0, - "watchEntity": { - "docs": [ - { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "b" - }, - "version": 2000 - } - ], - "targets": [ - 2 - ] - } + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 }, { - "clientIndex": 0, - "watchSnapshot": { - "targetIds": [ - ], - "version": 2000 - } + "clientIndex": 1, + "drainQueue": true }, { - "clientIndex": 0, + "clientIndex": 1, "userListen": { "query": { "filters": [ @@ -8984,44 +10535,26 @@ }, "targetId": 2 }, - "expectedSnapshotEvents": [ - { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 - }, - { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "b" - }, - "version": 2000 - } - ], - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } ], - "path": "collection" + "resumeToken": "" } } - ], + } + }, + { + "clientIndex": 0, + "drainQueue": true, "expectedState": { "activeTargets": { "2": { @@ -9039,20 +10572,26 @@ } } }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, { "clientIndex": 0, "watchEntity": { "docs": [ { - "key": "collection/c", + "key": "collection/a", "options": { "hasCommittedMutations": false, "hasLocalMutations": false }, "value": { - "key": "c" + "key": "a" }, - "version": 3000 + "version": 1000 } ], "targets": [ @@ -9060,26 +10599,39 @@ ] } }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, { "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], - "version": 3000 - }, + "version": 1000 + } + }, + { + "clientIndex": 1, + "drainQueue": true, "expectedSnapshotEvents": [ { "added": [ { - "key": "collection/c", + "key": "collection/a", "options": { "hasCommittedMutations": false, "hasLocalMutations": false }, "value": { - "key": "c" + "key": "a" }, - "version": 3000 + "version": 1000 } ], "errorCode": 0, @@ -9097,49 +10649,70 @@ }, { "clientIndex": 1, - "drainQueue": true, - "expectedSnapshotEvents": [ + "userUnlisten": [ + 2, { - "added": [ - { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "b" - }, - "version": 2000 - } + "filters": [ ], - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "drainQueue": true, + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ { "added": [ { - "key": "collection/c", + "key": "collection/a", "options": { "hasCommittedMutations": false, "hasLocalMutations": false }, "value": { - "key": "c" + "key": "a" }, - "version": 3000 + "version": 1000 } ], "errorCode": 0, - "fromCache": false, + "fromCache": true, "hasPendingWrites": false, "query": { "filters": [ @@ -9149,31 +10722,7 @@ "path": "collection" } } - ] - } - ] - }, - "Query is rejected and re-listened to": { - "describeName": "Listens:", - "itName": "Query is rejected and re-listened to", - "tags": [ - ], - "config": { - "numClients": 1, - "useGarbageCollection": false - }, - "steps": [ - { - "userListen": { - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - }, - "targetId": 2 - }, + ], "expectedState": { "activeTargets": { "2": { @@ -9192,44 +10741,8 @@ } }, { - "watchRemove": { - "cause": { - "code": 8 - }, - "targetIds": [ - 2 - ] - }, - "expectedSnapshotEvents": [ - { - "errorCode": 8, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } - ], - "expectedState": { - "activeTargets": { - } - } - }, - { - "userListen": { - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - }, - "targetId": 2 - }, + "clientIndex": 0, + "drainQueue": true, "expectedState": { "activeTargets": { "2": { @@ -9242,19 +10755,32 @@ "path": "collection" } ], - "resumeToken": "" + "resumeToken": "resume-token-1000" } } } }, { + "clientIndex": 0, "watchAck": [ 2 ] }, { + "clientIndex": 0, "watchEntity": { "docs": [ + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } ], "targets": [ 2 @@ -9262,21 +10788,40 @@ } }, { + "clientIndex": 0, "watchCurrent": [ [ 2 ], - "resume-token-1000" + "resume-token-2000" ] }, { + "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], - "version": 1000 - }, + "version": 2000 + } + }, + { + "clientIndex": 1, + "drainQueue": true, "expectedSnapshotEvents": [ { + "added": [ + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } + ], "errorCode": 0, "fromCache": false, "hasPendingWrites": false, @@ -9292,14 +10837,14 @@ } ] }, - "Query is rejected and re-listened to by secondary client": { + "Query is shared between primary and secondary client": { "describeName": "Listens:", - "itName": "Query is rejected and re-listened to by secondary client", + "itName": "Query is shared between primary and secondary client", "tags": [ "multi-client" ], "config": { - "numClients": 2, + "numClients": 3, "useGarbageCollection": false }, "steps": [ @@ -9314,11 +10859,7 @@ "clientIndex": 0 }, { - "clientIndex": 1, - "drainQueue": true - }, - { - "clientIndex": 1, + "clientIndex": 0, "userListen": { "query": { "filters": [ @@ -9348,45 +10889,63 @@ }, { "clientIndex": 0, - "drainQueue": true, - "expectedState": { - "activeTargets": { - "2": { - "queries": [ - { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - ], - "resumeToken": "" - } - } - } + "watchAck": [ + 2 + ] }, { "clientIndex": 0, - "watchRemove": { - "cause": { - "code": 8 - }, - "targetIds": [ + "watchEntity": { + "docs": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "targets": [ 2 ] - }, - "expectedState": { - "activeTargets": { - } } }, { - "clientIndex": 1, - "drainQueue": true, + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, "expectedSnapshotEvents": [ { - "errorCode": 8, + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, "fromCache": false, "hasPendingWrites": false, "query": { @@ -9399,6 +10958,10 @@ } ] }, + { + "clientIndex": 1, + "drainQueue": true + }, { "clientIndex": 1, "userListen": { @@ -9411,6 +10974,33 @@ }, "targetId": 2 }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], "expectedState": { "activeTargets": { "2": { @@ -9429,8 +11019,48 @@ } }, { - "clientIndex": 0, - "drainQueue": true, + "clientIndex": 2, + "drainQueue": true + }, + { + "clientIndex": 2, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], "expectedState": { "activeTargets": { "2": { @@ -9450,42 +11080,113 @@ }, { "clientIndex": 0, - "watchAck": [ - 2 - ] + "drainQueue": true }, { "clientIndex": 0, "watchEntity": { "docs": [ + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } ], "targets": [ 2 ] } }, - { - "clientIndex": 0, - "watchCurrent": [ - [ - 2 - ], - "resume-token-1000" - ] - }, { "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], - "version": 1000 - } + "version": 2000 + }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] }, { "clientIndex": 1, "drainQueue": true, "expectedSnapshotEvents": [ { + "added": [ + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 2, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 2000 + } + ], "errorCode": 0, "fromCache": false, "hasPendingWrites": false, @@ -9501,9 +11202,9 @@ } ] }, - "Query is rejected by primary client": { + "Query is unlistened to by primary client": { "describeName": "Listens:", - "itName": "Query is rejected by primary client", + "itName": "Query is unlistened to by primary client", "tags": [ "multi-client" ], @@ -9523,11 +11224,7 @@ "clientIndex": 0 }, { - "clientIndex": 1, - "drainQueue": true - }, - { - "clientIndex": 1, + "clientIndex": 0, "userListen": { "query": { "filters": [ @@ -9557,45 +11254,63 @@ }, { "clientIndex": 0, - "drainQueue": true, - "expectedState": { - "activeTargets": { - "2": { - "queries": [ - { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - ], - "resumeToken": "" - } - } - } + "watchAck": [ + 2 + ] }, { "clientIndex": 0, - "watchRemove": { - "cause": { - "code": 8 - }, - "targetIds": [ + "watchEntity": { + "docs": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "targets": [ 2 ] - }, - "expectedState": { - "activeTargets": { - } } }, { - "clientIndex": 1, - "drainQueue": true, + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, "expectedSnapshotEvents": [ { - "errorCode": 8, + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, "fromCache": false, "hasPendingWrites": false, "query": { @@ -9607,29 +11322,6 @@ } } ] - } - ] - }, - "Query is resumed by secondary client": { - "describeName": "Listens:", - "itName": "Query is resumed by secondary client", - "tags": [ - "multi-client" - ], - "config": { - "numClients": 2, - "useGarbageCollection": false - }, - "steps": [ - { - "clientIndex": 0, - "drainQueue": true - }, - { - "applyClientState": { - "visibility": "visible" - }, - "clientIndex": 0 }, { "clientIndex": 1, @@ -9647,6 +11339,33 @@ }, "targetId": 2 }, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ], "expectedState": { "activeTargets": { "2": { @@ -9666,7 +11385,20 @@ }, { "clientIndex": 0, - "drainQueue": true, + "drainQueue": true + }, + { + "clientIndex": 0, + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], "expectedState": { "activeTargets": { "2": { @@ -9684,18 +11416,12 @@ } } }, - { - "clientIndex": 0, - "watchAck": [ - 2 - ] - }, { "clientIndex": 0, "watchEntity": { "docs": [ { - "key": "collection/a", + "key": "collection/b", "options": { "hasCommittedMutations": false, "hasLocalMutations": false @@ -9703,7 +11429,7 @@ "value": { "key": "a" }, - "version": 1000 + "version": 2000 } ], "targets": [ @@ -9711,21 +11437,12 @@ ] } }, - { - "clientIndex": 0, - "watchCurrent": [ - [ - 2 - ], - "resume-token-1000" - ] - }, { "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], - "version": 1000 + "version": 2000 } }, { @@ -9735,7 +11452,7 @@ { "added": [ { - "key": "collection/a", + "key": "collection/b", "options": { "hasCommittedMutations": false, "hasLocalMutations": false @@ -9743,7 +11460,7 @@ "value": { "key": "a" }, - "version": 1000 + "version": 2000 } ], "errorCode": 0, @@ -9783,21 +11500,40 @@ "activeTargets": { } } - }, + } + ] + }, + "Query only raises events in participating clients": { + "describeName": "Listens:", + "itName": "Query only raises events in participating clients", + "tags": [ + "multi-client" + ], + "config": { + "numClients": 4, + "useGarbageCollection": false + }, + "steps": [ { "clientIndex": 0, - "watchRemove": { - "targetIds": [ - 2 - ] - } + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0 }, { "clientIndex": 1, "drainQueue": true }, { - "clientIndex": 1, + "clientIndex": 2, + "drainQueue": true + }, + { + "clientIndex": 2, "userListen": { "query": { "filters": [ @@ -9808,33 +11544,39 @@ }, "targetId": 2 }, - "expectedSnapshotEvents": [ - { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 - } - ], - "errorCode": 0, - "fromCache": true, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } ], - "path": "collection" + "resumeToken": "" } } - ], + } + }, + { + "clientIndex": 3, + "drainQueue": true + }, + { + "clientIndex": 3, + "userListen": { + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "targetId": 2 + }, "expectedState": { "activeTargets": { "2": { @@ -9867,7 +11609,7 @@ "path": "collection" } ], - "resumeToken": "resume-token-1000" + "resumeToken": "" } } } @@ -9883,7 +11625,7 @@ "watchEntity": { "docs": [ { - "key": "collection/b", + "key": "collection/a", "options": { "hasCommittedMutations": false, "hasLocalMutations": false @@ -9891,39 +11633,74 @@ "value": { "key": "a" }, - "version": 2000 + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1000" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + } + }, + { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 2, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" } - ], - "targets": [ - 2 - ] - } - }, - { - "clientIndex": 0, - "watchCurrent": [ - [ - 2 - ], - "resume-token-2000" + } ] }, { - "clientIndex": 0, - "watchSnapshot": { - "targetIds": [ - ], - "version": 2000 - } - }, - { - "clientIndex": 1, + "clientIndex": 3, "drainQueue": true, "expectedSnapshotEvents": [ { "added": [ { - "key": "collection/b", + "key": "collection/a", "options": { "hasCommittedMutations": false, "hasLocalMutations": false @@ -9931,7 +11708,7 @@ "value": { "key": "a" }, - "version": 2000 + "version": 1000 } ], "errorCode": 0, @@ -9949,26 +11726,23 @@ } ] }, - "Query is shared between primary and secondary client": { + "Query recovers after primary takeover": { "describeName": "Listens:", - "itName": "Query is shared between primary and secondary client", + "itName": "Query recovers after primary takeover", "tags": [ "multi-client" ], "config": { - "numClients": 3, + "numClients": 2, "useGarbageCollection": false }, "steps": [ { "clientIndex": 0, - "drainQueue": true - }, - { - "applyClientState": { - "visibility": "visible" - }, - "clientIndex": 0 + "drainQueue": true, + "expectedState": { + "isPrimary": true + } }, { "clientIndex": 0, @@ -10131,48 +11905,10 @@ } }, { - "clientIndex": 2, - "drainQueue": true - }, - { - "clientIndex": 2, - "userListen": { - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - }, - "targetId": 2 + "applyClientState": { + "primary": true }, - "expectedSnapshotEvents": [ - { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 - } - ], - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } - ], + "clientIndex": 1, "expectedState": { "activeTargets": { "2": { @@ -10185,17 +11921,20 @@ "path": "collection" } ], - "resumeToken": "" + "resumeToken": "resume-token-1000" } - } + }, + "isPrimary": true } }, { - "clientIndex": 0, - "drainQueue": true + "clientIndex": 1, + "watchAck": [ + 2 + ] }, { - "clientIndex": 0, + "clientIndex": 1, "watchEntity": { "docs": [ { @@ -10205,7 +11944,7 @@ "hasLocalMutations": false }, "value": { - "key": "a" + "key": "b" }, "version": 2000 } @@ -10216,174 +11955,71 @@ } }, { - "clientIndex": 0, - "watchSnapshot": { - "targetIds": [ + "clientIndex": 1, + "watchCurrent": [ + [ + 2 ], - "version": 2000 - }, - "expectedSnapshotEvents": [ - { - "added": [ - { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 2000 - } - ], - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } + "resume-token-2000" ] }, { "clientIndex": 1, - "drainQueue": true, - "expectedSnapshotEvents": [ - { - "added": [ - { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 2000 - } - ], - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } - ] - }, - { - "clientIndex": 2, - "drainQueue": true, + "watchSnapshot": { + "targetIds": [ + ], + "version": 2000 + }, "expectedSnapshotEvents": [ { "added": [ { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 2000 - } - ], - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } - ] - } - ] - }, - "Query is unlistened to by primary client": { - "describeName": "Listens:", - "itName": "Query is unlistened to by primary client", - "tags": [ - "multi-client" - ], - "config": { - "numClients": 2, - "useGarbageCollection": false - }, - "steps": [ - { - "clientIndex": 0, - "drainQueue": true - }, - { - "applyClientState": { - "visibility": "visible" - }, - "clientIndex": 0 - }, - { - "clientIndex": 0, - "userListen": { - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - }, - "targetId": 2 - }, - "expectedState": { - "activeTargets": { - "2": { - "queries": [ - { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } + "key": "collection/b", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "b" + }, + "version": 2000 + } + ], + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ ], - "resumeToken": "" + "orderBys": [ + ], + "path": "collection" } } - } + ] }, { "clientIndex": 0, - "watchAck": [ - 2 - ] + "drainQueue": true }, { - "clientIndex": 0, + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, "watchEntity": { "docs": [ { - "key": "collection/a", + "key": "collection/c", "options": { "hasCommittedMutations": false, "hasLocalMutations": false }, "value": { - "key": "a" + "key": "c" }, - "version": 1000 + "version": 3000 } ], "targets": [ @@ -10392,34 +12028,25 @@ } }, { - "clientIndex": 0, - "watchCurrent": [ - [ - 2 - ], - "resume-token-1000" - ] - }, - { - "clientIndex": 0, + "clientIndex": 1, "watchSnapshot": { "targetIds": [ ], - "version": 1000 + "version": 3000 }, "expectedSnapshotEvents": [ { "added": [ { - "key": "collection/a", + "key": "collection/c", "options": { "hasCommittedMutations": false, "hasLocalMutations": false }, "value": { - "key": "a" + "key": "c" }, - "version": 1000 + "version": 3000 } ], "errorCode": 0, @@ -10436,34 +12063,36 @@ ] }, { - "clientIndex": 1, + "clientIndex": 0, "drainQueue": true }, { - "clientIndex": 1, - "userListen": { - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - }, - "targetId": 2 - }, + "clientIndex": 0, + "runTimer": "client_metadata_refresh", "expectedSnapshotEvents": [ { "added": [ { - "key": "collection/a", + "key": "collection/b", "options": { "hasCommittedMutations": false, "hasLocalMutations": false }, "value": { - "key": "a" + "key": "b" }, - "version": 1000 + "version": 2000 + }, + { + "key": "collection/c", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "c" + }, + "version": 3000 } ], "errorCode": 0, @@ -10479,38 +12108,32 @@ } ], "expectedState": { - "activeTargets": { - "2": { - "queries": [ - { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - ], - "resumeToken": "" - } - } + "isPrimary": false } - }, - { - "clientIndex": 0, - "drainQueue": true - }, + } + ] + }, + "Re-opens target without existence filter": { + "describeName": "Listens:", + "itName": "Re-opens target without existence filter", + "tags": [ + ], + "config": { + "numClients": 1, + "useGarbageCollection": false + }, + "steps": [ { - "clientIndex": 0, - "userUnlisten": [ - 2, - { + "userListen": { + "query": { "filters": [ ], "orderBys": [ ], "path": "collection" - } - ], + }, + "targetId": 2 + }, "expectedState": { "activeTargets": { "2": { @@ -10529,11 +12152,15 @@ } }, { - "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { "watchEntity": { "docs": [ { - "key": "collection/b", + "key": "collection/a", "options": { "hasCommittedMutations": false, "hasLocalMutations": false @@ -10541,7 +12168,7 @@ "value": { "key": "a" }, - "version": 2000 + "version": 1000 } ], "targets": [ @@ -10550,21 +12177,24 @@ } }, { - "clientIndex": 0, - "watchSnapshot": { - "targetIds": [ + "watchCurrent": [ + [ + 2 ], - "version": 2000 - } + "resume-token-1000" + ] }, { - "clientIndex": 1, - "drainQueue": true, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1000 + }, "expectedSnapshotEvents": [ { "added": [ { - "key": "collection/b", + "key": "collection/a", "options": { "hasCommittedMutations": false, "hasLocalMutations": false @@ -10572,7 +12202,7 @@ "value": { "key": "a" }, - "version": 2000 + "version": 1000 } ], "errorCode": 0, @@ -10589,7 +12219,6 @@ ] }, { - "clientIndex": 1, "userUnlisten": [ 2, { @@ -10606,79 +12235,13 @@ } }, { - "clientIndex": 0, - "drainQueue": true, - "expectedState": { - "activeTargets": { - } - } - } - ] - }, - "Query only raises events in participating clients": { - "describeName": "Listens:", - "itName": "Query only raises events in participating clients", - "tags": [ - "multi-client" - ], - "config": { - "numClients": 4, - "useGarbageCollection": false - }, - "steps": [ - { - "clientIndex": 0, - "drainQueue": true - }, - { - "applyClientState": { - "visibility": "visible" - }, - "clientIndex": 0 - }, - { - "clientIndex": 1, - "drainQueue": true - }, - { - "clientIndex": 2, - "drainQueue": true - }, - { - "clientIndex": 2, - "userListen": { - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - }, - "targetId": 2 - }, - "expectedState": { - "activeTargets": { - "2": { - "queries": [ - { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - ], - "resumeToken": "" - } - } + "watchRemove": { + "targetIds": [ + 2 + ] } }, { - "clientIndex": 3, - "drainQueue": true - }, - { - "clientIndex": 3, "userListen": { "query": { "filters": [ @@ -10689,26 +12252,33 @@ }, "targetId": 2 }, - "expectedState": { - "activeTargets": { - "2": { - "queries": [ - { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } + "expectedSnapshotEvents": [ + { + "added": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "a" + }, + "version": 1000 + } + ], + "errorCode": 0, + "fromCache": true, + "hasPendingWrites": false, + "query": { + "filters": [ ], - "resumeToken": "" + "orderBys": [ + ], + "path": "collection" } } - } - }, - { - "clientIndex": 0, - "drainQueue": true, + ], "expectedState": { "activeTargets": { "2": { @@ -10721,77 +12291,46 @@ "path": "collection" } ], - "resumeToken": "" + "resumeToken": "resume-token-1000" } } } }, { - "clientIndex": 0, "watchAck": [ 2 ] }, { - "clientIndex": 0, "watchEntity": { "docs": [ { "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 + "value": null, + "version": 2000 } ], - "targets": [ + "removedTargets": [ 2 ] } }, { - "clientIndex": 0, "watchCurrent": [ [ 2 ], - "resume-token-1000" + "resume-token-2000" ] }, { - "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], - "version": 1000 - } - }, - { - "clientIndex": 1, - "drainQueue": true - }, - { - "clientIndex": 2, - "drainQueue": true, + "version": 2000 + }, "expectedSnapshotEvents": [ { - "added": [ - { - "key": "collection/a", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "a" - }, - "version": 1000 - } - ], "errorCode": 0, "fromCache": false, "hasPendingWrites": false, @@ -10801,16 +12340,8 @@ "orderBys": [ ], "path": "collection" - } - } - ] - }, - { - "clientIndex": 3, - "drainQueue": true, - "expectedSnapshotEvents": [ - { - "added": [ + }, + "removed": [ { "key": "collection/a", "options": { @@ -10822,25 +12353,15 @@ }, "version": 1000 } - ], - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } + ] } ] } ] }, - "Query recovers after primary takeover": { + "Secondary client advances query state with global snapshot from primary": { "describeName": "Listens:", - "itName": "Query recovers after primary takeover", + "itName": "Secondary client advances query state with global snapshot from primary", "tags": [ "multi-client" ], @@ -10851,7 +12372,13 @@ "steps": [ { "clientIndex": 0, - "drainQueue": true, + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0, "expectedState": { "isPrimary": true } @@ -10902,7 +12429,7 @@ "hasLocalMutations": false }, "value": { - "key": "a" + "key": "1" }, "version": 1000 } @@ -10938,7 +12465,7 @@ "hasLocalMutations": false }, "value": { - "key": "a" + "key": "1" }, "version": 1000 } @@ -10956,6 +12483,31 @@ } ] }, + { + "clientIndex": 0, + "userUnlisten": [ + 2, + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "expectedState": { + "activeTargets": { + } + } + }, + { + "clientIndex": 0, + "watchRemove": { + "targetIds": [ + 2 + ] + } + }, { "clientIndex": 1, "drainQueue": true @@ -10982,13 +12534,13 @@ "hasLocalMutations": false }, "value": { - "key": "a" + "key": "1" }, "version": 1000 } ], "errorCode": 0, - "fromCache": false, + "fromCache": true, "hasPendingWrites": false, "query": { "filters": [ @@ -11017,10 +12569,8 @@ } }, { - "applyClientState": { - "primary": true - }, - "clientIndex": 1, + "clientIndex": 0, + "drainQueue": true, "expectedState": { "activeTargets": { "2": { @@ -11035,29 +12585,142 @@ ], "resumeToken": "resume-token-1000" } - }, - "isPrimary": true + } } }, { - "clientIndex": 1, + "clientIndex": 0, "watchAck": [ 2 ] }, { - "clientIndex": 1, + "clientIndex": 0, "watchEntity": { "docs": [ { - "key": "collection/b", + "key": "collection/a", "options": { "hasCommittedMutations": false, "hasLocalMutations": false }, "value": { - "key": "b" + "key": "1" }, + "version": 1000 + } + ], + "targets": [ + 2 + ] + } + }, + { + "clientIndex": 0, + "watchCurrent": [ + [ + 2 + ], + "resume-token-1500" + ] + }, + { + "clientIndex": 0, + "watchSnapshot": { + "targetIds": [ + ], + "version": 1500 + } + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + } + ] + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "userDelete": "collection/a" + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": false, + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + }, + "removed": [ + { + "key": "collection/a", + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "1" + }, + "version": 1000 + } + ] + } + ] + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "writeAck": { + "version": 2000 + }, + "expectedState": { + "userCallbacks": { + "acknowledgedDocs": [ + "collection/a" + ], + "rejectedDocs": [ + ] + } + } + }, + { + "clientIndex": 0, + "watchAck": [ + 2 + ] + }, + { + "clientIndex": 0, + "watchEntity": { + "docs": [ + { + "key": "collection/a", + "value": null, "version": 2000 } ], @@ -11067,7 +12730,7 @@ } }, { - "clientIndex": 1, + "clientIndex": 0, "watchCurrent": [ [ 2 @@ -11076,140 +12739,51 @@ ] }, { - "clientIndex": 1, + "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], "version": 2000 - }, - "expectedSnapshotEvents": [ - { - "added": [ - { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "b" - }, - "version": 2000 - } - ], - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } - ] - }, - { - "clientIndex": 0, - "drainQueue": true + } }, { "clientIndex": 1, "drainQueue": true }, { - "clientIndex": 1, - "watchEntity": { - "docs": [ - { - "key": "collection/c", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "c" - }, - "version": 3000 - } - ], - "targets": [ - 2 - ] - } + "clientIndex": 0, + "drainQueue": true }, { - "clientIndex": 1, - "watchSnapshot": { - "targetIds": [ - ], - "version": 3000 - }, - "expectedSnapshotEvents": [ + "clientIndex": 0, + "userSet": [ + "collection/a", { - "added": [ - { - "key": "collection/c", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "c" - }, - "version": 3000 - } - ], - "errorCode": 0, - "fromCache": false, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } + "key": "2" } ] }, { - "clientIndex": 0, - "drainQueue": true - }, - { - "clientIndex": 0, - "runTimer": "client_metadata_refresh", + "clientIndex": 1, + "drainQueue": true, "expectedSnapshotEvents": [ { "added": [ { - "key": "collection/b", - "options": { - "hasCommittedMutations": false, - "hasLocalMutations": false - }, - "value": { - "key": "b" - }, - "version": 2000 - }, - { - "key": "collection/c", + "key": "collection/a", "options": { "hasCommittedMutations": false, - "hasLocalMutations": false + "hasLocalMutations": true }, "value": { - "key": "c" + "key": "2" }, - "version": 3000 + "version": 0 } ], "errorCode": 0, "fromCache": false, - "hasPendingWrites": false, + "hasPendingWrites": true, "query": { "filters": [ ], @@ -11218,24 +12792,36 @@ "path": "collection" } } - ], - "expectedState": { - "isPrimary": false - } + ] } ] }, - "Re-opens target without existence filter": { + "Secondary client raises latency compensated snapshot from primary mutation": { "describeName": "Listens:", - "itName": "Re-opens target without existence filter", + "itName": "Secondary client raises latency compensated snapshot from primary mutation", "tags": [ + "multi-client" ], "config": { - "numClients": 1, + "numClients": 2, "useGarbageCollection": false }, "steps": [ { + "clientIndex": 0, + "drainQueue": true + }, + { + "applyClientState": { + "visibility": "visible" + }, + "clientIndex": 0, + "expectedState": { + "isPrimary": true + } + }, + { + "clientIndex": 0, "userListen": { "query": { "filters": [ @@ -11264,11 +12850,13 @@ } }, { + "clientIndex": 0, "watchAck": [ 2 ] }, { + "clientIndex": 0, "watchEntity": { "docs": [ { @@ -11278,7 +12866,7 @@ "hasLocalMutations": false }, "value": { - "key": "a" + "key": "1" }, "version": 1000 } @@ -11289,6 +12877,7 @@ } }, { + "clientIndex": 0, "watchCurrent": [ [ 2 @@ -11297,6 +12886,7 @@ ] }, { + "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], @@ -11312,7 +12902,7 @@ "hasLocalMutations": false }, "value": { - "key": "a" + "key": "1" }, "version": 1000 } @@ -11331,6 +12921,7 @@ ] }, { + "clientIndex": 0, "userUnlisten": [ 2, { @@ -11347,6 +12938,7 @@ } }, { + "clientIndex": 0, "watchRemove": { "targetIds": [ 2 @@ -11354,6 +12946,11 @@ } }, { + "clientIndex": 1, + "drainQueue": true + }, + { + "clientIndex": 1, "userListen": { "query": { "filters": [ @@ -11374,7 +12971,7 @@ "hasLocalMutations": false }, "value": { - "key": "a" + "key": "1" }, "version": 1000 } @@ -11391,6 +12988,26 @@ } } ], + "expectedState": { + "activeTargets": { + "2": { + "queries": [ + { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } + ], + "resumeToken": "" + } + } + } + }, + { + "clientIndex": 0, + "drainQueue": true, "expectedState": { "activeTargets": { "2": { @@ -11409,38 +13026,52 @@ } }, { + "clientIndex": 0, "watchAck": [ 2 ] }, { + "clientIndex": 0, "watchEntity": { "docs": [ { "key": "collection/a", - "value": null, - "version": 2000 + "options": { + "hasCommittedMutations": false, + "hasLocalMutations": false + }, + "value": { + "key": "1" + }, + "version": 1000 } ], - "removedTargets": [ + "targets": [ 2 ] } }, { + "clientIndex": 0, "watchCurrent": [ [ 2 ], - "resume-token-2000" + "resume-token-1500" ] }, { + "clientIndex": 0, "watchSnapshot": { "targetIds": [ ], - "version": 2000 - }, + "version": 1500 + } + }, + { + "clientIndex": 1, + "drainQueue": true, "expectedSnapshotEvents": [ { "errorCode": 0, @@ -11452,20 +13083,51 @@ "orderBys": [ ], "path": "collection" - }, - "removed": [ + } + } + ] + }, + { + "clientIndex": 0, + "drainQueue": true + }, + { + "clientIndex": 0, + "userSet": [ + "collection/a", + { + "key": "2" + } + ] + }, + { + "clientIndex": 1, + "drainQueue": true, + "expectedSnapshotEvents": [ + { + "errorCode": 0, + "fromCache": false, + "hasPendingWrites": true, + "modified": [ { "key": "collection/a", "options": { "hasCommittedMutations": false, - "hasLocalMutations": false + "hasLocalMutations": true }, "value": { - "key": "a" + "key": "2" }, - "version": 1000 + "version": 0 } - ] + ], + "query": { + "filters": [ + ], + "orderBys": [ + ], + "path": "collection" + } } ] } @@ -14035,7 +15697,7 @@ "value": { "v": 2 }, - "version": 1000 + "version": 0 } ], "query": { @@ -14251,7 +15913,7 @@ "value": { "v": 2 }, - "version": 1000 + "version": 0 } ], "query": { @@ -14295,7 +15957,7 @@ "value": { "v": 3 }, - "version": 1000 + "version": 0 } ], "query": { @@ -14334,7 +15996,7 @@ "value": { "v": 4 }, - "version": 1000 + "version": 0 } ], "query": { @@ -14602,7 +16264,7 @@ "value": { "v": 2 }, - "version": 1000 + "version": 0 } ], "query": { @@ -14627,7 +16289,7 @@ "value": { "v": 2 }, - "version": 1000 + "version": 0 } ], "query": { diff --git a/Firestore/Example/Tests/SpecTests/json/recovery_spec_test.json b/Firestore/Example/Tests/SpecTests/json/recovery_spec_test.json index 9ae9f2349ff..c42d58c9d41 100644 --- a/Firestore/Example/Tests/SpecTests/json/recovery_spec_test.json +++ b/Firestore/Example/Tests/SpecTests/json/recovery_spec_test.json @@ -1012,20 +1012,6 @@ }, "targetId": 2 }, - "expectedSnapshotEvents": [ - { - "errorCode": 0, - "fromCache": true, - "hasPendingWrites": false, - "query": { - "filters": [ - ], - "orderBys": [ - ], - "path": "collection" - } - } - ], "expectedState": { "activeTargets": { "2": {