feat: migrate legacy playout workflow and scenes

This commit is contained in:
2026-07-10 23:58:45 +09:00
parent 491a740505
commit 8dae7b8e0d
128 changed files with 39177 additions and 205 deletions

View File

@@ -6,7 +6,7 @@ namespace MBN_STOCK_WEBVIEW.Playout.Tests;
public sealed class PlayoutSafetyValidationTests : IDisposable
{
private readonly TemporarySceneDirectory _scenes =
TemporarySceneDirectory.Create("test-scene.t2s");
TemporarySceneDirectory.Create("test-scene.t2s", "Video\\background.vrv");
[Theory]
[InlineData("Tornado2", true)]
@@ -94,6 +94,24 @@ public sealed class PlayoutSafetyValidationTests : IDisposable
Assert.Contains(nameof(PlayoutOptions.TestSceneAllowlist), exception.Message, StringComparison.Ordinal);
}
[Fact]
public void Validate_LiveModeRequiresClosedSceneAllowlist()
{
var options = ValidTestOptions();
options.Mode = PlayoutMode.Live;
options.OutputChannel = null;
options.TestProcessWindowTitlePattern = null;
options.TestSceneAllowlist = [];
var exception = Assert.Throws<PlayoutConfigurationException>(
() => ValidatedPlayoutOptions.Create(options));
Assert.Contains(
nameof(PlayoutOptions.TestSceneAllowlist),
exception.Message,
StringComparison.Ordinal);
}
[Theory]
[InlineData("localhost")]
[InlineData("test-tornado.local")]
@@ -202,6 +220,65 @@ public sealed class PlayoutSafetyValidationTests : IDisposable
Assert.DoesNotContain(rootedPath, exception.Message, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void ResolveCue_CanonicalizesAllowlistedBackgroundTextureUnderSceneRoot()
{
var validated = ValidatedPlayoutOptions.Create(ValidTestOptions());
var resolved = validated.ResolveCue(new PlayoutCue(
"test-scene.t2s",
"test-scene",
Mutations: [new PlayoutSetBackgroundTexture("Video/background.vrv")]));
var texture = Assert.IsType<PlayoutSetBackgroundTexture>(Assert.Single(resolved.Mutations!));
Assert.Equal(
Path.Combine(_scenes.Path, "Video", "background.vrv"),
texture.AssetPath,
ignoreCase: true);
}
[Fact]
public void ResolveCue_AcceptsTheLegacy2004BackgroundVideoLoopValue()
{
var validated = ValidatedPlayoutOptions.Create(ValidTestOptions());
var resolved = validated.ResolveCue(new PlayoutCue(
"test-scene.t2s",
"test-scene",
Mutations:
[
new PlayoutSetBackgroundVideo(
"Video/background.vrv",
LoopCount: 2004,
LoopInfinite: true)
]));
var video = Assert.IsType<PlayoutSetBackgroundVideo>(Assert.Single(resolved.Mutations!));
Assert.Equal(2004, video.LoopCount);
Assert.Equal(
Path.Combine(_scenes.Path, "Video", "background.vrv"),
video.AssetPath,
ignoreCase: true);
}
[Theory]
[InlineData("../outside.vrv")]
[InlineData("Video/missing.vrv")]
[InlineData("Video/background.exe")]
public void ResolveCue_RejectsUnsafeBackgroundTextureWithoutLeakingInput(string assetPath)
{
var validated = ValidatedPlayoutOptions.Create(ValidTestOptions());
var exception = Assert.Throws<PlayoutRequestException>(() =>
validated.ResolveCue(new PlayoutCue(
"test-scene.t2s",
"test-scene",
Mutations: [new PlayoutSetBackgroundTexture(assetPath)])));
Assert.DoesNotContain(assetPath, exception.Message, StringComparison.OrdinalIgnoreCase);
Assert.DoesNotContain(_scenes.Path, exception.Message, StringComparison.OrdinalIgnoreCase);
}
[Theory]
[InlineData(0, 5000, 64, nameof(PlayoutOptions.Port))]
[InlineData(30001, 99, 64, nameof(PlayoutOptions.OperationTimeoutMilliseconds))]