using MBN_STOCK_WEBVIEW.Core.Playout; using MBN_STOCK_WEBVIEW.Infrastructure.Diagnostics; using MMoneyCoderSharp.Data; namespace MBN_STOCK_WEBVIEW.Infrastructure.Tests; public sealed class NativeOperatorLogTransitionTrackerTests { [Fact] public void DatabaseMapping_CoversEveryClosedHealthState() { var expected = new Dictionary { [DatabaseHealthState.NotConfigured] = NativeOperatorDatabaseState.NotConfigured, [DatabaseHealthState.Healthy] = NativeOperatorDatabaseState.Healthy, [DatabaseHealthState.Unhealthy] = NativeOperatorDatabaseState.Unhealthy, [DatabaseHealthState.TimedOut] = NativeOperatorDatabaseState.TimedOut }; Assert.Equal(Enum.GetValues().Length, expected.Count); foreach (var pair in expected) { Assert.True(NativeOperatorLogTransitionTracker.TryMapDatabaseState( pair.Key, out var actual)); Assert.Equal(pair.Value, actual); } Assert.False(NativeOperatorLogTransitionTracker.TryMapDatabaseState( (DatabaseHealthState)int.MaxValue, out _)); } [Fact] public void TornadoMapping_CoversEveryClosedConnectionState() { var expected = new Dictionary { [PlayoutConnectionState.Disabled] = NativeOperatorTornadoState.Disabled, [PlayoutConnectionState.DryRunReady] = NativeOperatorTornadoState.DryRunReady, [PlayoutConnectionState.Disconnected] = NativeOperatorTornadoState.Disconnected, [PlayoutConnectionState.Connecting] = NativeOperatorTornadoState.Connecting, [PlayoutConnectionState.Connected] = NativeOperatorTornadoState.Connected, [PlayoutConnectionState.Reconnecting] = NativeOperatorTornadoState.Reconnecting, [PlayoutConnectionState.Disconnecting] = NativeOperatorTornadoState.Disconnecting, [PlayoutConnectionState.Faulted] = NativeOperatorTornadoState.Faulted, [PlayoutConnectionState.OutcomeUnknown] = NativeOperatorTornadoState.OutcomeUnknown, [PlayoutConnectionState.Disposed] = NativeOperatorTornadoState.Disposed }; Assert.Equal(Enum.GetValues().Length, expected.Count); foreach (var pair in expected) { Assert.True(NativeOperatorLogTransitionTracker.TryMapTornadoState( pair.Key, out var actual)); Assert.Equal(pair.Value, actual); } Assert.False(NativeOperatorLogTransitionTracker.TryMapTornadoState( (PlayoutConnectionState)int.MaxValue, out _)); } [Fact] public void DatabaseTransitions_SuppressDuplicatesIndependentlyPerProvider() { var tracker = new NativeOperatorLogTransitionTracker(); Assert.True(tracker.TryObserveDatabaseState( DataSourceKind.Oracle, DatabaseHealthState.Healthy, out var oracleHealthy)); Assert.Equal(NativeOperatorLogEvent.OracleStateChanged, oracleHealthy.Event); Assert.Equal(NativeOperatorDatabaseState.Healthy, oracleHealthy.DatabaseState); Assert.False(tracker.TryObserveDatabaseState( DataSourceKind.Oracle, DatabaseHealthState.Healthy, out _)); Assert.True(tracker.TryObserveDatabaseState( DataSourceKind.MariaDb, DatabaseHealthState.Healthy, out var mariaHealthy)); Assert.Equal(NativeOperatorLogEvent.MariaDbStateChanged, mariaHealthy.Event); Assert.False(tracker.TryObserveDatabaseState( DataSourceKind.MariaDb, DatabaseHealthState.Healthy, out _)); Assert.True(tracker.TryObserveDatabaseState( DataSourceKind.Oracle, DatabaseHealthState.TimedOut, out var oracleTimedOut)); Assert.Equal(NativeOperatorDatabaseState.TimedOut, oracleTimedOut.DatabaseState); Assert.False(tracker.TryObserveDatabaseState( (DataSourceKind)int.MaxValue, DatabaseHealthState.Healthy, out _)); } [Fact] public void TornadoTransitions_SuppressOnlyIdenticalConsecutiveStates() { var tracker = new NativeOperatorLogTransitionTracker(); Assert.True(tracker.TryObserveTornadoState( PlayoutConnectionState.Disconnected, out var disconnected)); Assert.Equal(NativeOperatorTornadoState.Disconnected, disconnected.TornadoState); Assert.False(tracker.TryObserveTornadoState( PlayoutConnectionState.Disconnected, out _)); Assert.True(tracker.TryObserveTornadoState( PlayoutConnectionState.Connecting, out var connecting)); Assert.Equal(NativeOperatorTornadoState.Connecting, connecting.TornadoState); Assert.True(tracker.TryObserveTornadoState( PlayoutConnectionState.Disconnected, out _)); } [Fact] public void CommandTracker_EmitsOneRequestAndExactlyOneMatchingTerminalRecord() { var tracker = new NativeOperatorCommandLogTracker(); Assert.True(tracker.TryBegin( NativeOperatorPlayoutCommand.Prepare, out var requested)); Assert.Equal(NativeOperatorLogEvent.PlayoutCommandRequested, requested.Event); Assert.Equal(NativeOperatorPlayoutCommand.Prepare, requested.Command); Assert.False(tracker.TryComplete( NativeOperatorPlayoutCommand.Next, NativeOperatorPlayoutCompletion.Succeeded, out _)); Assert.True(tracker.TryComplete( NativeOperatorPlayoutCommand.Prepare, NativeOperatorPlayoutCompletion.Rejected, out var completed)); Assert.Equal(NativeOperatorLogEvent.PlayoutCommandCompleted, completed.Event); Assert.Equal(NativeOperatorPlayoutCompletion.Rejected, completed.Completion); Assert.False(tracker.TryComplete( NativeOperatorPlayoutCommand.Prepare, NativeOperatorPlayoutCompletion.Succeeded, out _)); Assert.False(tracker.TryMarkCurrentOutcomeUnknown(out _)); } [Fact] public void CommandTracker_TimeoutOutcomeWinsAndSuppressesLateCompletion() { var tracker = new NativeOperatorCommandLogTracker(); Assert.True(tracker.TryBegin(NativeOperatorPlayoutCommand.TakeIn, out _)); Assert.True(tracker.TryMarkCurrentOutcomeUnknown(out var unknown)); Assert.Equal(NativeOperatorLogEvent.OutcomeUnknown, unknown.Event); Assert.Equal(NativeOperatorPlayoutCommand.TakeIn, unknown.Command); Assert.False(tracker.TryComplete( NativeOperatorPlayoutCommand.TakeIn, NativeOperatorPlayoutCompletion.Succeeded, out _)); Assert.True(tracker.TryBegin(NativeOperatorPlayoutCommand.Next, out _)); Assert.True(tracker.TryMarkOutcomeUnknown( NativeOperatorPlayoutCommand.Next, out var secondUnknown)); Assert.Equal(NativeOperatorLogEvent.OutcomeUnknown, secondUnknown.Event); } [Fact] public void CommandTracker_UndefinedScalarsFailClosed() { var tracker = new NativeOperatorCommandLogTracker(); Assert.False(tracker.TryBegin((NativeOperatorPlayoutCommand)int.MaxValue, out _)); Assert.False(tracker.TryComplete( NativeOperatorPlayoutCommand.Prepare, (NativeOperatorPlayoutCompletion)int.MaxValue, out _)); Assert.False(tracker.TryMarkOutcomeUnknown( (NativeOperatorPlayoutCommand)int.MaxValue, out _)); } }