using ZB.MOM.WW.CBDD.Core.Indexing; using ZB.MOM.WW.CBDD.Core.Storage; namespace ZB.MOM.WW.CBDD.Tests; public class BTreeDeleteUnderflowTests { /// /// Executes Delete_HeavyWorkload_Should_Remain_Queryable_After_Merges. /// [Fact] public void Delete_HeavyWorkload_Should_Remain_Queryable_After_Merges() { var dbPath = Path.Combine(Path.GetTempPath(), $"btree_underflow_{Guid.NewGuid():N}.db"); try { using var storage = new StorageEngine(dbPath, PageFileConfig.Default); var index = new BTreeIndex(storage, IndexOptions.CreateBTree("k")); var insertTxn = storage.BeginTransaction().TransactionId; for (int i = 1; i <= 240; i++) { index.Insert(IndexKey.Create(i), new DocumentLocation((uint)(1000 + i), 0), insertTxn); } storage.CommitTransaction(insertTxn); var deleteTxn = storage.BeginTransaction().TransactionId; for (int i = 1; i <= 190; i++) { index.Delete(IndexKey.Create(i), new DocumentLocation((uint)(1000 + i), 0), deleteTxn).ShouldBeTrue(); } storage.CommitTransaction(deleteTxn); for (int i = 1; i <= 190; i++) { index.TryFind(IndexKey.Create(i), out _, 0).ShouldBeFalse(); } for (int i = 191; i <= 240; i++) { index.TryFind(IndexKey.Create(i), out var location, 0).ShouldBeTrue(); location.PageId.ShouldBe((uint)(1000 + i)); } var remaining = index.GreaterThan(IndexKey.Create(190), orEqual: false, 0).ToList(); remaining.Count.ShouldBe(50); remaining.First().Key.ShouldBe(IndexKey.Create(191)); remaining.Last().Key.ShouldBe(IndexKey.Create(240)); } finally { if (File.Exists(dbPath)) File.Delete(dbPath); var walPath = Path.ChangeExtension(dbPath, ".wal"); if (File.Exists(walPath)) File.Delete(walPath); } } }