feat: verify Tornado PGM cut sequence

This commit is contained in:
2026-07-10 16:05:06 +09:00
parent 930424b752
commit d12a5d8095
15 changed files with 4344 additions and 74 deletions

View File

@@ -185,6 +185,95 @@ public sealed class DynamicK3dSessionTests
Assert.Equal(1, log.Names.Count(name => name == "Disconnect"));
}
[Fact]
public async Task GuardedConnect_WhenFinalTargetCheckFails_BlocksKtapAndNeverDisconnects()
{
using var scenes = TemporarySceneDirectory.Create("test-scene.t2s");
var options = ValidatedPlayoutOptions.Create(TestOptions(scenes.Path));
var log = new FakeComLog();
var engine = new FakeEngine(log, new FakePlayer(log), new FakeScene(log));
var activator = new FakeActivator(log, engine);
var releaser = new FakeReleaser(
log,
(engine, "Engine"),
(activator.EventHandler, "EventHandler"));
await using var dispatcher = new StaDispatcher(capacity: 1);
await dispatcher.InvokeAsync(
() =>
{
using var session = new DynamicK3dSession(activator, releaser);
Assert.Throws<K3dConnectSafetyException>(() => session.ConnectGuarded(
options,
() =>
{
log.Add("FinalSafetyCheck");
return false;
},
new FakeK3dSdkDispatchLatch()));
Assert.Equal(
PlayoutKtapConnectState.NotAttempted,
session.LastKtapConnectState);
return true;
},
TimeSpan.FromSeconds(5),
CancellationToken.None);
Assert.Equal(
new[]
{
$"Create:{K3dComConstants.KaEventHandlerClassGuid:B}",
$"Create:{K3dComConstants.KaEngineClassGuid:B}",
"FinalSafetyCheck",
"Release:Engine",
"Release:EventHandler"
},
log.Names);
Assert.DoesNotContain(log.Names, name =>
name.StartsWith("KTAPConnect:", StringComparison.Ordinal));
Assert.DoesNotContain("Disconnect", log.Names);
}
[Fact]
public async Task GuardedConnect_WhenKtapThrows_ReleasesWithoutSdkDisconnect()
{
using var scenes = TemporarySceneDirectory.Create("test-scene.t2s");
var options = ValidatedPlayoutOptions.Create(TestOptions(scenes.Path));
var log = new FakeComLog();
var failure = new COMException("fake ambiguous guarded connect failure");
var engine = new FakeEngine(
log,
new FakePlayer(log),
new FakeScene(log),
connectFailure: failure);
var activator = new FakeActivator(log, engine);
var releaser = new FakeReleaser(
log,
(engine, "Engine"),
(activator.EventHandler, "EventHandler"));
await using var dispatcher = new StaDispatcher(capacity: 1);
await dispatcher.InvokeAsync(
() =>
{
using var session = new DynamicK3dSession(activator, releaser);
var exception = Assert.Throws<COMException>(
() => session.ConnectGuarded(
options,
() => true,
new FakeK3dSdkDispatchLatch()));
Assert.Same(failure, exception);
return true;
},
TimeSpan.FromSeconds(5),
CancellationToken.None);
Assert.Contains("KTAPConnect:1:127.0.0.1:30001:0", log.Names);
Assert.DoesNotContain("Disconnect", log.Names);
Assert.Equal(1, log.Names.Count(name => name == "Release:Engine"));
Assert.Equal(1, log.Names.Count(name => name == "Release:EventHandler"));
}
[Theory]
[InlineData(PlayoutTakeOutScope.All, "StopAll")]
[InlineData(PlayoutTakeOutScope.Layout, "CutOut:10")]