feat: harden isolated Tornado test workflow
This commit is contained in:
200
tests/MBN_STOCK_WEBVIEW.Playout.Tests/SmokeCommandLineTests.cs
Normal file
200
tests/MBN_STOCK_WEBVIEW.Playout.Tests/SmokeCommandLineTests.cs
Normal file
@@ -0,0 +1,200 @@
|
||||
using MBN_STOCK_WEBVIEW.PlayoutSmoke;
|
||||
|
||||
namespace MBN_STOCK_WEBVIEW.Playout.Tests;
|
||||
|
||||
public sealed class SmokeCommandLineTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Tornado2 TEST", false)]
|
||||
[InlineData("TEST-1", false)]
|
||||
[InlineData("Tornado2", true)]
|
||||
[InlineData("PGM", true)]
|
||||
[InlineData("CONTEST", true)]
|
||||
[InlineData("", true)]
|
||||
[InlineData(null, true)]
|
||||
public void TornadoWindowTitleWithoutExplicitTestMarkerIsUnsafe(
|
||||
string? title,
|
||||
bool expected)
|
||||
{
|
||||
Assert.Equal(expected, SmokeCommandLine.IsUnsafeTornadoWindowTitle(title));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_NoArguments_PreservesReadOnlyProbeDefault()
|
||||
{
|
||||
var parsed = SmokeCommandLine.Parse([]);
|
||||
|
||||
Assert.True(parsed.IsValid);
|
||||
Assert.Equal(SmokeCommandKind.Probe, parsed.Invocation.Kind);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("--probe", "Probe")]
|
||||
[InlineData("--PROBE", "Probe")]
|
||||
[InlineData("--dry-run", "DryRun")]
|
||||
public void Parse_ExistingComFreeCommandsRemainAvailable(
|
||||
string argument,
|
||||
string expected)
|
||||
{
|
||||
var parsed = SmokeCommandLine.Parse([argument]);
|
||||
|
||||
Assert.True(parsed.IsValid);
|
||||
Assert.Equal(expected, parsed.Invocation.Kind.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_TestConnectRequiresExplicitAcknowledgementAndConfigArgument()
|
||||
{
|
||||
var withoutAcknowledgement = SmokeCommandLine.Parse(
|
||||
["--test-connect", "--config", "C:\\safe\\playout.local.json"]);
|
||||
var complete = SmokeCommandLine.Parse(
|
||||
[
|
||||
"--test-connect",
|
||||
SmokeCommandLine.AcknowledgementFlag,
|
||||
"--config",
|
||||
"C:\\safe\\playout.local.json"
|
||||
]);
|
||||
|
||||
Assert.False(withoutAcknowledgement.IsValid);
|
||||
Assert.Equal("missing-acknowledgement", withoutAcknowledgement.ErrorCode);
|
||||
Assert.True(complete.IsValid);
|
||||
Assert.Equal(SmokeCommandKind.TestConnect, complete.Invocation.Kind);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_TestSequenceRequiresBothSceneCodesAndBoundedObservation()
|
||||
{
|
||||
var missingObservation = SmokeCommandLine.Parse(
|
||||
[
|
||||
"--test-sequence",
|
||||
SmokeCommandLine.AcknowledgementFlag,
|
||||
"--config",
|
||||
"C:\\safe\\playout.local.json",
|
||||
"--prepare",
|
||||
"5001",
|
||||
"--next",
|
||||
"5006"
|
||||
]);
|
||||
var complete = SmokeCommandLine.Parse(
|
||||
[
|
||||
"--test-sequence",
|
||||
"--prepare",
|
||||
"5001",
|
||||
"--observe-ms",
|
||||
"1000",
|
||||
SmokeCommandLine.AcknowledgementFlag,
|
||||
"--next",
|
||||
"5006",
|
||||
"--config",
|
||||
"C:\\safe\\playout.local.json"
|
||||
]);
|
||||
|
||||
Assert.False(missingObservation.IsValid);
|
||||
Assert.Equal("missing-required-option", missingObservation.ErrorCode);
|
||||
Assert.True(complete.IsValid);
|
||||
Assert.Equal(1000, complete.Invocation.ObservationMilliseconds);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("999")]
|
||||
[InlineData("30001")]
|
||||
[InlineData("1.5")]
|
||||
[InlineData("secret")]
|
||||
public void Parse_RejectsUnboundedOrNonIntegralObservation(string value)
|
||||
{
|
||||
var parsed = ValidSequenceArguments(observation: value);
|
||||
|
||||
Assert.False(parsed.IsValid);
|
||||
Assert.Equal("invalid-observation-duration", parsed.ErrorCode);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("../5001")]
|
||||
[InlineData("5001.t2s")]
|
||||
[InlineData("장면")]
|
||||
[InlineData("SCENE A")]
|
||||
public void Parse_RejectsUnsafeSceneCodesWithoutReflectingThem(string sceneCode)
|
||||
{
|
||||
var parsed = ValidSequenceArguments(prepare: sceneCode);
|
||||
|
||||
Assert.False(parsed.IsValid);
|
||||
Assert.Equal("unsafe-scene-code", parsed.ErrorCode);
|
||||
Assert.DoesNotContain(sceneCode, parsed.ErrorCode, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_TestConnectRejectsMutationOptions()
|
||||
{
|
||||
var parsed = SmokeCommandLine.Parse(
|
||||
[
|
||||
"--test-connect",
|
||||
SmokeCommandLine.AcknowledgementFlag,
|
||||
"--config",
|
||||
"C:\\safe\\playout.local.json",
|
||||
"--prepare",
|
||||
"5001"
|
||||
]);
|
||||
|
||||
Assert.False(parsed.IsValid);
|
||||
Assert.Equal("unknown-option", parsed.ErrorCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_TestSequenceRequiresTwoDistinctSceneCodes()
|
||||
{
|
||||
var parsed = SmokeCommandLine.Parse(
|
||||
[
|
||||
"--test-sequence",
|
||||
SmokeCommandLine.AcknowledgementFlag,
|
||||
"--config",
|
||||
"C:\\safe\\playout.local.json",
|
||||
"--prepare",
|
||||
"5001",
|
||||
"--next",
|
||||
"5001",
|
||||
"--observe-ms",
|
||||
"1000"
|
||||
]);
|
||||
|
||||
Assert.False(parsed.IsValid);
|
||||
Assert.Equal("duplicate-scene-code", parsed.ErrorCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_TestPlanUsesTheSameSequenceInputsButNeverImpliesExecution()
|
||||
{
|
||||
var parsed = SmokeCommandLine.Parse(
|
||||
[
|
||||
"--test-plan",
|
||||
SmokeCommandLine.AcknowledgementFlag,
|
||||
"--config",
|
||||
"C:\\safe\\playout.local.json",
|
||||
"--prepare",
|
||||
"5001",
|
||||
"--next",
|
||||
"5006",
|
||||
"--observe-ms",
|
||||
"5000"
|
||||
]);
|
||||
|
||||
Assert.True(parsed.IsValid);
|
||||
Assert.Equal(SmokeCommandKind.TestPlan, parsed.Invocation.Kind);
|
||||
}
|
||||
|
||||
private static SmokeCommandParseResult ValidSequenceArguments(
|
||||
string prepare = "5001",
|
||||
string observation = "1000") =>
|
||||
SmokeCommandLine.Parse(
|
||||
[
|
||||
"--test-sequence",
|
||||
SmokeCommandLine.AcknowledgementFlag,
|
||||
"--config",
|
||||
"C:\\safe\\playout.local.json",
|
||||
"--prepare",
|
||||
prepare,
|
||||
"--next",
|
||||
"5006",
|
||||
"--observe-ms",
|
||||
observation
|
||||
]);
|
||||
}
|
||||
Reference in New Issue
Block a user