@@ -277,8 +277,7 @@ describeSpec('Existence Filters:', [], () => {
277
277
*/
278
278
specTest (
279
279
'Full re-query is skipped when bloom filter can identify documents deleted' ,
280
- // TODO(b/278759251) Remove 'no-ios' once bloom filter is merged.
281
- [ 'no-ios' ] ,
280
+ [ ] ,
282
281
( ) => {
283
282
const query1 = query ( 'collection' ) ;
284
283
const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
@@ -310,8 +309,7 @@ describeSpec('Existence Filters:', [], () => {
310
309
311
310
specTest (
312
311
'Full re-query is triggered when bloom filter can not identify documents deleted' ,
313
- // TODO(b/278759251) Remove 'no-ios' once bloom filter is merged.
314
- [ 'no-ios' ] ,
312
+ [ ] ,
315
313
( ) => {
316
314
const query1 = query ( 'collection' ) ;
317
315
const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
@@ -343,8 +341,7 @@ describeSpec('Existence Filters:', [], () => {
343
341
344
342
specTest (
345
343
'Bloom filter can process special characters in document name' ,
346
- // TODO(b/278759251) Remove 'no-ios' once bloom filter is merged.
347
- [ 'no-ios' ] ,
344
+ [ ] ,
348
345
( ) => {
349
346
const query1 = query ( 'collection' ) ;
350
347
const docA = doc ( 'collection/ÀÒ∑' , 1000 , { v : 1 } ) ;
@@ -372,8 +369,7 @@ describeSpec('Existence Filters:', [], () => {
372
369
373
370
specTest (
374
371
'Bloom filter fills in default values for undefined padding and hashCount' ,
375
- // TODO(b/278759251) Remove 'no-ios' once bloom filter is merged.
376
- [ 'no-ios' ] ,
372
+ [ ] ,
377
373
( ) => {
378
374
const query1 = query ( 'collection' ) ;
379
375
const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
@@ -445,8 +441,7 @@ describeSpec('Existence Filters:', [], () => {
445
441
446
442
specTest (
447
443
'Full re-query is triggered when bloom filter hashCount is invalid' ,
448
- // TODO(b/278759251) Remove 'no-ios' once bloom filter is merged.
449
- [ 'no-ios' ] ,
444
+ [ ] ,
450
445
( ) => {
451
446
const query1 = query ( 'collection' ) ;
452
447
const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
@@ -478,187 +473,162 @@ describeSpec('Existence Filters:', [], () => {
478
473
}
479
474
) ;
480
475
481
- specTest (
482
- 'Full re-query is triggered when bloom filter is empty' ,
483
- // TODO(b/278759251) Remove 'no-ios' once bloom filter is merged.
484
- [ 'no-ios' ] ,
485
- ( ) => {
486
- const query1 = query ( 'collection' ) ;
487
- const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
488
- const docB = doc ( 'collection/b' , 1000 , { v : 1 } ) ;
489
-
490
- //Generate an empty bloom filter.
491
- const bloomFilterProto = generateBloomFilterProto ( {
492
- contains : [ ] ,
493
- notContains : [ ] ,
494
- bitCount : 0 ,
495
- hashCount : 0
496
- } ) ;
497
-
498
- return (
499
- spec ( )
500
- . userListens ( query1 )
501
- . watchAcksFull ( query1 , 1000 , docA , docB )
502
- . expectEvents ( query1 , { added : [ docA , docB ] } )
503
- // DocB is deleted in the next sync.
504
- . watchFilters ( [ query1 ] , [ docA . key ] , bloomFilterProto )
505
- . watchSnapshots ( 2000 )
506
- // Re-run query is triggered.
507
- . expectEvents ( query1 , { fromCache : true } )
508
- . expectActiveTargets ( {
509
- query : query1 ,
510
- resumeToken : '' ,
511
- targetPurpose : TargetPurpose . ExistenceFilterMismatch
512
- } )
513
- ) ;
514
- }
515
- ) ;
476
+ specTest ( 'Full re-query is triggered when bloom filter is empty' , [ ] , ( ) => {
477
+ const query1 = query ( 'collection' ) ;
478
+ const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
479
+ const docB = doc ( 'collection/b' , 1000 , { v : 1 } ) ;
516
480
517
- specTest (
518
- 'Same documents can have different bloom filters' ,
519
- // TODO(b/278759251) Remove 'no-ios' once bloom filter is merged.
520
- [ 'no-ios' ] ,
521
- ( ) => {
522
- const query1 = query ( 'collection' , filter ( 'v' , '<=' , 2 ) ) ;
523
- const query2 = query ( 'collection' , filter ( 'v' , '>=' , 2 ) ) ;
481
+ //Generate an empty bloom filter.
482
+ const bloomFilterProto = generateBloomFilterProto ( {
483
+ contains : [ ] ,
484
+ notContains : [ ] ,
485
+ bitCount : 0 ,
486
+ hashCount : 0
487
+ } ) ;
524
488
525
- const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
526
- const docB = doc ( 'collection/b' , 1000 , { v : 2 } ) ;
527
- const docC = doc ( 'collection/c' , 1000 , { v : 3 } ) ;
489
+ return (
490
+ spec ( )
491
+ . userListens ( query1 )
492
+ . watchAcksFull ( query1 , 1000 , docA , docB )
493
+ . expectEvents ( query1 , { added : [ docA , docB ] } )
494
+ // DocB is deleted in the next sync.
495
+ . watchFilters ( [ query1 ] , [ docA . key ] , bloomFilterProto )
496
+ . watchSnapshots ( 2000 )
497
+ // Re-run query is triggered.
498
+ . expectEvents ( query1 , { fromCache : true } )
499
+ . expectActiveTargets ( {
500
+ query : query1 ,
501
+ resumeToken : '' ,
502
+ targetPurpose : TargetPurpose . ExistenceFilterMismatch
503
+ } )
504
+ ) ;
505
+ } ) ;
528
506
529
- const bloomFilterProto1 = generateBloomFilterProto ( {
530
- contains : [ docB ] ,
531
- notContains : [ docA , docC ] ,
532
- bitCount : 5 ,
533
- hashCount : 2
534
- } ) ;
535
- const bloomFilterProto2 = generateBloomFilterProto ( {
536
- contains : [ docB ] ,
537
- notContains : [ docA , docC ] ,
538
- bitCount : 4 ,
539
- hashCount : 1
540
- } ) ;
541
- return (
542
- spec ( )
543
- . userListens ( query1 )
544
- . watchAcksFull ( query1 , 1000 , docA , docB )
545
- . expectEvents ( query1 , { added : [ docA , docB ] } )
546
- . userListens ( query2 )
547
- . expectEvents ( query2 , { added : [ docB ] , fromCache : true } )
548
- . watchAcksFull ( query2 , 1001 , docB , docC )
549
- . expectEvents ( query2 , { added : [ docC ] } )
507
+ specTest ( 'Same documents can have different bloom filters' , [ ] , ( ) => {
508
+ const query1 = query ( 'collection' , filter ( 'v' , '<=' , 2 ) ) ;
509
+ const query2 = query ( 'collection' , filter ( 'v' , '>=' , 2 ) ) ;
550
510
551
- // DocA is deleted in the next sync for query1.
552
- . watchFilters ( [ query1 ] , [ docB . key ] , bloomFilterProto1 )
553
- . watchSnapshots ( 2000 )
554
- // BloomFilter identify docA is deleted, skip full query.
555
- . expectEvents ( query1 , { fromCache : true } )
556
- . expectLimboDocs ( docA . key ) // DocA is now in limbo.
557
-
558
- // DocC is deleted in the next sync for query2.
559
- . watchFilters ( [ query2 ] , [ docB . key ] , bloomFilterProto2 )
560
- . watchSnapshots ( 3000 )
561
- // BloomFilter identify docC is deleted, skip full query.
562
- . expectEvents ( query2 , { fromCache : true } )
563
- . expectLimboDocs ( docA . key , docC . key ) // DocC is now in limbo.
564
- ) ;
565
- }
566
- ) ;
511
+ const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
512
+ const docB = doc ( 'collection/b' , 1000 , { v : 2 } ) ;
513
+ const docC = doc ( 'collection/c' , 1000 , { v : 3 } ) ;
514
+
515
+ const bloomFilterProto1 = generateBloomFilterProto ( {
516
+ contains : [ docB ] ,
517
+ notContains : [ docA , docC ] ,
518
+ bitCount : 5 ,
519
+ hashCount : 2
520
+ } ) ;
521
+ const bloomFilterProto2 = generateBloomFilterProto ( {
522
+ contains : [ docB ] ,
523
+ notContains : [ docA , docC ] ,
524
+ bitCount : 4 ,
525
+ hashCount : 1
526
+ } ) ;
527
+ return (
528
+ spec ( )
529
+ . userListens ( query1 )
530
+ . watchAcksFull ( query1 , 1000 , docA , docB )
531
+ . expectEvents ( query1 , { added : [ docA , docB ] } )
532
+ . userListens ( query2 )
533
+ . expectEvents ( query2 , { added : [ docB ] , fromCache : true } )
534
+ . watchAcksFull ( query2 , 1001 , docB , docC )
535
+ . expectEvents ( query2 , { added : [ docC ] } )
567
536
568
- specTest (
569
- 'Bloom filter is handled at global snapshot' ,
570
- // TODO(b/278759251) Remove 'no-ios' once bloom filter is merged.
571
- [ 'no-ios' ] ,
572
- ( ) => {
573
- const query1 = query ( 'collection' ) ;
574
- const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
575
- const docB = doc ( 'collection/b' , 2000 , { v : 2 } ) ;
576
- const docC = doc ( 'collection/c' , 3000 , { v : 3 } ) ;
537
+ // DocA is deleted in the next sync for query1.
538
+ . watchFilters ( [ query1 ] , [ docB . key ] , bloomFilterProto1 )
539
+ . watchSnapshots ( 2000 )
540
+ // BloomFilter identify docA is deleted, skip full query.
541
+ . expectEvents ( query1 , { fromCache : true } )
542
+ . expectLimboDocs ( docA . key ) // DocA is now in limbo.
543
+
544
+ // DocC is deleted in the next sync for query2.
545
+ . watchFilters ( [ query2 ] , [ docB . key ] , bloomFilterProto2 )
546
+ . watchSnapshots ( 3000 )
547
+ // BloomFilter identify docC is deleted, skip full query.
548
+ . expectEvents ( query2 , { fromCache : true } )
549
+ . expectLimboDocs ( docA . key , docC . key ) // DocC is now in limbo.
550
+ ) ;
551
+ } ) ;
577
552
578
- const bloomFilterProto = generateBloomFilterProto ( {
579
- contains : [ docA ] ,
580
- notContains : [ docB ]
581
- } ) ;
553
+ specTest ( 'Bloom filter is handled at global snapshot' , [ ] , ( ) => {
554
+ const query1 = query ( 'collection' ) ;
555
+ const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
556
+ const docB = doc ( 'collection/b' , 2000 , { v : 2 } ) ;
557
+ const docC = doc ( 'collection/c' , 3000 , { v : 3 } ) ;
582
558
583
- return (
584
- spec ( )
585
- . userListens ( query1 )
586
- . watchAcksFull ( query1 , 1000 , docA , docB )
587
- . expectEvents ( query1 , { added : [ docA , docB ] } )
588
- // Send a mismatching existence filter with one document, but don't
589
- // send a new global snapshot. We should not see an event until we
590
- // receive the snapshot.
591
- . watchFilters ( [ query1 ] , [ docA . key ] , bloomFilterProto )
592
- . watchSends ( { affects : [ query1 ] } , docC )
593
- . watchSnapshots ( 2000 )
594
- . expectEvents ( query1 , { added : [ docC ] , fromCache : true } )
595
- // Re-run of the query1 is skipped, docB is in limbo.
596
- . expectLimboDocs ( docB . key )
597
- ) ;
598
- }
599
- ) ;
559
+ const bloomFilterProto = generateBloomFilterProto ( {
560
+ contains : [ docA ] ,
561
+ notContains : [ docB ]
562
+ } ) ;
600
563
601
- specTest (
602
- 'Bloom filter limbo resolution is denied' ,
603
- // TODO(b/278759251) Remove 'no-ios' once bloom filter is merged.
604
- [ 'no-ios' ] ,
605
- ( ) => {
606
- const query1 = query ( 'collection' ) ;
607
- const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
608
- const docB = doc ( 'collection/b' , 1000 , { v : 1 } ) ;
609
- const bloomFilterProto = generateBloomFilterProto ( {
610
- contains : [ docA ] ,
611
- notContains : [ docB ]
612
- } ) ;
613
- return spec ( )
564
+ return (
565
+ spec ( )
614
566
. userListens ( query1 )
615
567
. watchAcksFull ( query1 , 1000 , docA , docB )
616
568
. expectEvents ( query1 , { added : [ docA , docB ] } )
569
+ // Send a mismatching existence filter with one document, but don't
570
+ // send a new global snapshot. We should not see an event until we
571
+ // receive the snapshot.
617
572
. watchFilters ( [ query1 ] , [ docA . key ] , bloomFilterProto )
573
+ . watchSends ( { affects : [ query1 ] } , docC )
618
574
. watchSnapshots ( 2000 )
619
- . expectEvents ( query1 , { fromCache : true } )
620
- . expectLimboDocs ( docB . key ) // DocB is now in limbo.
621
- . watchRemoves (
622
- newQueryForPath ( docB . key . path ) ,
623
- new RpcError ( Code . PERMISSION_DENIED , 'no' )
624
- )
625
- . expectLimboDocs ( ) // DocB is no longer in limbo.
626
- . expectEvents ( query1 , {
627
- removed : [ docB ]
628
- } ) ;
629
- }
630
- ) ;
631
-
632
- specTest (
633
- 'Bloom filter with large size works as expected' ,
634
- // TODO(b/278759251) Remove 'no-ios' once bloom filter is merged.
635
- [ 'no-ios' ] ,
636
- ( ) => {
637
- const query1 = query ( 'collection' ) ;
638
- const docs = [ ] ;
639
- for ( let i = 0 ; i < 100 ; i ++ ) {
640
- docs . push ( doc ( `collection/doc${ i } ` , 1000 , { v : 1 } ) ) ;
641
- }
642
- const docKeys = docs . map ( item => item . key ) ;
575
+ . expectEvents ( query1 , { added : [ docC ] , fromCache : true } )
576
+ // Re-run of the query1 is skipped, docB is in limbo.
577
+ . expectLimboDocs ( docB . key )
578
+ ) ;
579
+ } ) ;
643
580
644
- const bloomFilterProto = generateBloomFilterProto ( {
645
- contains : docs . slice ( 0 , 50 ) ,
646
- notContains : docs . slice ( 50 ) ,
647
- bitCount : 1000 ,
648
- hashCount : 16
581
+ specTest ( 'Bloom filter limbo resolution is denied' , [ ] , ( ) => {
582
+ const query1 = query ( 'collection' ) ;
583
+ const docA = doc ( 'collection/a' , 1000 , { v : 1 } ) ;
584
+ const docB = doc ( 'collection/b' , 1000 , { v : 1 } ) ;
585
+ const bloomFilterProto = generateBloomFilterProto ( {
586
+ contains : [ docA ] ,
587
+ notContains : [ docB ]
588
+ } ) ;
589
+ return spec ( )
590
+ . userListens ( query1 )
591
+ . watchAcksFull ( query1 , 1000 , docA , docB )
592
+ . expectEvents ( query1 , { added : [ docA , docB ] } )
593
+ . watchFilters ( [ query1 ] , [ docA . key ] , bloomFilterProto )
594
+ . watchSnapshots ( 2000 )
595
+ . expectEvents ( query1 , { fromCache : true } )
596
+ . expectLimboDocs ( docB . key ) // DocB is now in limbo.
597
+ . watchRemoves (
598
+ newQueryForPath ( docB . key . path ) ,
599
+ new RpcError ( Code . PERMISSION_DENIED , 'no' )
600
+ )
601
+ . expectLimboDocs ( ) // DocB is no longer in limbo.
602
+ . expectEvents ( query1 , {
603
+ removed : [ docB ]
649
604
} ) ;
650
- return (
651
- spec ( )
652
- . userListens ( query1 )
653
- . watchAcksFull ( query1 , 1000 , ...docs )
654
- . expectEvents ( query1 , { added : docs } )
655
- // Doc0 to doc49 are deleted in the next sync.
656
- . watchFilters ( [ query1 ] , docKeys . slice ( 0 , 50 ) , bloomFilterProto )
657
- . watchSnapshots ( 2000 )
658
- // BloomFilter correctly identifies docs that deleted, skip full query.
659
- . expectEvents ( query1 , { fromCache : true } )
660
- . expectLimboDocs ( ...docKeys . slice ( 50 ) )
661
- ) ;
605
+ } ) ;
606
+
607
+ specTest ( 'Bloom filter with large size works as expected' , [ ] , ( ) => {
608
+ const query1 = query ( 'collection' ) ;
609
+ const docs = [ ] ;
610
+ for ( let i = 0 ; i < 100 ; i ++ ) {
611
+ docs . push ( doc ( `collection/doc${ i } ` , 1000 , { v : 1 } ) ) ;
662
612
}
663
- ) ;
613
+ const docKeys = docs . map ( item => item . key ) ;
614
+
615
+ const bloomFilterProto = generateBloomFilterProto ( {
616
+ contains : docs . slice ( 0 , 50 ) ,
617
+ notContains : docs . slice ( 50 ) ,
618
+ bitCount : 1000 ,
619
+ hashCount : 16
620
+ } ) ;
621
+ return (
622
+ spec ( )
623
+ . userListens ( query1 )
624
+ . watchAcksFull ( query1 , 1000 , ...docs )
625
+ . expectEvents ( query1 , { added : docs } )
626
+ // Doc0 to doc49 are deleted in the next sync.
627
+ . watchFilters ( [ query1 ] , docKeys . slice ( 0 , 50 ) , bloomFilterProto )
628
+ . watchSnapshots ( 2000 )
629
+ // BloomFilter correctly identifies docs that deleted, skip full query.
630
+ . expectEvents ( query1 , { fromCache : true } )
631
+ . expectLimboDocs ( ...docKeys . slice ( 50 ) )
632
+ ) ;
633
+ } ) ;
664
634
} ) ;
0 commit comments