@@ -2243,99 +2243,98 @@ apiDescribe('Queries', persistence => {
2243
2243
return map ;
2244
2244
} , { } as { [ key : string ] : DocumentData } ) ;
2245
2245
2246
- // Ensure that the local cache is configured to use LRU garbage
2247
- // collection (rather than eager garbage collection) so that the resume
2248
- // token and document data does not get prematurely evicted.
2246
+ // Ensure that the local cache is configured to use LRU garbage collection
2247
+ // (rather than eager garbage collection) so that the resume token and
2248
+ // document data does not get prematurely evicted.
2249
2249
const lruPersistence = persistence . toLruGc ( ) ;
2250
2250
2251
- return withRetry ( async attemptNumber => {
2252
- return withTestCollection (
2253
- lruPersistence ,
2254
- testDocs ,
2255
- async ( coll , db ) => {
2256
- // Run a query to populate the local cache with documents that have
2257
- // names with complex Unicode characters.
2258
- const snapshot1 = await getDocs ( coll ) ;
2259
- const snapshot1DocumentIds = snapshot1 . docs . map (
2260
- documentSnapshot => documentSnapshot . id
2261
- ) ;
2262
- expect (
2263
- snapshot1DocumentIds ,
2264
- 'snapshot1DocumentIds'
2265
- ) . to . have . members ( testDocIds ) ;
2266
-
2267
- // Delete one of the documents so that the next call to getDocs() will
2268
- // experience an existence filter mismatch. Do this deletion in a
2269
- // transaction, rather than using deleteDoc(), to avoid affecting the
2270
- // local cache.
2271
- await runTransaction ( db , async txn => {
2272
- const snapshotOfDocumentToDelete = await txn . get (
2273
- doc ( coll , 'DocumentToDelete' )
2274
- ) ;
2275
- expect (
2276
- snapshotOfDocumentToDelete . exists ( ) ,
2277
- 'snapshotOfDocumentToDelete.exists()'
2278
- ) . to . be . true ;
2279
- txn . delete ( snapshotOfDocumentToDelete . ref ) ;
2280
- } ) ;
2281
-
2282
- // Wait for 10 seconds, during which Watch will stop tracking the
2283
- // query and will send an existence filter rather than "delete" events
2284
- // when the query is resumed.
2285
- await new Promise ( resolve => setTimeout ( resolve , 10000 ) ) ;
2286
-
2287
- // Resume the query and save the resulting snapshot for verification.
2288
- // Use some internal testing hooks to "capture" the existence filter
2289
- // mismatches.
2290
- const [ existenceFilterMismatches , snapshot2 ] =
2291
- await captureExistenceFilterMismatches ( ( ) => getDocs ( coll ) ) ;
2292
- const snapshot2DocumentIds = snapshot2 . docs . map (
2293
- documentSnapshot => documentSnapshot . id
2294
- ) ;
2295
- const testDocIdsMinusDeletedDocId = testDocIds . filter (
2296
- documentId => documentId !== 'DocumentToDelete'
2297
- ) ;
2298
- expect (
2299
- snapshot2DocumentIds ,
2300
- 'snapshot2DocumentIds'
2301
- ) . to . have . members ( testDocIdsMinusDeletedDocId ) ;
2302
-
2303
- // Verify that Watch sent an existence filter with the correct counts.
2304
- expect (
2305
- existenceFilterMismatches ,
2306
- 'existenceFilterMismatches'
2307
- ) . to . have . length ( 1 ) ;
2308
- const { localCacheCount, existenceFilterCount, bloomFilter } =
2309
- existenceFilterMismatches [ 0 ] ;
2310
- expect ( localCacheCount , 'localCacheCount' ) . to . equal (
2311
- testDocIds . length
2312
- ) ;
2313
- expect ( existenceFilterCount , 'existenceFilterCount' ) . to . equal (
2314
- testDocIds . length - 1
2315
- ) ;
2251
+ return withTestCollection ( lruPersistence , testDocs , async ( coll , db ) => {
2252
+ // Run a query to populate the local cache with documents that have
2253
+ // names with complex Unicode characters.
2254
+ const snapshot1 = await getDocs ( coll ) ;
2255
+ const snapshot1DocumentIds = snapshot1 . docs . map (
2256
+ documentSnapshot => documentSnapshot . id
2257
+ ) ;
2258
+ expect ( snapshot1DocumentIds , 'snapshot1DocumentIds' ) . to . have . members (
2259
+ testDocIds
2260
+ ) ;
2316
2261
2317
- // Verify that Watch sent a valid bloom filter.
2318
- if ( ! bloomFilter ) {
2319
- expect . fail (
2320
- 'The existence filter should have specified a bloom filter ' +
2321
- 'in its `unchanged_names` field.'
2322
- ) ;
2323
- throw new Error ( 'should never get here' ) ;
2324
- }
2325
-
2326
- // Verify that the bloom filter was successfully used to avert a full
2327
- // requery. If a false positive occurred, which is statistically rare,
2328
- // but technically possible, then retry the entire test.
2329
- if ( attemptNumber === 1 && ! bloomFilter . applied ) {
2330
- throw new RetryError ( ) ;
2331
- }
2332
-
2333
- expect (
2334
- bloomFilter . applied ,
2335
- `bloomFilter.applied with attemptNumber=${ attemptNumber } `
2336
- ) . to . be . true ;
2337
- }
2262
+ // Delete one of the documents so that the next call to getDocs() will
2263
+ // experience an existence filter mismatch. Do this deletion in a
2264
+ // transaction, rather than using deleteDoc(), to avoid affecting the
2265
+ // local cache.
2266
+ await runTransaction ( db , async txn => {
2267
+ const snapshotOfDocumentToDelete = await txn . get (
2268
+ doc ( coll , 'DocumentToDelete' )
2269
+ ) ;
2270
+ expect (
2271
+ snapshotOfDocumentToDelete . exists ( ) ,
2272
+ 'snapshotOfDocumentToDelete.exists()'
2273
+ ) . to . be . true ;
2274
+ txn . delete ( snapshotOfDocumentToDelete . ref ) ;
2275
+ } ) ;
2276
+
2277
+ // Wait for 10 seconds, during which Watch will stop tracking the query
2278
+ // and will send an existence filter rather than "delete" events when
2279
+ // the query is resumed.
2280
+ await new Promise ( resolve => setTimeout ( resolve , 10000 ) ) ;
2281
+
2282
+ // Resume the query and save the resulting snapshot for verification.
2283
+ // Use some internal testing hooks to "capture" the existence filter
2284
+ // mismatches.
2285
+ const [ existenceFilterMismatches , snapshot2 ] =
2286
+ await captureExistenceFilterMismatches ( ( ) => getDocs ( coll ) ) ;
2287
+ const snapshot2DocumentIds = snapshot2 . docs . map (
2288
+ documentSnapshot => documentSnapshot . id
2289
+ ) ;
2290
+ const testDocIdsMinusDeletedDocId = testDocIds . filter (
2291
+ documentId => documentId !== 'DocumentToDelete'
2292
+ ) ;
2293
+ expect ( snapshot2DocumentIds , 'snapshot2DocumentIds' ) . to . have . members (
2294
+ testDocIdsMinusDeletedDocId
2295
+ ) ;
2296
+
2297
+ // Verify that Watch sent an existence filter with the correct counts.
2298
+ expect (
2299
+ existenceFilterMismatches ,
2300
+ 'existenceFilterMismatches'
2301
+ ) . to . have . length ( 1 ) ;
2302
+ const existenceFilterMismatch = existenceFilterMismatches [ 0 ] ;
2303
+ expect (
2304
+ existenceFilterMismatch . localCacheCount ,
2305
+ 'localCacheCount'
2306
+ ) . to . equal ( testDocIds . length ) ;
2307
+ expect (
2308
+ existenceFilterMismatch . existenceFilterCount ,
2309
+ 'existenceFilterCount'
2310
+ ) . to . equal ( testDocIds . length - 1 ) ;
2311
+
2312
+ // Verify that we got a bloom filter from Watch.
2313
+ const bloomFilter = existenceFilterMismatch . bloomFilter ! ;
2314
+ expect ( bloomFilter ?. mightContain , 'bloomFilter.mightContain' ) . to . not . be
2315
+ . undefined ;
2316
+
2317
+ // The bloom filter application should statistically be successful
2318
+ // almost every time; the _only_ time when it would _not_ be successful
2319
+ // is if there is a false positive when testing for 'DocumentToDelete'
2320
+ // in the bloom filter. So verify that the bloom filter application is
2321
+ // successful, unless there was a false positive.
2322
+ const isFalsePositive = bloomFilter . mightContain ! (
2323
+ `${ coll . path } /DocumentToDelete`
2324
+ ) ;
2325
+ expect ( bloomFilter . applied , 'bloomFilter.applied' ) . to . equal (
2326
+ ! isFalsePositive
2338
2327
) ;
2328
+
2329
+ // Verify that the bloom filter contains the document paths with complex
2330
+ // Unicode characters.
2331
+ for ( const testDocId of testDocIdsMinusDeletedDocId ) {
2332
+ const testDocPath = `${ coll . path } /${ testDocId } ` ;
2333
+ expect (
2334
+ bloomFilter . mightContain ! ( testDocPath ) ,
2335
+ `bloomFilter.mightContain('${ testDocPath } ')`
2336
+ ) . to . be . true ;
2337
+ }
2339
2338
} ) ;
2340
2339
}
2341
2340
) . timeout ( '90s' ) ;
0 commit comments