Skip to content

Commit 4e86d01

Browse files
Add more Recovery spec tests (#3084)
* Clean up recovery spec tests * Spec tests for updateClientMetadataAndTryBecomePrimary and 'Lookup mutation documents' recovery * Feedback
1 parent babdcfd commit 4e86d01

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed

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

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,36 @@ describeSpec('Persistence Recovery', ['no-ios', 'no-android'], () => {
5757
}
5858
);
5959

60+
specTest(
61+
'Clients fail to lookup mutations (with recovery)',
62+
['multi-client'],
63+
() => {
64+
// Multi-Tab uses a Local Storage notification to inform all tabs about
65+
// changes to a mutation tab. To act upon these changes, the tabs read
66+
// the mutated document from IndexedDB. This test verifies that mutations
67+
// are applied even if the lookup fails temporarily.
68+
return (
69+
client(0)
70+
.expectPrimaryState(true)
71+
// All tabs fail to act upon the Local Storage notifications
72+
.failDatabaseTransactions('Lookup mutation documents')
73+
.client(1)
74+
.expectPrimaryState(false)
75+
.userSets('collection/a', { v: 1 })
76+
.failDatabaseTransactions('Lookup mutation documents')
77+
// All tabs recover and the notifications are processed
78+
.client(0)
79+
.recoverDatabase()
80+
.runTimer(TimerId.AsyncQueueRetry)
81+
.writeAcks('collection/a', 1, { expectUserCallback: false })
82+
.client(1)
83+
.recoverDatabase()
84+
.runTimer(TimerId.AsyncQueueRetry)
85+
.expectUserCallbacks({ acknowledged: ['collection/a'] })
86+
);
87+
}
88+
);
89+
6090
specTest(
6191
'Query raises events in secondary client (with recovery)',
6292
['multi-client'],
@@ -114,6 +144,55 @@ describeSpec('Persistence Recovery', ['no-ios', 'no-android'], () => {
114144
}
115145
);
116146

147+
specTest(
148+
'Ignores intermittent lease refresh failures (with recovery)',
149+
['multi-client'],
150+
() => {
151+
// This test verifies that an IndexedDB failure during a lease refresh
152+
// does not impact client functionality. Lease refresh failures are
153+
// ignored, as the lease is also verified each time an operation is
154+
// run.
155+
return (
156+
client(0)
157+
.expectPrimaryState(true)
158+
.client(1)
159+
.expectPrimaryState(false)
160+
// Run the initial sequence: The primary client fails its lease refresh
161+
// before the secondary client.
162+
.client(0)
163+
.failDatabaseTransactions('updateClientMetadataAndTryBecomePrimary')
164+
.runTimer(TimerId.ClientMetadataRefresh)
165+
.client(1)
166+
.failDatabaseTransactions('updateClientMetadataAndTryBecomePrimary')
167+
.runTimer(TimerId.ClientMetadataRefresh)
168+
.client(0)
169+
.recoverDatabase()
170+
.runTimer(TimerId.ClientMetadataRefresh)
171+
.expectPrimaryState(true)
172+
.client(1)
173+
.recoverDatabase()
174+
.runTimer(TimerId.ClientMetadataRefresh)
175+
.expectPrimaryState(false)
176+
// Run the opposite sequence: The secondary client fails its lease
177+
// refresh before the primary client.
178+
.client(1)
179+
.failDatabaseTransactions('updateClientMetadataAndTryBecomePrimary')
180+
.runTimer(TimerId.ClientMetadataRefresh)
181+
.client(0)
182+
.failDatabaseTransactions('updateClientMetadataAndTryBecomePrimary')
183+
.runTimer(TimerId.ClientMetadataRefresh)
184+
.client(1)
185+
.recoverDatabase()
186+
.runTimer(TimerId.ClientMetadataRefresh)
187+
.expectPrimaryState(false)
188+
.client(0)
189+
.recoverDatabase()
190+
.runTimer(TimerId.ClientMetadataRefresh)
191+
.expectPrimaryState(true)
192+
);
193+
}
194+
);
195+
117196
specTest('Recovers when write cannot be persisted', [], () => {
118197
return (
119198
spec()

0 commit comments

Comments
 (0)