feat: make LegacyParityApp playout live-only
This commit is contained in:
@@ -17,29 +17,25 @@ public sealed class LegacyDevelopmentLiveStartupContractTests
|
||||
"MBN_STOCK_WEBVIEW.LegacyParityApp");
|
||||
|
||||
[Fact]
|
||||
public void VisualStudioProfilesPutDevelopmentLiveFirstAndKeepExplicitDryRun()
|
||||
public void VisualStudioExposesOneLivePackageProfileWithoutDryRun()
|
||||
{
|
||||
using var document = JsonDocument.Parse(File.ReadAllText(Path.Combine(
|
||||
ParityRoot,
|
||||
"Properties",
|
||||
"launchSettings.json")));
|
||||
var profiles = document.RootElement.GetProperty("profiles")
|
||||
.EnumerateObject()
|
||||
.ToArray();
|
||||
var profile = Assert.Single(document.RootElement.GetProperty("profiles")
|
||||
.EnumerateObject());
|
||||
|
||||
Assert.Equal(2, profiles.Length);
|
||||
Assert.Equal(
|
||||
"MBN_STOCK_WEBVIEW.LegacyParityApp - Development Live (Package)",
|
||||
profiles[0].Name);
|
||||
Assert.Equal("MsixPackage", profiles[0].Value.GetProperty("commandName").GetString());
|
||||
Assert.Equal(ExactArgument,
|
||||
profiles[0].Value.GetProperty("commandLineArgs").GetString());
|
||||
Assert.Equal(
|
||||
"MBN_STOCK_WEBVIEW.LegacyParityApp - Explicit DryRun (Package)",
|
||||
profiles[1].Name);
|
||||
Assert.Equal("MsixPackage", profiles[1].Value.GetProperty("commandName").GetString());
|
||||
Assert.Equal(string.Empty,
|
||||
profiles[1].Value.GetProperty("commandLineArgs").GetString());
|
||||
Assert.Contains("Live", profile.Name, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("DryRun", profile.Name, StringComparison.Ordinal);
|
||||
Assert.Equal("MsixPackage", profile.Value.GetProperty("commandName").GetString());
|
||||
var arguments = profile.Value.TryGetProperty("commandLineArgs", out var value)
|
||||
? value.GetString()
|
||||
: null;
|
||||
Assert.True(
|
||||
string.IsNullOrEmpty(arguments) ||
|
||||
string.Equals(arguments, ExactArgument, StringComparison.Ordinal),
|
||||
"The sole Live package profile may use only the normal launch or exact Live argument.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -75,7 +71,7 @@ public sealed class LegacyDevelopmentLiveStartupContractTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AppAppliesCompileTimeBuildGateBeforeConstructingMainWindow()
|
||||
public void AppAppliesRuntimeGateBeforeConstructingAnyRuntimeWindow()
|
||||
{
|
||||
var app = File.ReadAllText(Path.Combine(ParityRoot, "App.xaml.cs"));
|
||||
var bootstrap = app.IndexOf(
|
||||
@@ -87,35 +83,37 @@ public sealed class LegacyDevelopmentLiveStartupContractTests
|
||||
var constructMainWindow = app.IndexOf(
|
||||
"new MainWindow();",
|
||||
StringComparison.Ordinal);
|
||||
var sourceOnlyDirective = app.IndexOf(
|
||||
"#if SOURCE_ONLY_RUNTIME",
|
||||
StringComparison.Ordinal);
|
||||
var fullRuntimeDirective = app.IndexOf(
|
||||
"#else",
|
||||
constructSetupWindow,
|
||||
StringComparison.Ordinal);
|
||||
var runtimeEndDirective = app.IndexOf(
|
||||
"#endif",
|
||||
constructMainWindow,
|
||||
StringComparison.Ordinal);
|
||||
|
||||
Assert.True(bootstrap >= 0);
|
||||
Assert.True(constructSetupWindow > bootstrap);
|
||||
Assert.True(constructMainWindow > constructSetupWindow);
|
||||
Assert.Contains("#if DEBUG", app, StringComparison.Ordinal);
|
||||
Assert.Contains("const bool isDebugBuild = true;", app, StringComparison.Ordinal);
|
||||
Assert.Contains("const bool isDebugBuild = false;", app, StringComparison.Ordinal);
|
||||
Assert.Contains("#if SOURCE_ONLY_RUNTIME", app, StringComparison.Ordinal);
|
||||
Assert.Contains("const bool isSourceOnlyBuild = true;", app,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("const bool isSourceOnlyBuild = false;", app,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("isSourceOnlyBuild", app, StringComparison.Ordinal);
|
||||
Assert.Contains("? null", app, StringComparison.Ordinal);
|
||||
Assert.True(sourceOnlyDirective >= 0);
|
||||
Assert.True(constructSetupWindow > sourceOnlyDirective);
|
||||
Assert.True(fullRuntimeDirective > constructSetupWindow);
|
||||
Assert.True(bootstrap > fullRuntimeDirective);
|
||||
Assert.True(constructMainWindow > bootstrap);
|
||||
Assert.True(runtimeEndDirective > constructMainWindow);
|
||||
Assert.Contains("args.Arguments", app, StringComparison.Ordinal);
|
||||
Assert.Contains("Environment.GetCommandLineArgs()", app, StringComparison.Ordinal);
|
||||
Assert.Contains("ResolveLaunchArguments(", app, StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"IsDevelopmentLiveLaunchRequested = string.Equals(",
|
||||
"IsDevelopmentLiveLaunchRequested = developmentLive.IsRequested;",
|
||||
app,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"IsDevelopmentLiveLaunch = developmentLive.IsApplied;",
|
||||
app,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"_window = showFirstRunSetup",
|
||||
app,
|
||||
StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("#if DEBUG", app, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -162,14 +160,15 @@ public sealed class LegacyDevelopmentLiveStartupContractTests
|
||||
" _appliedOperatorSettings.SceneDirectory",
|
||||
playout.ReplaceLineEndings("\n"),
|
||||
StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("forceSafeDryRun", playout, StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"IsSourceOnlyBuild ||\n _isDevelopmentLiveLaunchRequested",
|
||||
playout.ReplaceLineEndings("\n"),
|
||||
"if (_playoutOptions.Mode != PlayoutMode.Live)",
|
||||
playout,
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DevelopmentLiveDatabaseFailureForcesDryRunAndSkipsAutomaticConnect()
|
||||
public void DatabaseFailureDoesNotDowngradeOrBlockValidatedLiveEngine()
|
||||
{
|
||||
var window = File.ReadAllText(Path.Combine(ParityRoot, "MainWindow.xaml.cs"))
|
||||
.ReplaceLineEndings("\n");
|
||||
@@ -178,49 +177,87 @@ public sealed class LegacyDevelopmentLiveStartupContractTests
|
||||
"MainWindow.Playout.cs"))
|
||||
.ReplaceLineEndings("\n");
|
||||
|
||||
var blockAssignment = window.IndexOf(
|
||||
"_developmentLiveStartupBlocked = true;",
|
||||
StringComparison.Ordinal);
|
||||
var successAssignment = window.IndexOf(
|
||||
"databaseInitializationSucceeded = true;",
|
||||
StringComparison.Ordinal);
|
||||
var runtimeReset = window.IndexOf(
|
||||
"_databaseRuntime = null;",
|
||||
successAssignment,
|
||||
StringComparison.Ordinal);
|
||||
var pagePlanReset = window.IndexOf(
|
||||
"fixedPagePlanProvider = null;",
|
||||
successAssignment,
|
||||
runtimeReset,
|
||||
StringComparison.Ordinal);
|
||||
var databaseFailureEnd = window.IndexOf(
|
||||
"_industryWorkflow = new LegacyIndustrySelectionWorkflow(",
|
||||
pagePlanReset,
|
||||
StringComparison.Ordinal);
|
||||
var playoutInitialization = window.IndexOf(
|
||||
"InitializePlayoutRuntime();",
|
||||
StringComparison.Ordinal);
|
||||
Assert.True(successAssignment >= 0);
|
||||
Assert.True(runtimeReset > successAssignment);
|
||||
Assert.True(pagePlanReset > successAssignment);
|
||||
Assert.True(blockAssignment > runtimeReset);
|
||||
Assert.True(playoutInitialization > blockAssignment);
|
||||
Assert.Contains(
|
||||
"var databaseInitializationSucceeded = false;",
|
||||
window,
|
||||
|
||||
Assert.True(runtimeReset >= 0);
|
||||
Assert.True(pagePlanReset > runtimeReset);
|
||||
Assert.True(databaseFailureEnd > pagePlanReset);
|
||||
Assert.True(playoutInitialization > databaseFailureEnd);
|
||||
Assert.DoesNotContain(
|
||||
"_developmentLiveStartupBlocked = true;",
|
||||
window[runtimeReset..databaseFailureEnd],
|
||||
StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("databaseInitializationSucceeded", window,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"if (_isDevelopmentLiveLaunch && !databaseInitializationSucceeded)\n" +
|
||||
" {\n" +
|
||||
" // Development Live is one fail-closed startup transaction.",
|
||||
window,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"_isDevelopmentLiveLaunch &&\n" +
|
||||
" !_developmentLiveStartupBlocked\n" +
|
||||
"_isDevelopmentLiveLaunch\n" +
|
||||
" ? PlayoutOptionsLoader.LoadDevelopmentLive(",
|
||||
playout,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"_isDevelopmentLiveLaunchRequested ||\n" +
|
||||
" _developmentLiveStartupBlocked",
|
||||
"if (_playoutOptions.Mode != PlayoutMode.Live)",
|
||||
playout,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"_playoutEngine = PlayoutEngineFactory.Create(",
|
||||
playout,
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BootstrapOrPlayoutInvariantFailureBlocksEngineAndAutomaticConnect()
|
||||
{
|
||||
var window = File.ReadAllText(Path.Combine(ParityRoot, "MainWindow.xaml.cs"))
|
||||
.ReplaceLineEndings("\n");
|
||||
var playout = File.ReadAllText(Path.Combine(
|
||||
ParityRoot,
|
||||
"MainWindow.Playout.cs"))
|
||||
.ReplaceLineEndings("\n");
|
||||
|
||||
var initialBlock = window.IndexOf(
|
||||
"_developmentLiveStartupBlocked =\n" +
|
||||
" _isDevelopmentLiveLaunchRequested &&\n" +
|
||||
" !_isDevelopmentLiveLaunch;",
|
||||
StringComparison.Ordinal);
|
||||
var earlyBlock = playout.IndexOf(
|
||||
"if (_developmentLiveStartupBlocked)",
|
||||
StringComparison.Ordinal);
|
||||
var earlyReturn = playout.IndexOf("return;", earlyBlock, StringComparison.Ordinal);
|
||||
var loadLive = playout.IndexOf(
|
||||
"PlayoutOptionsLoader.LoadDevelopmentLive(",
|
||||
StringComparison.Ordinal);
|
||||
var requireLive = playout.IndexOf(
|
||||
"if (_playoutOptions.Mode != PlayoutMode.Live)",
|
||||
StringComparison.Ordinal);
|
||||
var createEngine = playout.IndexOf(
|
||||
"_playoutEngine = PlayoutEngineFactory.Create(",
|
||||
StringComparison.Ordinal);
|
||||
var blockOnInitializationFailure = playout.IndexOf(
|
||||
"_developmentLiveStartupBlocked = true;",
|
||||
createEngine,
|
||||
StringComparison.Ordinal);
|
||||
|
||||
Assert.True(initialBlock >= 0);
|
||||
Assert.True(earlyBlock >= 0);
|
||||
Assert.True(earlyReturn > earlyBlock);
|
||||
Assert.True(loadLive > earlyReturn);
|
||||
Assert.True(requireLive > loadLive);
|
||||
Assert.True(createEngine > requireLive);
|
||||
Assert.True(blockOnInitializationFailure > createEngine);
|
||||
Assert.DoesNotContain("forceSafeDryRun", playout, StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"if (!_developmentLiveStartupBlocked)\n" +
|
||||
" {\n" +
|
||||
|
||||
@@ -16,17 +16,28 @@ public sealed class LegacyFirstRunSetupNativeContractTests
|
||||
var app = File.ReadAllText(Path.Combine(AppRoot, "App.xaml.cs"))
|
||||
.ReplaceLineEndings("\n");
|
||||
|
||||
Assert.Contains(
|
||||
"var showFirstRunSetup = isSourceOnlyBuild && isDebugBuild;\n" +
|
||||
" _window = showFirstRunSetup\n" +
|
||||
" ? new FirstRunSetupWindow()\n" +
|
||||
" : new MainWindow();",
|
||||
app,
|
||||
var sourceOnlyStart = app.IndexOf("#if SOURCE_ONLY_RUNTIME",
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"var launchArguments = isSourceOnlyBuild\n" +
|
||||
" ? null",
|
||||
app,
|
||||
var fullRuntimeStart = app.IndexOf("#else", sourceOnlyStart,
|
||||
StringComparison.Ordinal);
|
||||
var runtimeEnd = app.IndexOf("#endif", fullRuntimeStart,
|
||||
StringComparison.Ordinal);
|
||||
Assert.True(sourceOnlyStart >= 0);
|
||||
Assert.True(fullRuntimeStart > sourceOnlyStart);
|
||||
Assert.True(runtimeEnd > fullRuntimeStart);
|
||||
|
||||
var sourceOnly = app[sourceOnlyStart..fullRuntimeStart];
|
||||
var fullRuntime = app[fullRuntimeStart..runtimeEnd];
|
||||
Assert.Contains("new FirstRunSetupWindow()", sourceOnly, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("new MainWindow()", sourceOnly, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain(
|
||||
"DevelopmentLiveLaunchBootstrap.TryApply(",
|
||||
sourceOnly,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("DevelopmentLiveLaunchBootstrap.TryApply(", fullRuntime,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("new MainWindow()", fullRuntime, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("new FirstRunSetupWindow()", fullRuntime,
|
||||
StringComparison.Ordinal);
|
||||
Assert.DoesNotContain(
|
||||
"new FirstRunSetupWindow(App.IsDevelopmentLiveLaunch",
|
||||
|
||||
@@ -104,9 +104,11 @@ public sealed class LegacyOperatorSettingsNativeContractTests
|
||||
Playout,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"operatorBackgroundDirectory: _appliedOperatorSettings.BackgroundDirectory",
|
||||
"operatorBackgroundDirectory:",
|
||||
Playout,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("_appliedOperatorSettings.BackgroundDirectory", Playout,
|
||||
StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("InitializePlayoutRuntime();", Settings, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("CreateLegacyExecutableDefault(", Settings,
|
||||
StringComparison.Ordinal);
|
||||
|
||||
@@ -442,7 +442,9 @@ public sealed class LegacyRuntimeAssetDeploymentContractTests
|
||||
"src",
|
||||
"MBN_STOCK_WEBVIEW.LegacyParityApp",
|
||||
"MainWindow.Playout.cs"));
|
||||
Assert.Contains("forceSafeDryRun: IsSourceOnlyBuild", playout,
|
||||
Assert.DoesNotContain("forceSafeDryRun", playout,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("if (_playoutOptions.Mode != PlayoutMode.Live)", playout,
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
@@ -540,7 +542,8 @@ public sealed class LegacyRuntimeAssetDeploymentContractTests
|
||||
"[ValidateSet('127.0.0.1', '::1')]",
|
||||
initializer,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("mode = 'DryRun'", initializer, StringComparison.Ordinal);
|
||||
Assert.Contains("mode = 'Live'", initializer, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("mode = 'DryRun'", initializer, StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"trustedLiveOutputEnabled = $true",
|
||||
initializer,
|
||||
|
||||
@@ -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