Files
MBN_STOCK_WEBVIEW/tests/MBN_STOCK_WEBVIEW.LegacyWeb.Tests/LegacyDevelopmentLiveStartupContractTests.cs

254 lines
10 KiB
C#

using System.Text.Json;
namespace MBN_STOCK_WEBVIEW.LegacyWeb.Tests;
public sealed class LegacyDevelopmentLiveStartupContractTests
{
private const string ParityProjectGuid =
"{0F72B3C8-8A81-4D1E-8E57-0C0E9A9960C1}";
private const string PrototypeProjectGuid =
"{E6F5F1A0-D0FD-4E6B-A76D-1E8E3DAE8606}";
private const string ExactArgument = "--development-live";
private static readonly string RepositoryRoot = FindRepositoryRoot();
private static readonly string ParityRoot = Path.Combine(
RepositoryRoot,
"src",
"MBN_STOCK_WEBVIEW.LegacyParityApp");
[Fact]
public void VisualStudioProfilesPutDevelopmentLiveFirstAndKeepExplicitDryRun()
{
using var document = JsonDocument.Parse(File.ReadAllText(Path.Combine(
ParityRoot,
"Properties",
"launchSettings.json")));
var profiles = document.RootElement.GetProperty("profiles")
.EnumerateObject()
.ToArray();
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());
}
[Fact]
public void SharedSolutionLaunchStartsOnlyTheLegacyParityApp()
{
using var document = JsonDocument.Parse(File.ReadAllText(Path.Combine(
RepositoryRoot,
"MBN_STOCK_WEBVIEW.slnLaunch")));
var profile = Assert.Single(document.RootElement.EnumerateArray());
Assert.Equal("Legacy Parity App (VS F5)", profile.GetProperty("Name").GetString());
var project = Assert.Single(profile.GetProperty("Projects").EnumerateArray());
Assert.Equal(
"src\\MBN_STOCK_WEBVIEW.LegacyParityApp\\MBN_STOCK_WEBVIEW.LegacyParityApp.csproj",
project.GetProperty("Path").GetString());
Assert.Equal("Start", project.GetProperty("Action").GetString());
}
[Fact]
public void NormalDebugDeployTargetsParityInsteadOfThePrototype()
{
var solution = File.ReadAllText(Path.Combine(
RepositoryRoot,
"MBN_STOCK_WEBVIEW.sln"));
Assert.Contains(
$"{ParityProjectGuid}.Debug|x64.Deploy.0 = Debug|x64",
solution,
StringComparison.Ordinal);
Assert.DoesNotContain(
$"{PrototypeProjectGuid}.Debug|x64.Deploy.0 = Debug|x64",
solution,
StringComparison.Ordinal);
}
[Fact]
public void AppAppliesCompileTimeBuildGateBeforeConstructingMainWindow()
{
var app = File.ReadAllText(Path.Combine(ParityRoot, "App.xaml.cs"));
var bootstrap = app.IndexOf(
"DevelopmentLiveLaunchBootstrap.TryApply(",
StringComparison.Ordinal);
var constructWindow = app.IndexOf("_window = new MainWindow();", StringComparison.Ordinal);
Assert.True(bootstrap >= 0);
Assert.True(constructWindow > bootstrap);
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.Contains("args.Arguments", app, StringComparison.Ordinal);
Assert.Contains("Environment.GetCommandLineArgs()", app, StringComparison.Ordinal);
Assert.Contains("ResolveLaunchArguments(", app, StringComparison.Ordinal);
Assert.Contains(
"IsDevelopmentLiveLaunchRequested = string.Equals(",
app,
StringComparison.Ordinal);
Assert.Contains(
"IsDevelopmentLiveLaunch = developmentLive.IsApplied;",
app,
StringComparison.Ordinal);
}
[Fact]
public void AppliedDevelopmentLiveUsesOnlyProtectedStartupInputs()
{
var window = File.ReadAllText(Path.Combine(ParityRoot, "MainWindow.xaml.cs"));
var playout = File.ReadAllText(Path.Combine(
ParityRoot,
"MainWindow.Playout.cs"));
Assert.Contains(
"_isDevelopmentLiveLaunch = App.IsDevelopmentLiveLaunch;",
window,
StringComparison.Ordinal);
Assert.Contains(
"_isDevelopmentLiveLaunchRequested = App.IsDevelopmentLiveLaunchRequested;",
window,
StringComparison.Ordinal);
Assert.Contains(
"? LegacyRuntimeStockCutMenuLoader.ResolveFromBaseDirectory(",
window,
StringComparison.Ordinal);
Assert.Contains(
"? null\n : _appliedOperatorSettings.ResourceDirectory;",
window.ReplaceLineEndings("\n"),
StringComparison.Ordinal);
Assert.Contains(
"DatabaseRuntime.CreateDevelopmentLiveLocalOverride()",
window,
StringComparison.Ordinal);
Assert.Contains(
"? PlayoutOptionsLoader.LoadDevelopmentLive(",
playout,
StringComparison.Ordinal);
Assert.Contains(
"IsSourceOnlyBuild ||\n _isDevelopmentLiveLaunchRequested",
playout.ReplaceLineEndings("\n"),
StringComparison.Ordinal);
}
[Fact]
public void DevelopmentLiveDatabaseFailureForcesDryRunAndSkipsAutomaticConnect()
{
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 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,
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,
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" +
" ? PlayoutOptionsLoader.LoadDevelopmentLive(",
playout,
StringComparison.Ordinal);
Assert.Contains(
"_isDevelopmentLiveLaunchRequested ||\n" +
" _developmentLiveStartupBlocked",
playout,
StringComparison.Ordinal);
Assert.Contains(
"if (!_developmentLiveStartupBlocked)\n" +
" {\n" +
" await ConnectPlayoutAsync(_lifetimeCancellation.Token);",
window,
StringComparison.Ordinal);
}
[Fact]
public void TrackedExampleContainsOnlyNonUsableHashPlaceholders()
{
var example = File.ReadAllText(Path.Combine(
RepositoryRoot,
"Config",
"playout.development-live.example.json"));
using var document = JsonDocument.Parse(example);
var root = document.RootElement;
Assert.Equal(1, root.GetProperty("schemaVersion").GetInt32());
Assert.Equal("Live", root.GetProperty("mode").GetString());
Assert.StartsWith("<64-HEX-", root.GetProperty("nativeSha256").GetString());
Assert.StartsWith("<64-HEX-", root.GetProperty("interopSha256").GetString());
Assert.DoesNotContain(":\\", example, StringComparison.Ordinal);
}
[Fact]
public void RealDevelopmentAuthorizationFileIsIgnoredEverywhere()
{
var ignore = File.ReadAllText(Path.Combine(RepositoryRoot, ".gitignore"));
Assert.Contains("Config/playout.development-live.local.json", ignore,
StringComparison.Ordinal);
Assert.Contains("**/playout.development-live.local.json", ignore,
StringComparison.Ordinal);
}
private static string FindRepositoryRoot()
{
var current = new DirectoryInfo(AppContext.BaseDirectory);
while (current is not null)
{
if (File.Exists(Path.Combine(current.FullName, "MBN_STOCK_WEBVIEW.sln")))
{
return current.FullName;
}
current = current.Parent;
}
throw new DirectoryNotFoundException("Repository root was not found.");
}
}