feat: make LegacyParityApp playout live-only
This commit is contained in:
@@ -2,6 +2,7 @@ using System.Security;
|
||||
using System.Text;
|
||||
using MBN_STOCK_WEBVIEW.Playout.Configuration;
|
||||
using MBN_STOCK_WEBVIEW.Playout.Diagnostics;
|
||||
using MBN_STOCK_WEBVIEW.Playout.Safety;
|
||||
|
||||
namespace MBN_STOCK_WEBVIEW.Playout.Tests;
|
||||
|
||||
@@ -42,12 +43,18 @@ public sealed class DevelopmentLiveLaunchBootstrapTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResolveLaunchArguments_RejectsMissingOrAdditionalProcessArguments()
|
||||
public void ResolveLaunchArguments_DistinguishesNormalLaunchFromAdditionalArguments()
|
||||
{
|
||||
Assert.Null(DevelopmentLiveLaunchBootstrap.ResolveLaunchArguments("", ["app.exe"]));
|
||||
Assert.Null(DevelopmentLiveLaunchBootstrap.ResolveLaunchArguments(
|
||||
var additionalArguments = DevelopmentLiveLaunchBootstrap.ResolveLaunchArguments(
|
||||
"",
|
||||
["app.exe", DevelopmentLiveLaunchBootstrap.ExactLaunchArgument, "extra"]));
|
||||
["app.exe", DevelopmentLiveLaunchBootstrap.ExactLaunchArgument, "extra"]);
|
||||
|
||||
Assert.NotNull(additionalArguments);
|
||||
Assert.NotEqual(string.Empty, additionalArguments);
|
||||
Assert.NotEqual(
|
||||
DevelopmentLiveLaunchBootstrap.ExactLaunchArgument,
|
||||
additionalArguments);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -65,13 +72,11 @@ public sealed class DevelopmentLiveLaunchBootstrapTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData("--development-live ")]
|
||||
[InlineData(" --development-live")]
|
||||
[InlineData("--DEVELOPMENT-LIVE")]
|
||||
[InlineData("--development-live --another-option")]
|
||||
public void NonExactArgument_SkipsWithoutReadingOrMutating(string? arguments)
|
||||
public void NonExactArgument_IsRejectedWithoutReadingOrMutating(string? arguments)
|
||||
{
|
||||
var platform = FakePlatform.Valid();
|
||||
|
||||
@@ -81,37 +86,56 @@ public sealed class DevelopmentLiveLaunchBootstrapTests
|
||||
"ignored.json",
|
||||
platform);
|
||||
|
||||
Assert.Equal(DevelopmentLiveBootstrapStatus.Skipped, result.Status);
|
||||
Assert.Equal("development-live-not-requested", result.Code);
|
||||
Assert.Equal(DevelopmentLiveBootstrapStatus.Rejected, result.Status);
|
||||
Assert.Equal("development-live-arguments-invalid", result.Code);
|
||||
Assert.False(result.IsLaunchAllowed);
|
||||
Assert.True(result.IsRequested);
|
||||
Assert.Equal(0, platform.ReadCount);
|
||||
Assert.Empty(platform.Environment);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReleaseBuild_SkipsExactArgumentWithoutReadingOrMutating()
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void GateALaunch_BypassesOrdinaryAuthorizationWithoutEnvironmentMutation(
|
||||
bool isDebugBuild)
|
||||
{
|
||||
var platform = FakePlatform.Valid();
|
||||
platform.Environment[
|
||||
PlayoutLaunchAuthorization.GateACapabilityEnvironmentVariable] =
|
||||
new string('A', 64);
|
||||
var originalEnvironment = platform.Environment.ToArray();
|
||||
|
||||
var result = DevelopmentLiveLaunchBootstrap.TryApply(
|
||||
DevelopmentLiveLaunchBootstrap.ExactLaunchArgument,
|
||||
isDebugBuild: false,
|
||||
"ignored.json",
|
||||
null,
|
||||
isDebugBuild,
|
||||
"must-not-be-read.json",
|
||||
platform);
|
||||
|
||||
Assert.Equal(DevelopmentLiveBootstrapStatus.Skipped, result.Status);
|
||||
Assert.Equal("development-live-debug-only", result.Code);
|
||||
Assert.Equal(DevelopmentLiveBootstrapStatus.GateABypassed, result.Status);
|
||||
Assert.Equal("development-live-gate-a-bypassed", result.Code);
|
||||
Assert.True(result.IsLaunchAllowed);
|
||||
Assert.False(result.IsRequested);
|
||||
Assert.Equal(0, platform.ReadCount);
|
||||
Assert.Empty(platform.Environment);
|
||||
Assert.Equal(originalEnvironment, platform.Environment);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DebugExactArgumentAndStrictFile_ApplyAllProcessGates()
|
||||
[Theory]
|
||||
[InlineData(null, true)]
|
||||
[InlineData("", true)]
|
||||
[InlineData("--development-live", true)]
|
||||
[InlineData(null, false)]
|
||||
[InlineData("", false)]
|
||||
[InlineData("--development-live", false)]
|
||||
public void NormalOrExactLaunchAndStrictFile_ApplyAllProcessGates(
|
||||
string? arguments,
|
||||
bool isDebugBuild)
|
||||
{
|
||||
var platform = FakePlatform.Valid();
|
||||
|
||||
var result = DevelopmentLiveLaunchBootstrap.TryApply(
|
||||
DevelopmentLiveLaunchBootstrap.ExactLaunchArgument,
|
||||
isDebugBuild: true,
|
||||
arguments,
|
||||
isDebugBuild,
|
||||
"authorization.json",
|
||||
platform);
|
||||
|
||||
@@ -188,6 +212,25 @@ public sealed class DevelopmentLiveLaunchBootstrapTests
|
||||
Assert.Empty(platform.Environment);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidAuthorizationFileRead_IsUnavailableAndDoesNotMutateEnvironment()
|
||||
{
|
||||
var platform = FakePlatform.Valid();
|
||||
platform.ReadException = new InvalidDataException("sensitive authorization bytes");
|
||||
|
||||
var result = DevelopmentLiveLaunchBootstrap.TryApply(
|
||||
null,
|
||||
isDebugBuild: false,
|
||||
"sensitive authorization path",
|
||||
platform);
|
||||
|
||||
Assert.Equal(DevelopmentLiveBootstrapStatus.Rejected, result.Status);
|
||||
Assert.Equal("development-live-authorization-unavailable", result.Code);
|
||||
Assert.False(result.IsLaunchAllowed);
|
||||
Assert.DoesNotContain("sensitive", result.Code, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Empty(platform.Environment);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnvironmentFailure_DisarmsEveryPreviousProcessValue()
|
||||
{
|
||||
@@ -196,7 +239,8 @@ public sealed class DevelopmentLiveLaunchBootstrapTests
|
||||
InstalledK3dInteropMetadata.ApprovedNativeSha256EnvironmentVariable] = "old-native";
|
||||
platform.Environment[
|
||||
InstalledK3dInteropMetadata.ApprovedSha256EnvironmentVariable] = "old-interop";
|
||||
platform.Environment[DevelopmentLiveLaunchBootstrap.ModeEnvironmentVariable] = "DryRun";
|
||||
platform.Environment[DevelopmentLiveLaunchBootstrap.ModeEnvironmentVariable] =
|
||||
"stale-mode";
|
||||
platform.Environment[PlayoutOptionsLoader.LiveAuthorizationEnvironmentVariable] =
|
||||
"old-authorization";
|
||||
platform.FailOnceOnSetName = DevelopmentLiveLaunchBootstrap.ModeEnvironmentVariable;
|
||||
|
||||
@@ -256,7 +256,7 @@ public sealed class PlayoutOptionsLoaderTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LoadDevelopmentLive_RejectsNonCanonicalJsonAndAllowlistExpansion()
|
||||
public void LoadDevelopmentLive_RejectsWrongModeNonCanonicalJsonAndAllowlistExpansion()
|
||||
{
|
||||
using var environment = ClearedEnvironment();
|
||||
var canonical = DevelopmentLiveBaseJson();
|
||||
@@ -265,12 +265,16 @@ public sealed class PlayoutOptionsLoaderTests
|
||||
string[] invalidConfigurations =
|
||||
[
|
||||
canonical.Replace(
|
||||
"\"mode\": \"Live\"",
|
||||
"\"mode\": \"DryRun\"",
|
||||
"\"Mode\": \"DryRun\"",
|
||||
StringComparison.Ordinal),
|
||||
canonical.Replace(
|
||||
"\"mode\": \"DryRun\"",
|
||||
"\"mode\": \"DryRun\", \"mode\": \"DryRun\"",
|
||||
"\"mode\": \"Live\"",
|
||||
"\"Mode\": \"Live\"",
|
||||
StringComparison.Ordinal),
|
||||
canonical.Replace(
|
||||
"\"mode\": \"Live\"",
|
||||
"\"mode\": \"Live\", \"mode\": \"Live\"",
|
||||
StringComparison.Ordinal),
|
||||
canonical.Replace(
|
||||
"\"port\": 31001",
|
||||
@@ -586,7 +590,7 @@ public sealed class PlayoutOptionsLoaderTests
|
||||
private static string DevelopmentLiveBaseJson() =>
|
||||
"""
|
||||
{
|
||||
"mode": "DryRun",
|
||||
"mode": "Live",
|
||||
"host": "127.0.0.1",
|
||||
"port": 31001,
|
||||
"tcpMode": 1,
|
||||
|
||||
Reference in New Issue
Block a user