using Microsoft.Extensions.Logging.Abstractions;
using ZB.MOM.WW.CBDDC.Core;
using ZB.MOM.WW.CBDDC.Core.Network;
using ZB.MOM.WW.CBDDC.Core.Storage;
namespace ZB.MOM.WW.CBDDC.Network.Tests;
public class MultiDatasetSyncOrchestratorTests
{
///
/// Verifies multi-dataset sync is disabled, only the primary context is created.
///
[Fact]
public void Constructor_WhenMultiDatasetDisabled_ShouldOnlyCreatePrimaryContext()
{
var sut = CreateSut(
[
new DatasetSyncOptions { DatasetId = DatasetId.Primary, Enabled = true },
new DatasetSyncOptions { DatasetId = DatasetId.Logs, Enabled = true }
],
new MultiDatasetRuntimeOptions
{
EnableMultiDatasetSync = false,
EnableDatasetPrimary = true,
EnableDatasetLogs = true
});
var datasetIds = sut.Contexts.Select(c => c.DatasetId).ToList();
datasetIds.Count.ShouldBe(1);
datasetIds[0].ShouldBe(DatasetId.Primary);
}
///
/// Verifies that failures in one orchestrator do not prevent remaining contexts from starting and stopping.
///
[Fact]
public async Task StartStop_WhenOneDatasetThrows_ShouldContinueOtherDatasets()
{
var orchestrators = new Dictionary(StringComparer.Ordinal)
{
[DatasetId.Primary] = new TrackingSyncOrchestrator(),
[DatasetId.Logs] = new TrackingSyncOrchestrator(startException: new InvalidOperationException("boom")),
[DatasetId.Timeseries] = new TrackingSyncOrchestrator()
};
var sut = CreateSut(
[],
new MultiDatasetRuntimeOptions
{
EnableMultiDatasetSync = true,
EnableDatasetPrimary = true,
EnableDatasetLogs = true,
EnableDatasetTimeseries = true
},
options => orchestrators[DatasetId.Normalize(options.DatasetId)]);
await sut.Start();
await sut.Stop();
orchestrators[DatasetId.Primary].StartCalls.ShouldBe(1);
orchestrators[DatasetId.Primary].StopCalls.ShouldBe(1);
orchestrators[DatasetId.Logs].StartCalls.ShouldBe(1);
orchestrators[DatasetId.Logs].StopCalls.ShouldBe(1);
orchestrators[DatasetId.Timeseries].StartCalls.ShouldBe(1);
orchestrators[DatasetId.Timeseries].StopCalls.ShouldBe(1);
}
private static MultiDatasetSyncOrchestrator CreateSut(
IEnumerable datasetOptions,
MultiDatasetRuntimeOptions runtimeOptions,
Func? orchestratorFactory = null)
{
return new MultiDatasetSyncOrchestrator(
Substitute.For(),
Substitute.For(),
Substitute.For(),
Substitute.For(),
Substitute.For(),
Substitute.For(),
NullLoggerFactory.Instance,
datasetOptions,
runtimeOptions,
orchestratorFactory: orchestratorFactory);
}
private sealed class TrackingSyncOrchestrator(Exception? startException = null, Exception? stopException = null)
: ISyncOrchestrator
{
///
/// Number of times has been called.
///
public int StartCalls { get; private set; }
///
/// Number of times has been called.
///
public int StopCalls { get; private set; }
///
/// Starts the orchestrator.
///
public Task Start()
{
StartCalls++;
if (startException != null) throw startException;
return Task.CompletedTask;
}
///
/// Stops the orchestrator.
///
public Task Stop()
{
StopCalls++;
if (stopException != null) throw stopException;
return Task.CompletedTask;
}
}
}