Add XML docs required by CommentChecker fixes
All checks were successful
NuGet Package Publish / nuget (push) Successful in 1m13s
All checks were successful
NuGet Package Publish / nuget (push) Successful in 1m13s
This commit is contained in:
@@ -12,6 +12,9 @@ namespace ZB.MOM.WW.CBDDC.Sample.Console.Tests;
|
||||
|
||||
public class LmdbOplogMigrationTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Verifies dual-write mode writes each entry to both Surreal and LMDB stores.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task FeatureFlags_DualWrite_WritesToBothStores()
|
||||
{
|
||||
@@ -39,6 +42,9 @@ public class LmdbOplogMigrationTests
|
||||
(await lmdbStore.GetEntryByHashAsync(entry.Hash)).ShouldNotBeNull();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies preferred LMDB reads reconcile missing LMDB data from Surreal.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task FeatureFlags_PreferLmdbReads_ReconcilesFromSurrealWhenLmdbMissingEntries()
|
||||
{
|
||||
@@ -78,6 +84,9 @@ public class LmdbOplogMigrationTests
|
||||
telemetry.ReconciledEntries.ShouldBeGreaterThanOrEqualTo(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies shadow validation records mismatches when LMDB and Surreal diverge.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task FeatureFlags_ShadowValidation_RecordsMismatchTelemetry()
|
||||
{
|
||||
@@ -112,6 +121,9 @@ public class LmdbOplogMigrationTests
|
||||
snapshot.ShadowMismatches.ShouldBe(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies rollback to Surreal when dual-write is disabled uses Surreal for all writes and reads.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task FeatureFlags_RollbackToSurreal_UsesSurrealForWritesAndReads()
|
||||
{
|
||||
@@ -143,6 +155,9 @@ public class LmdbOplogMigrationTests
|
||||
routedRead.Hash.ShouldBe(entry.Hash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies backfill succeeds and records matching dataset counts.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task BackfillTool_BackfillAndValidate_ReportsSuccess()
|
||||
{
|
||||
@@ -173,6 +188,9 @@ public class LmdbOplogMigrationTests
|
||||
report.DestinationCount.ShouldBe(4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies backfill can target non-primary datasets successfully.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task BackfillTool_BackfillAndValidate_WorksPerDataset()
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace ZB.MOM.WW.CBDDC.Sample.Console.Tests;
|
||||
|
||||
public class SurrealOplogStoreContractParityTests : OplogStoreContractTestBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override Task<IOplogStoreContractHarness> CreateHarnessAsync()
|
||||
{
|
||||
return Task.FromResult<IOplogStoreContractHarness>(new SurrealOplogStoreContractHarness());
|
||||
@@ -20,11 +21,15 @@ public class SurrealOplogStoreContractParityTests : OplogStoreContractTestBase
|
||||
|
||||
public class LmdbOplogStoreContractTests : OplogStoreContractTestBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override Task<IOplogStoreContractHarness> CreateHarnessAsync()
|
||||
{
|
||||
return Task.FromResult<IOplogStoreContractHarness>(new LmdbOplogStoreContractHarness());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies prune operations clear index tables as expected.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Lmdb_IndexConsistency_InsertPopulatesAndPruneRemovesIndexes()
|
||||
{
|
||||
@@ -54,6 +59,9 @@ public class LmdbOplogStoreContractTests : OplogStoreContractTestBase
|
||||
after.OplogNodeHeadCount.ShouldBe(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies prune retains newer entries while removing qualifying stale records.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Lmdb_Prune_RemovesAtOrBeforeCutoff_AndKeepsNewerInterleavedEntries()
|
||||
{
|
||||
@@ -79,6 +87,9 @@ public class LmdbOplogStoreContractTests : OplogStoreContractTestBase
|
||||
remaining.Contains(nodeANew.Hash).ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies node head values recompute correctly after prune operations.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Lmdb_NodeHead_AdvancesAndRecomputesAcrossPrune()
|
||||
{
|
||||
@@ -100,6 +111,9 @@ public class LmdbOplogStoreContractTests : OplogStoreContractTestBase
|
||||
(await store.GetLastEntryHashAsync("node-a")).ShouldBeNull();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies durable persistence preserves node head after reopen.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Lmdb_RestartDurability_PreservesHeadAndScans()
|
||||
{
|
||||
@@ -121,6 +135,9 @@ public class LmdbOplogStoreContractTests : OplogStoreContractTestBase
|
||||
after[1].Hash.ShouldBe(entry2.Hash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies appending duplicate entries remains idempotent.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Lmdb_Dedupe_DuplicateHashAppendIsIdempotent()
|
||||
{
|
||||
@@ -137,6 +154,9 @@ public class LmdbOplogStoreContractTests : OplogStoreContractTestBase
|
||||
exported[0].Hash.ShouldBe(entry.Hash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies prune performance remains bounded under large synthetic datasets.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Lmdb_PrunePerformanceSmoke_LargeSyntheticWindow_CompletesWithinGenerousBudget()
|
||||
{
|
||||
@@ -164,30 +184,53 @@ internal sealed class SurrealOplogStoreContractHarness : IOplogStoreContractHarn
|
||||
{
|
||||
private readonly SurrealTestHarness _harness;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new surrogate Surreal contract harness.
|
||||
/// </summary>
|
||||
public SurrealOplogStoreContractHarness()
|
||||
{
|
||||
_harness = new SurrealTestHarness();
|
||||
Store = _harness.CreateOplogStore();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the active store instance.
|
||||
/// </summary>
|
||||
public IOplogStore Store { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reopens the Surreal store and returns a fresh harness handle.
|
||||
/// </summary>
|
||||
public IOplogStore ReopenStore()
|
||||
{
|
||||
Store = _harness.CreateOplogStore();
|
||||
return Store;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends an entry into the Surreal store for a dataset.
|
||||
/// </summary>
|
||||
/// <param name="entry">The oplog entry to append.</param>
|
||||
/// <param name="datasetId">The dataset identifier for the append operation.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
public Task AppendOplogEntryAsync(OplogEntry entry, string datasetId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return ((SurrealOplogStore)Store).AppendOplogEntryAsync(entry, datasetId, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports all entries for a dataset from the Surreal store.
|
||||
/// </summary>
|
||||
/// <param name="datasetId">The dataset identifier to export.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
public Task<IEnumerable<OplogEntry>> ExportAsync(string datasetId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return ((SurrealOplogStore)Store).ExportAsync(datasetId, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes Surreal harness resources.
|
||||
/// </summary>
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return _harness.DisposeAsync();
|
||||
@@ -199,6 +242,9 @@ internal sealed class LmdbOplogStoreContractHarness : IOplogStoreContractHarness
|
||||
private readonly string _rootPath;
|
||||
private LmdbOplogStore? _store;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new LMDB contract harness and backing store.
|
||||
/// </summary>
|
||||
public LmdbOplogStoreContractHarness()
|
||||
{
|
||||
_rootPath = Path.Combine(Path.GetTempPath(), "cbddc-lmdb-tests", Guid.NewGuid().ToString("N"));
|
||||
@@ -206,8 +252,14 @@ internal sealed class LmdbOplogStoreContractHarness : IOplogStoreContractHarness
|
||||
_store = CreateStore();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the active LMDB store.
|
||||
/// </summary>
|
||||
public IOplogStore Store => _store ?? throw new ObjectDisposedException(nameof(LmdbOplogStoreContractHarness));
|
||||
|
||||
/// <summary>
|
||||
/// Recreates the LMDB store instance and returns it.
|
||||
/// </summary>
|
||||
public IOplogStore ReopenStore()
|
||||
{
|
||||
_store?.Dispose();
|
||||
@@ -215,18 +267,32 @@ internal sealed class LmdbOplogStoreContractHarness : IOplogStoreContractHarness
|
||||
return _store;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends an entry into the LMDB store for a dataset.
|
||||
/// </summary>
|
||||
/// <param name="entry">The oplog entry to append.</param>
|
||||
/// <param name="datasetId">The dataset identifier for the append operation.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
public Task AppendOplogEntryAsync(OplogEntry entry, string datasetId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return (_store ?? throw new ObjectDisposedException(nameof(LmdbOplogStoreContractHarness)))
|
||||
.AppendOplogEntryAsync(entry, datasetId, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports all entries for a dataset from the LMDB store.
|
||||
/// </summary>
|
||||
/// <param name="datasetId">The dataset identifier to export.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
public Task<IEnumerable<OplogEntry>> ExportAsync(string datasetId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return (_store ?? throw new ObjectDisposedException(nameof(LmdbOplogStoreContractHarness)))
|
||||
.ExportAsync(datasetId, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes LMDB harness resources.
|
||||
/// </summary>
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
_store?.Dispose();
|
||||
|
||||
@@ -6,6 +6,9 @@ namespace ZB.MOM.WW.CBDDC.Sample.Console.Tests;
|
||||
|
||||
public class MultiDatasetConfigParsingTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Verifies multi-dataset section binds runtime options from JSON.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void MultiDatasetSection_ShouldBindRuntimeOptions()
|
||||
{
|
||||
|
||||
@@ -6,6 +6,9 @@ namespace ZB.MOM.WW.CBDDC.Sample.Console.Tests;
|
||||
|
||||
public abstract class OplogStoreContractTestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Verifies append, merge, and drop behavior across query, chain, and restart scenarios.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task OplogStore_AppendQueryMergeDrop_AndLastHash_Works()
|
||||
{
|
||||
@@ -46,6 +49,9 @@ public abstract class OplogStoreContractTestBase
|
||||
(await rehydratedStore.ExportAsync()).ShouldBeEmpty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies dataset isolation between primary and secondary stores.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task OplogStore_DatasetIsolation_Works()
|
||||
{
|
||||
@@ -68,6 +74,9 @@ public abstract class OplogStoreContractTestBase
|
||||
logs[0].DatasetId.ShouldBe(DatasetId.Logs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies chain range queries return ordered linked entries.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task OplogStore_GetChainRangeAsync_ReturnsOrderedLinkedRange()
|
||||
{
|
||||
@@ -89,8 +98,20 @@ public abstract class OplogStoreContractTestBase
|
||||
range[1].Hash.ShouldBe(entry3.Hash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the contract harness for this test class.
|
||||
/// </summary>
|
||||
protected abstract Task<IOplogStoreContractHarness> CreateHarnessAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a reusable oplog entry with deterministic timestamps.
|
||||
/// </summary>
|
||||
/// <param name="collection">The collection name.</param>
|
||||
/// <param name="key">The entry key.</param>
|
||||
/// <param name="nodeId">The node identifier generating the entry.</param>
|
||||
/// <param name="wall">The wall-clock component of the HLC timestamp.</param>
|
||||
/// <param name="logic">The logical clock component of the HLC timestamp.</param>
|
||||
/// <param name="previousHash">The previous entry hash.</param>
|
||||
protected static OplogEntry CreateOplogEntry(
|
||||
string collection,
|
||||
string key,
|
||||
@@ -111,11 +132,28 @@ public abstract class OplogStoreContractTestBase
|
||||
|
||||
public interface IOplogStoreContractHarness : IAsyncDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the active contract store.
|
||||
/// </summary>
|
||||
IOplogStore Store { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Reopens the harness storage.
|
||||
/// </summary>
|
||||
IOplogStore ReopenStore();
|
||||
|
||||
/// <summary>
|
||||
/// Appends an entry for the specified dataset.
|
||||
/// </summary>
|
||||
/// <param name="entry">The oplog entry to append.</param>
|
||||
/// <param name="datasetId">The dataset identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
Task AppendOplogEntryAsync(OplogEntry entry, string datasetId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Exports entries for the specified dataset.
|
||||
/// </summary>
|
||||
/// <param name="datasetId">The dataset identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
Task<IEnumerable<OplogEntry>> ExportAsync(string datasetId, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user