Files
CBDD/tests/CBDD.Tests/CursorTests.cs
Joseph Doherty 3ffd468c79
All checks were successful
NuGet Publish / build-and-pack (push) Successful in 45s
NuGet Publish / publish-to-gitea (push) Successful in 52s
Fix audit findings for coverage, architecture checks, and XML docs
2026-02-20 15:43:25 -05:00

129 lines
3.7 KiB
C#
Executable File

using ZB.MOM.WW.CBDD.Core.Storage;
using ZB.MOM.WW.CBDD.Core.Indexing;
using ZB.MOM.WW.CBDD.Bson;
using Xunit;
namespace ZB.MOM.WW.CBDD.Tests;
public class CursorTests : IDisposable
{
private readonly string _testFile;
private readonly StorageEngine _storage;
private readonly BTreeIndex _index;
/// <summary>
/// Initializes a new instance of the <see cref="CursorTests"/> class.
/// </summary>
public CursorTests()
{
_testFile = Path.Combine(Path.GetTempPath(), $"docdb_cursor_test_{Guid.NewGuid()}.db");
_storage = new StorageEngine(_testFile, PageFileConfig.Default);
var options = IndexOptions.CreateBTree("test");
_index = new BTreeIndex(_storage, options);
SeedData();
}
private void SeedData()
{
var txnId = _storage.BeginTransaction().TransactionId;
// Insert 10, 20, 30
_index.Insert(IndexKey.Create(10), new DocumentLocation(1, 0), txnId);
_index.Insert(IndexKey.Create(20), new DocumentLocation(2, 0), txnId);
_index.Insert(IndexKey.Create(30), new DocumentLocation(3, 0), txnId);
_storage.CommitTransaction(txnId);
}
/// <summary>
/// Tests move to first should position at first.
/// </summary>
[Fact]
public void MoveToFirst_ShouldPositionAtFirst()
{
using var cursor = _index.CreateCursor(0);
cursor.MoveToFirst().ShouldBeTrue();
cursor.Current.Key.ShouldBe(IndexKey.Create(10));
}
/// <summary>
/// Tests move to last should position at last.
/// </summary>
[Fact]
public void MoveToLast_ShouldPositionAtLast()
{
using var cursor = _index.CreateCursor(0);
cursor.MoveToLast().ShouldBeTrue();
cursor.Current.Key.ShouldBe(IndexKey.Create(30));
}
/// <summary>
/// Tests move next should traverse forward.
/// </summary>
[Fact]
public void MoveNext_ShouldTraverseForward()
{
using var cursor = _index.CreateCursor(0);
cursor.MoveToFirst();
cursor.MoveNext().ShouldBeTrue();
cursor.Current.Key.ShouldBe(IndexKey.Create(20));
cursor.MoveNext().ShouldBeTrue();
cursor.Current.Key.ShouldBe(IndexKey.Create(30));
cursor.MoveNext().ShouldBeFalse(); // End
}
/// <summary>
/// Tests move prev should traverse backward.
/// </summary>
[Fact]
public void MovePrev_ShouldTraverseBackward()
{
using var cursor = _index.CreateCursor(0);
cursor.MoveToLast();
cursor.MovePrev().ShouldBeTrue();
cursor.Current.Key.ShouldBe(IndexKey.Create(20));
cursor.MovePrev().ShouldBeTrue();
cursor.Current.Key.ShouldBe(IndexKey.Create(10));
cursor.MovePrev().ShouldBeFalse(); // Start
}
/// <summary>
/// Tests seek should position exact or next.
/// </summary>
[Fact]
public void Seek_ShouldPositionExact_OrNext()
{
using var cursor = _index.CreateCursor(0);
// Exact
cursor.Seek(IndexKey.Create(20)).ShouldBeTrue();
cursor.Current.Key.ShouldBe(IndexKey.Create(20));
// Non-exact (15 -> should land on 20)
cursor.Seek(IndexKey.Create(15)).ShouldBeFalse();
cursor.Current.Key.ShouldBe(IndexKey.Create(20));
// Non-exact (35 -> should be invalid/end)
cursor.Seek(IndexKey.Create(35)).ShouldBeFalse();
// Current should throw invalid
Should.Throw<InvalidOperationException>(() => cursor.Current);
}
/// <summary>
/// Disposes the resources used by this instance.
/// </summary>
public void Dispose()
{
_storage.Dispose();
if (File.Exists(_testFile)) File.Delete(_testFile);
}
}