Files
MBN_STOCK_WEBVIEW/tests/MBN_STOCK_WEBVIEW.Playout.Tests/DynamicK3dEventHandlerTests.cs

104 lines
3.3 KiB
C#

using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using MBN_STOCK_WEBVIEW.Playout.Interop;
namespace MBN_STOCK_WEBVIEW.Playout.Tests;
public sealed class DynamicK3dEventHandlerTests
{
[Fact]
public void GeneratedHandler_ImplementsImportedInterfaceAndForwardsOnlyLifecycleCallbacks()
{
var sink = new RecordingSink();
var value = DynamicK3dEventHandlerBuilder.Create(typeof(IFakeK3dEventHandler), sink);
var handler = Assert.IsAssignableFrom<IFakeK3dEventHandler>(value);
handler.OnHello();
handler.OnScenePlayed(1, 9, 10);
handler.OnCutOut(0, 9, 10);
handler.OnStopAll(1);
handler.OnIgnored("sensitive value");
Assert.Equal(
new[]
{
"OnHello:",
"OnScenePlayed:1,9,10",
"OnCutOut:0,9,10",
"OnStopAll:1"
},
sink.Calls);
Assert.Equal(
ClassInterfaceType.None,
value.GetType().GetCustomAttributes(typeof(ClassInterfaceAttribute), inherit: false)
.Cast<ClassInterfaceAttribute>()
.Single()
.Value);
}
[Fact]
public void EventQueue_ParsesCallbacksWithoutThrowingAcrossNativeBoundary()
{
var queue = new K3dEventQueue(capacity: 4);
queue.OnCallback("OnHello", []);
queue.OnCallback("OnScenePlayed", [1, 9, 10]);
queue.OnCallback("OnCutOut", [0, 9, 10]);
queue.OnCallback("OnStopAll", [1]);
queue.OnCallback("OnScenePlayed", ["invalid"]);
Assert.True(queue.HelloObserved);
Assert.False(queue.HasOverflowed);
Assert.Equal(3, queue.PendingCount);
Assert.True(queue.TryDequeue(out var played));
Assert.Equal(
new K3dLifecycleCallback(K3dLifecycleCallbackKind.ScenePlayed, true, 9, 10),
played);
Assert.True(queue.TryDequeue(out var cut));
Assert.False(cut.IsSuccess);
Assert.True(queue.TryDequeue(out var stopped));
Assert.Equal(K3dLifecycleCallbackKind.StopAll, stopped.Kind);
Assert.False(queue.TryDequeue(out _));
}
[Fact]
public void EventQueue_OverflowLatchesAndNeverExceedsCapacity()
{
var queue = new K3dEventQueue(capacity: 1);
queue.OnCallback("OnStopAll", [1]);
queue.OnCallback("OnStopAll", [1]);
Assert.True(queue.HasOverflowed);
Assert.Equal(1, queue.PendingCount);
Assert.True(queue.TryDequeue(out _));
Assert.False(queue.TryDequeue(out _));
}
private sealed class RecordingSink : IK3dEventSink
{
private readonly ConcurrentQueue<string> _calls = new();
public string[] Calls => _calls.ToArray();
public void OnCallback(string methodName, object?[] arguments) =>
_calls.Enqueue($"{methodName}:{string.Join(',', arguments)}");
}
[ComImport]
[Guid("C21817DB-C0D3-4647-8D85-027338DCF832")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IFakeK3dEventHandler
{
void OnHello();
void OnScenePlayed(int success, int outputChannelIndex, int layerIndex);
void OnCutOut(int success, int outputChannelIndex, int layerIndex);
void OnStopAll(int success);
void OnIgnored(string value);
}
}