@@ -445,6 +445,98 @@ describe("IdList", () => {
445445 . true ;
446446 } ) ;
447447
448+ it ( "should bulk delete elements not all known" , ( ) => {
449+ let list = IdList . new ( ) ;
450+ const bunchStartId = { bunchId : "abc" , counter : 0 } ;
451+ const id : ElementId = { bunchId : "abc" , counter : 5 } ;
452+
453+ // Insert counters 5..9; counters 0..4 are not known.
454+ list = list . insertAfter ( null , id , 5 ) ;
455+ expect ( list . length ) . to . equal ( 5 ) ;
456+
457+ // Delete the whole bunch starting at counter 0.
458+ list = list . delete ( bunchStartId , 10 ) ;
459+ expect ( list . length ) . to . equal ( 0 ) ;
460+ expect ( list . has ( id ) ) . to . be . false ;
461+ expect ( list . isKnown ( id ) ) . to . be . true ;
462+ expect ( list . isKnown ( bunchStartId ) ) . to . be . false ;
463+ } ) ;
464+
465+ it ( "should bulk delete across multiple leaves" , ( ) => {
466+ let list = IdList . new ( ) ;
467+ list = list . insertAfter ( null , { bunchId : "test" , counter : 0 } , 10 ) ;
468+ list = list . insertAfter (
469+ { bunchId : "test" , counter : 9 } ,
470+ { bunchId : "test" , counter : 100 } ,
471+ 10
472+ ) ;
473+ // Leaf 1: counters 0..9
474+ // Leaf 2: counters 100..109
475+ expect ( list . length ) . to . equal ( 20 ) ;
476+
477+ // Delete across multiple leaves
478+ list = list . delete ( { bunchId : "test" , counter : 5 } , 100 ) ;
479+ expect ( list . length ) . to . equal ( 10 ) ;
480+ } ) ;
481+
482+ it ( "should bulk delete and undelete across split leaves" , ( ) => {
483+ let list = IdList . new ( ) ;
484+ list = list . insertAfter ( null , { bunchId : "abc" , counter : 0 } , 10 ) ;
485+ // Split the leaf with a different bunch.
486+ list = list . insertAfter (
487+ { bunchId : "abc" , counter : 5 } ,
488+ { bunchId : "def" , counter : 0 } ,
489+ 10
490+ ) ;
491+ expect ( list . length ) . to . equal ( 20 ) ;
492+
493+ // Delete the original bunch.
494+ list = list . delete ( { bunchId : "abc" , counter : 0 } , 10 ) ;
495+
496+ expect ( list . length ) . to . equal ( 10 ) ;
497+ for ( const id of list . values ( ) ) {
498+ expect ( id . bunchId ) . to . equal ( "def" ) ;
499+ }
500+
501+ // Undelete.
502+ list = list . undelete ( { bunchId : "abc" , counter : 0 } , 10 ) ;
503+ expect ( list . length ) . to . equal ( 20 ) ;
504+ expect ( list . at ( 5 ) ) . to . deep . equal ( { bunchId : "abc" , counter : 5 } ) ;
505+ expect ( list . at ( 16 ) ) . to . deep . equal ( { bunchId : "abc" , counter : 6 } ) ;
506+ } ) ;
507+
508+ it ( "should bulk delete and undelete across split leaves 2" , ( ) => {
509+ let list = IdList . new ( ) ;
510+ list = list . insertAfter ( null , { bunchId : "abc" , counter : 0 } , 10 ) ;
511+ // Split the leaf with a different bunch.
512+ list = list . insertAfter (
513+ { bunchId : "abc" , counter : 5 } ,
514+ { bunchId : "def" , counter : 0 } ,
515+ 10
516+ ) ;
517+ expect ( list . length ) . to . equal ( 20 ) ;
518+
519+ // Delete part of the original bunch, crossing the split.
520+ list = list . delete ( { bunchId : "abc" , counter : 2 } , 6 ) ;
521+
522+ expect ( list . length ) . to . equal ( 14 ) ;
523+ for ( let i = 0 ; i < 2 ; i ++ ) {
524+ expect ( list . at ( i ) . bunchId ) . to . equal ( "abc" ) ;
525+ }
526+ for ( let i = 2 ; i < 12 ; i ++ ) {
527+ expect ( list . at ( i ) . bunchId ) . to . equal ( "def" ) ;
528+ }
529+ for ( let i = 12 ; i < 14 ; i ++ ) {
530+ expect ( list . at ( i ) . bunchId ) . to . equal ( "abc" ) ;
531+ }
532+
533+ // Undelete.
534+ list = list . undelete ( { bunchId : "abc" , counter : 2 } , 6 ) ;
535+ expect ( list . length ) . to . equal ( 20 ) ;
536+ expect ( list . at ( 5 ) ) . to . deep . equal ( { bunchId : "abc" , counter : 5 } ) ;
537+ expect ( list . at ( 16 ) ) . to . deep . equal ( { bunchId : "abc" , counter : 6 } ) ;
538+ } ) ;
539+
448540 it ( "should delete a range of elements" , ( ) => {
449541 let list = IdList . new ( ) ;
450542 const id1 : ElementId = { bunchId : "abc" , counter : 1 } ;
@@ -465,6 +557,18 @@ describe("IdList", () => {
465557 { bunchId : id1 . bunchId , counter : 5 } ,
466558 ] ) ;
467559 } ) ;
560+
561+ it ( "should do nothing when count = 0" , ( ) => {
562+ let list = IdList . new ( ) ;
563+ const id : ElementId = { bunchId : "abc" , counter : 1 } ;
564+
565+ list = list . insertAfter ( null , id ) ;
566+ expect ( list . length ) . to . equal ( 1 ) ;
567+
568+ list = list . delete ( id , 0 ) ;
569+ expect ( list . length ) . to . equal ( 1 ) ;
570+ expect ( list . has ( id ) ) . to . be . true ;
571+ } ) ;
468572 } ) ;
469573
470574 describe ( "undelete operations" , ( ) => {
@@ -487,6 +591,17 @@ describe("IdList", () => {
487591 expect ( ( ) => ( list = list . undelete ( id ) ) ) . to . throw ( ) ;
488592 } ) ;
489593
594+ it ( "should throw when any bulk ID is unknown" , ( ) => {
595+ let list = IdList . new ( ) ;
596+ const id1 : ElementId = { bunchId : "abc" , counter : 1 } ;
597+ const id3 : ElementId = { bunchId : "abc" , counter : 3 } ;
598+ list = list . insertAfter ( null , id1 ) ;
599+ list = list . insertAfter ( id1 , id3 ) ;
600+
601+ // Counter 2 is not known.
602+ expect ( ( ) => ( list = list . undelete ( id1 , 3 ) ) ) . to . throw ( ) ;
603+ } ) ;
604+
490605 it ( "should do nothing when undeleting an already present ID" , ( ) => {
491606 let list = IdList . new ( ) ;
492607 const id : ElementId = { bunchId : "abc" , counter : 1 } ;
@@ -518,6 +633,46 @@ describe("IdList", () => {
518633 expect ( list . has ( { bunchId : id . bunchId , counter : id . counter + 3 } ) ) . to . be
519634 . true ;
520635 } ) ;
636+
637+ it ( "should bulk undelete across multiple leaves" , ( ) => {
638+ let list = IdList . new ( ) ;
639+ list = list . insertAfter ( null , { bunchId : "test" , counter : 0 } , 20 ) ;
640+ list = list . insertAfter (
641+ { bunchId : "test" , counter : 9 } ,
642+ { bunchId : "test" , counter : 100 } ,
643+ 1
644+ ) ;
645+ // Leaf A: counter 0..9
646+ // Leaf B: counter 100
647+ // Leaf C: counter 10..19
648+ expect ( list . length ) . to . equal ( 21 ) ;
649+
650+ // Delete counters 5..15
651+ list = list . delete ( { bunchId : "test" , counter : 5 } , 11 ) ;
652+ expect ( list . length ) . to . equal ( 10 ) ;
653+
654+ // Undelete counters 5..15
655+ list = list . undelete ( { bunchId : "test" , counter : 5 } , 11 ) ;
656+ expect ( list . length ) . to . equal ( 21 ) ;
657+
658+ for ( let i = 0 ; i < 20 ; i ++ ) {
659+ expect ( list . has ( { bunchId : "test" , counter : i } ) ) . to . be . true ;
660+ }
661+ expect ( list . has ( { bunchId : "test" , counter : 100 } ) ) . to . be . true ;
662+ } ) ;
663+
664+ it ( "should do nothing when count = 0" , ( ) => {
665+ let list = IdList . new ( ) ;
666+ const id : ElementId = { bunchId : "abc" , counter : 1 } ;
667+
668+ list = list . insertAfter ( null , id ) . delete ( id ) ;
669+ expect ( list . length ) . to . equal ( 0 ) ;
670+
671+ list = list . undelete ( id , 0 ) ;
672+ expect ( list . length ) . to . equal ( 0 ) ;
673+ expect ( list . has ( id ) ) . to . be . false ;
674+ expect ( list . isKnown ( id ) ) . to . be . true ;
675+ } ) ;
521676 } ) ;
522677
523678 describe ( "accessor operations" , ( ) => {
0 commit comments