129 lines
3.7 KiB
C#
Executable File
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);
|
|
}
|
|
}
|