mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 23:54:26 +08:00
feat.airapp剥离启动器
This commit is contained in:
@@ -96,17 +96,17 @@ public sealed class AirAppLauncherServiceTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateBrokerStartInfo_UsesAirAppBrokerCommandAndRequesterPid()
|
||||
public void CreateRuntimeStartInfo_UsesAirAppRuntimeAndRequesterPid()
|
||||
{
|
||||
var startInfo = AirAppLauncherService.CreateBrokerStartInfo(
|
||||
@"C:\Apps\LanMountainDesktop.Launcher.exe",
|
||||
var startInfo = AirAppLauncherService.CreateRuntimeStartInfo(
|
||||
@"C:\Apps\LanMountainDesktop.AirAppRuntime.exe",
|
||||
12345);
|
||||
|
||||
Assert.Equal(@"C:\Apps\LanMountainDesktop.Launcher.exe", startInfo.FileName);
|
||||
Assert.Equal(@"C:\Apps\LanMountainDesktop.AirAppRuntime.exe", startInfo.FileName);
|
||||
Assert.Equal(@"C:\Apps", startInfo.WorkingDirectory);
|
||||
Assert.False(startInfo.UseShellExecute);
|
||||
Assert.Equal(
|
||||
["air-app-broker", "--requester-pid", "12345"],
|
||||
["--requester-pid", "12345"],
|
||||
startInfo.ArgumentList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using LanMountainDesktop.Launcher.AirApp;
|
||||
using LanMountainDesktop.Launcher.Infrastructure;
|
||||
using Xunit;
|
||||
|
||||
namespace LanMountainDesktop.Tests;
|
||||
@@ -29,38 +27,14 @@ public sealed class AirAppProcessStarterRuntimeTests : IDisposable
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateStartInfo_UsesArchitectureMatchedDotnetHost_ForDllFallbackOnWindows()
|
||||
public void CreateStartInfo_UsesDotnetHost_ForDllFallback()
|
||||
{
|
||||
if (!OperatingSystem.IsWindows())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var programFiles = Path.Combine(_root, "ProgramFiles");
|
||||
var dotnetRoot = Path.Combine(programFiles, "dotnet");
|
||||
Directory.CreateDirectory(dotnetRoot);
|
||||
var dotnetHost = Path.Combine(dotnetRoot, "dotnet.exe");
|
||||
File.WriteAllText(dotnetHost, string.Empty);
|
||||
Directory.CreateDirectory(Path.Combine(
|
||||
dotnetRoot,
|
||||
"shared",
|
||||
DotNetRuntimeProbe.RequiredSharedFrameworkName,
|
||||
"10.0.5"));
|
||||
|
||||
var hostDll = Path.Combine(_root, "LanMountainDesktop.AirAppHost.dll");
|
||||
File.WriteAllText(hostDll, string.Empty);
|
||||
var options = new DotNetRuntimeProbeOptions
|
||||
{
|
||||
Architecture = DotNetRuntimeArchitecture.X64,
|
||||
ProgramFilesPath = programFiles,
|
||||
ProgramFilesX86Path = Path.Combine(_root, "ProgramFilesX86"),
|
||||
IncludeRegistry = false,
|
||||
IncludeDotNetCli = false
|
||||
};
|
||||
|
||||
var startInfo = AirAppProcessStarter.CreateStartInfo(hostDll, options);
|
||||
var startInfo = AirAppProcessStarter.CreateStartInfo(hostDll);
|
||||
|
||||
Assert.Equal(dotnetHost, startInfo.FileName);
|
||||
Assert.Contains("dotnet", Path.GetFileName(startInfo.FileName), StringComparison.OrdinalIgnoreCase);
|
||||
Assert.Equal(hostDll, startInfo.ArgumentList.Single());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
using System.Text.Json;
|
||||
using LanMountainDesktop.Shared.IPC;
|
||||
using Xunit;
|
||||
|
||||
namespace LanMountainDesktop.Tests;
|
||||
|
||||
public sealed class AirAppRuntimeDataRootResolverTests : IDisposable
|
||||
{
|
||||
private readonly string _root = Path.Combine(
|
||||
Path.GetTempPath(),
|
||||
"LanMountainDesktop.AirAppRuntimeDataRootResolverTests",
|
||||
Guid.NewGuid().ToString("N"));
|
||||
|
||||
[Fact]
|
||||
public void ResolveDataRoot_UsesPortableDataLocationConfig()
|
||||
{
|
||||
var portableRoot = Path.Combine(_root, "PortableData");
|
||||
WriteConfig(new
|
||||
{
|
||||
dataLocationMode = "Portable",
|
||||
portableDataPath = portableRoot
|
||||
});
|
||||
|
||||
var resolved = AirAppRuntimeDataRootResolver.ResolveDataRoot(_root);
|
||||
|
||||
Assert.Equal(Path.GetFullPath(portableRoot), resolved);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResolveDataRoot_UsesSystemDataLocationConfig()
|
||||
{
|
||||
var systemRoot = Path.Combine(_root, "SystemData");
|
||||
WriteConfig(new
|
||||
{
|
||||
dataLocationMode = "System",
|
||||
systemDataPath = systemRoot
|
||||
});
|
||||
|
||||
var resolved = AirAppRuntimeDataRootResolver.ResolveDataRoot(_root);
|
||||
|
||||
Assert.Equal(Path.GetFullPath(systemRoot), resolved);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResolveDataRoot_FallsBackToDefaultWhenConfigMissing()
|
||||
{
|
||||
var resolved = AirAppRuntimeDataRootResolver.ResolveDataRoot(_root);
|
||||
|
||||
Assert.Equal(
|
||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "LanMountainDesktop"),
|
||||
resolved);
|
||||
}
|
||||
|
||||
private void WriteConfig<T>(T config)
|
||||
{
|
||||
var configDirectory = Path.Combine(_root, ".Launcher");
|
||||
Directory.CreateDirectory(configDirectory);
|
||||
File.WriteAllText(
|
||||
Path.Combine(configDirectory, "data-location.config.json"),
|
||||
JsonSerializer.Serialize(config));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Directory.Exists(_root))
|
||||
{
|
||||
Directory.Delete(_root, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,17 @@
|
||||
using System.Diagnostics;
|
||||
using LanMountainDesktop.ComponentSystem;
|
||||
using LanMountainDesktop.Launcher;
|
||||
using LanMountainDesktop.Launcher.AirApp;
|
||||
using LanMountainDesktop.Launcher.Shell.EntryHandlers;
|
||||
using LanMountainDesktop.Shared.IPC.Abstractions.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace LanMountainDesktop.Tests;
|
||||
|
||||
public sealed class LauncherAirAppLifecycleServiceTests
|
||||
public sealed class AirAppRuntimeLifecycleServiceTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task OpenAsync_ReusesExistingInstanceForSameKey()
|
||||
{
|
||||
var starter = new TestAirAppProcessStarter(Process.GetCurrentProcess());
|
||||
var service = new LauncherAirAppLifecycleService(starter);
|
||||
var service = new AirAppLifecycleService(starter);
|
||||
var request = new AirAppOpenRequest(
|
||||
"whiteboard",
|
||||
BuiltInComponentIds.DesktopWhiteboard,
|
||||
@@ -36,7 +33,7 @@ public sealed class LauncherAirAppLifecycleServiceTests
|
||||
public async Task OpenAsync_ReusesGlobalClockSuiteAcrossClockComponents()
|
||||
{
|
||||
var starter = new TestAirAppProcessStarter(Process.GetCurrentProcess());
|
||||
var service = new LauncherAirAppLifecycleService(starter);
|
||||
var service = new AirAppLifecycleService(starter);
|
||||
|
||||
var first = await service.OpenAsync(new AirAppOpenRequest(
|
||||
"world-clock",
|
||||
@@ -62,7 +59,7 @@ public sealed class LauncherAirAppLifecycleServiceTests
|
||||
public async Task OpenAsync_PrunesExitedRegisteredInstanceBeforeRestart()
|
||||
{
|
||||
var starter = new TestAirAppProcessStarter(Process.GetCurrentProcess());
|
||||
var service = new LauncherAirAppLifecycleService(starter);
|
||||
var service = new AirAppLifecycleService(starter);
|
||||
var instanceKey = AirAppInstanceKey.Build(
|
||||
"whiteboard",
|
||||
BuiltInComponentIds.DesktopWhiteboard,
|
||||
@@ -92,7 +89,7 @@ public sealed class LauncherAirAppLifecycleServiceTests
|
||||
[Fact]
|
||||
public async Task HasLiveAirApps_ReturnsFalseAfterUnregisteringLastInstance()
|
||||
{
|
||||
var service = new LauncherAirAppLifecycleService(new TestAirAppProcessStarter(Process.GetCurrentProcess()));
|
||||
var service = new AirAppLifecycleService(new TestAirAppProcessStarter(Process.GetCurrentProcess()));
|
||||
var instanceKey = AirAppInstanceKey.Build("world-clock", BuiltInComponentIds.DesktopWorldClock, "clock-1");
|
||||
|
||||
_ = await service.RegisterAsync(new AirAppRegistrationRequest(
|
||||
@@ -112,26 +109,35 @@ public sealed class LauncherAirAppLifecycleServiceTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AirAppBrokerLifetime_KeepsAliveWhileRequesterIsAlive()
|
||||
public void RuntimeLifetime_KeepsAliveWhileRequesterIsAlive()
|
||||
{
|
||||
var service = new LauncherAirAppLifecycleService(new TestAirAppProcessStarter(null));
|
||||
var service = new AirAppLifecycleService(new TestAirAppProcessStarter(null));
|
||||
var lifetime = new AirAppRuntimeLifetime(
|
||||
new AirAppRuntimeOptions(null, null, 0, Environment.ProcessId),
|
||||
service);
|
||||
|
||||
Assert.True(AirAppBrokerEntryHandler.ShouldKeepAirAppBrokerAlive(Environment.ProcessId, service));
|
||||
Assert.True(lifetime.ShouldKeepAlive());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AirAppBrokerLifetime_StopsWhenRequesterExitedAndNoAirAppsRemain()
|
||||
public void RuntimeLifetime_StopsWhenNoProcessOrAirAppsRemain()
|
||||
{
|
||||
var service = new LauncherAirAppLifecycleService(new TestAirAppProcessStarter(null));
|
||||
var service = new AirAppLifecycleService(new TestAirAppProcessStarter(null));
|
||||
var lifetime = new AirAppRuntimeLifetime(
|
||||
new AirAppRuntimeOptions(null, null, int.MaxValue, int.MaxValue),
|
||||
service);
|
||||
|
||||
Assert.False(AirAppBrokerEntryHandler.ShouldKeepAirAppBrokerAlive(int.MaxValue, service));
|
||||
Assert.False(lifetime.ShouldKeepAlive());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AirAppBrokerLifetime_KeepsAliveWhileAirAppIsAlive()
|
||||
public async Task RuntimeLifetime_KeepsAliveWhileAirAppIsAlive()
|
||||
{
|
||||
var service = new LauncherAirAppLifecycleService(new TestAirAppProcessStarter(null));
|
||||
var service = new AirAppLifecycleService(new TestAirAppProcessStarter(null));
|
||||
var instanceKey = AirAppInstanceKey.Build("world-clock", BuiltInComponentIds.DesktopWorldClock, "clock-2");
|
||||
var lifetime = new AirAppRuntimeLifetime(
|
||||
new AirAppRuntimeOptions(null, null, int.MaxValue, int.MaxValue),
|
||||
service);
|
||||
|
||||
_ = await service.RegisterAsync(new AirAppRegistrationRequest(
|
||||
instanceKey,
|
||||
@@ -142,28 +148,23 @@ public sealed class LauncherAirAppLifecycleServiceTests
|
||||
BuiltInComponentIds.DesktopWorldClock,
|
||||
"clock-2"));
|
||||
|
||||
Assert.True(AirAppBrokerEntryHandler.ShouldKeepAirAppBrokerAlive(int.MaxValue, service));
|
||||
Assert.True(lifetime.ShouldKeepAlive());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CommandContext_RecognizesAirAppBrokerAsGuiCommandInDebugEnvironment()
|
||||
public async Task RuntimeControl_AttachesHostProcess()
|
||||
{
|
||||
var oldEnvironment = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
|
||||
try
|
||||
{
|
||||
Environment.SetEnvironmentVariable("DOTNET_ENVIRONMENT", "Development");
|
||||
var service = new AirAppLifecycleService(new TestAirAppProcessStarter(null));
|
||||
var lifetime = new AirAppRuntimeLifetime(
|
||||
new AirAppRuntimeOptions(null, null, int.MaxValue, int.MaxValue),
|
||||
service);
|
||||
var control = new AirAppRuntimeControlService(lifetime);
|
||||
|
||||
var context = CommandContext.FromArgs(["air-app-broker", "--requester-pid", "42"]);
|
||||
var result = await control.AttachHostAsync(Environment.ProcessId);
|
||||
|
||||
Assert.True(context.IsGuiCommand);
|
||||
Assert.True(context.IsAirAppBrokerCommand);
|
||||
Assert.True(context.IsDebugMode);
|
||||
Assert.Equal(42, context.GetIntOption("requester-pid", 0));
|
||||
}
|
||||
finally
|
||||
{
|
||||
Environment.SetEnvironmentVariable("DOTNET_ENVIRONMENT", oldEnvironment);
|
||||
}
|
||||
Assert.True(result.Accepted);
|
||||
Assert.Equal(Environment.ProcessId, result.Status.HostProcessId);
|
||||
Assert.True(result.Status.HostProcessAlive);
|
||||
}
|
||||
|
||||
private sealed class TestAirAppProcessStarter : IAirAppProcessStarter
|
||||
@@ -9,7 +9,6 @@ public sealed class CommandContextTests
|
||||
{
|
||||
{ [], "normal" },
|
||||
{ ["preview-oobe"], "debug-preview" },
|
||||
{ ["apply-update"], "normal" },
|
||||
{ ["--source", "plugin.lmdp", "--plugins-dir", "plugins", "--result", "result.json"], "plugin-install" },
|
||||
{ ["launch", "--launch-source", "postinstall"], "postinstall" }
|
||||
};
|
||||
@@ -22,4 +21,12 @@ public sealed class CommandContextTests
|
||||
|
||||
Assert.Equal(expectedLaunchSource, context.LaunchSource);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FromArgs_DoesNotTreatAirAppBrokerAsLauncherGuiCommand()
|
||||
{
|
||||
var context = CommandContext.FromArgs(["air-app-broker", "--requester-pid", "42"]);
|
||||
|
||||
Assert.False(context.IsGuiCommand);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
global using LanMountainDesktop.Launcher.AirApp;
|
||||
global using LanMountainDesktop.AirAppRuntime;
|
||||
global using LanMountainDesktop.Launcher.Deployment;
|
||||
global using LanMountainDesktop.Launcher.Infrastructure;
|
||||
global using LanMountainDesktop.Launcher.Ipc;
|
||||
|
||||
@@ -11,7 +11,6 @@ public sealed class HostActivationPolicyTests
|
||||
[Theory]
|
||||
[InlineData("launch", "normal", true)]
|
||||
[InlineData("launch", "restart", false)]
|
||||
[InlineData("apply-update", "normal", false)]
|
||||
public void ShouldProbeExistingHostBeforeLaunch_RespectsLaunchSource(
|
||||
string command,
|
||||
string launchSource,
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LanMountainDesktop\LanMountainDesktop.csproj" />
|
||||
<ProjectReference Include="..\LanMountainDesktop.AirAppRuntime\LanMountainDesktop.AirAppRuntime.csproj" />
|
||||
<ProjectReference Include="..\LanMountainDesktop.Launcher\LanMountainDesktop.Launcher.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -47,6 +47,95 @@ public sealed class LauncherArchitectureTests
|
||||
Assert.Empty(offenders);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LauncherProject_DoesNotOwnUpdateApplyOrRollback()
|
||||
{
|
||||
var launcherFiles = Directory
|
||||
.EnumerateFiles(LauncherProjectRoot, "*.cs", SearchOption.AllDirectories)
|
||||
.Where(file => !file.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}", StringComparison.OrdinalIgnoreCase))
|
||||
.Where(file => !file.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}", StringComparison.OrdinalIgnoreCase))
|
||||
.ToArray();
|
||||
|
||||
var forbiddenTokens = new[]
|
||||
{
|
||||
"LauncherUpdateCommandExecutor",
|
||||
"PlondsUpdateApplier",
|
||||
"UpdateRollbackGateway",
|
||||
"UpdateInstallGateway",
|
||||
"LanMountainDesktop.Services.Update",
|
||||
"apply-update",
|
||||
"rollback --app-root"
|
||||
};
|
||||
|
||||
var offenders = launcherFiles
|
||||
.SelectMany(file => forbiddenTokens
|
||||
.Where(token => File.ReadAllText(file).Contains(token, StringComparison.Ordinal))
|
||||
.Select(token => $"{RelativeToRepo(file)} contains {token}"))
|
||||
.ToArray();
|
||||
|
||||
Assert.Empty(offenders);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LauncherProjectFile_DoesNotSourceLinkHostUpdateImplementation()
|
||||
{
|
||||
var project = File.ReadAllText(Path.Combine(LauncherProjectRoot, "LanMountainDesktop.Launcher.csproj"));
|
||||
|
||||
Assert.DoesNotContain(@"..\LanMountainDesktop\Services\Update", project, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("PlondsUpdateApplier", project, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("UpdateRollbackGateway", project, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("UpdateInstallGateway", project, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HostUpdateFlow_DoesNotDelegateApplyOrRollbackToLauncher()
|
||||
{
|
||||
var guardedFiles = new[]
|
||||
{
|
||||
Path.Combine(RepoRoot, "LanMountainDesktop", "Services", "Update", "UpdateInstallGateway.cs"),
|
||||
Path.Combine(RepoRoot, "LanMountainDesktop", "Services", "Update", "UpdateOrchestrator.cs")
|
||||
};
|
||||
|
||||
var forbiddenTokens = new[]
|
||||
{
|
||||
"LauncherPathResolver",
|
||||
"ResolveLauncherExecutablePath",
|
||||
"apply-update",
|
||||
"rollback --app-root",
|
||||
"Launched Launcher"
|
||||
};
|
||||
|
||||
var offenders = guardedFiles
|
||||
.SelectMany(file => forbiddenTokens
|
||||
.Where(token => File.ReadAllText(file).Contains(token, StringComparison.Ordinal))
|
||||
.Select(token => $"{RelativeToRepo(file)} contains {token}"))
|
||||
.ToArray();
|
||||
|
||||
Assert.Empty(offenders);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HostUpdateFlow_OwnsDeltaApplyAndRollbackExecution()
|
||||
{
|
||||
var installGateway = File.ReadAllText(Path.Combine(
|
||||
RepoRoot,
|
||||
"LanMountainDesktop",
|
||||
"Services",
|
||||
"Update",
|
||||
"UpdateInstallGateway.cs"));
|
||||
var orchestrator = File.ReadAllText(Path.Combine(
|
||||
RepoRoot,
|
||||
"LanMountainDesktop",
|
||||
"Services",
|
||||
"Update",
|
||||
"UpdateOrchestrator.cs"));
|
||||
|
||||
Assert.Contains("new PlondsUpdateApplier", installGateway, StringComparison.Ordinal);
|
||||
Assert.Contains("DeploymentLockService.ClearLock", installGateway, StringComparison.Ordinal);
|
||||
Assert.Contains("new UpdateRollbackGateway().RollbackLatest", orchestrator, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("LanMountainDesktop.Launcher", orchestrator, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LauncherCompositionRootStaysThin()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
global using LanMountainDesktop.Launcher.AirApp;
|
||||
global using LanMountainDesktop.AirAppRuntime;
|
||||
global using LanMountainDesktop.Launcher.Deployment;
|
||||
global using LanMountainDesktop.Launcher.Infrastructure;
|
||||
global using LanMountainDesktop.Launcher.Ipc;
|
||||
|
||||
59
LanMountainDesktop.Tests/LauncherUpdateCommandTests.cs
Normal file
59
LanMountainDesktop.Tests/LauncherUpdateCommandTests.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using System.Text.Json;
|
||||
using LanMountainDesktop.Launcher;
|
||||
using LanMountainDesktop.Launcher.Infrastructure;
|
||||
using LanMountainDesktop.Launcher.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace LanMountainDesktop.Tests;
|
||||
|
||||
public sealed class LauncherUpdateCommandTests : IDisposable
|
||||
{
|
||||
private readonly string _root = Path.Combine(
|
||||
Path.GetTempPath(),
|
||||
"LanMountainDesktop.LauncherUpdateCommandTests",
|
||||
Guid.NewGuid().ToString("N"));
|
||||
|
||||
[Fact]
|
||||
public async Task ApplyUpdateCommand_IsNotHandledByLauncherCli()
|
||||
{
|
||||
Directory.CreateDirectory(_root);
|
||||
var resultPath = Path.Combine(_root, "result.json");
|
||||
var context = CommandContext.FromArgs(["apply-update", "--app-root", _root, "--result", resultPath]);
|
||||
|
||||
var exitCode = await Commands.RunCliCommandAsync(context);
|
||||
var result = ReadResult(resultPath);
|
||||
|
||||
Assert.Equal(1, exitCode);
|
||||
Assert.Equal("command", result.Stage);
|
||||
Assert.Equal("unsupported_command", result.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RollbackCommand_IsNotHandledByLauncherCli()
|
||||
{
|
||||
Directory.CreateDirectory(_root);
|
||||
var resultPath = Path.Combine(_root, "result.json");
|
||||
var context = CommandContext.FromArgs(["rollback", "--app-root", _root, "--result", resultPath]);
|
||||
|
||||
var exitCode = await Commands.RunCliCommandAsync(context);
|
||||
var result = ReadResult(resultPath);
|
||||
|
||||
Assert.Equal(1, exitCode);
|
||||
Assert.Equal("command", result.Stage);
|
||||
Assert.Equal("unsupported_command", result.Code);
|
||||
}
|
||||
|
||||
private static LauncherResult ReadResult(string path)
|
||||
{
|
||||
var result = JsonSerializer.Deserialize<LauncherResult>(File.ReadAllText(path));
|
||||
return result ?? throw new InvalidOperationException("Launcher result was not written.");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Directory.Exists(_root))
|
||||
{
|
||||
Directory.Delete(_root, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,10 +10,12 @@ public sealed class PackagingRuntimePolicyTests
|
||||
var script = ReadRepositoryFile("LanMountainDesktop", "scripts", "package.ps1");
|
||||
|
||||
Assert.Contains("Publish-LauncherPayload", script);
|
||||
Assert.Contains("Publish-AirAppRuntimePayload", script);
|
||||
Assert.Contains("\"app-$Version\"", script);
|
||||
Assert.Contains("Publish-MainAppFrameworkDependentPayload", script);
|
||||
Assert.Contains("\"--self-contained\", \"false\"", script);
|
||||
Assert.Contains("\"-p:SelfContained=false\"", script);
|
||||
Assert.Contains("\"-p:PublishAot=false\"", script);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -28,12 +30,13 @@ public sealed class PackagingRuntimePolicyTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WindowsPayloadGuard_RequiresLauncherMainAndAirAppHost()
|
||||
public void WindowsPayloadGuard_RequiresLauncherRuntimeMainAndAirAppHost()
|
||||
{
|
||||
var script = ReadRepositoryFile("LanMountainDesktop", "scripts", "Optimize-PublishPayload.ps1");
|
||||
|
||||
Assert.Contains("Assert-WindowsPayloadContainsRequiredHosts", script);
|
||||
Assert.Contains("LanMountainDesktop.Launcher.exe", script);
|
||||
Assert.Contains("LanMountainDesktop.AirAppRuntime.exe", script);
|
||||
Assert.Contains("LanMountainDesktop.exe", script);
|
||||
Assert.Contains("LanMountainDesktop.AirAppHost.exe", script);
|
||||
}
|
||||
@@ -44,9 +47,21 @@ public sealed class PackagingRuntimePolicyTests
|
||||
var workflow = ReadRepositoryFile(".github", "workflows", "release.yml");
|
||||
|
||||
Assert.Contains("Verify Windows app host payload", workflow);
|
||||
Assert.Contains("LanMountainDesktop.AirAppRuntime.exe", workflow);
|
||||
Assert.Contains("LanMountainDesktop.AirAppHost.exe", workflow);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AirAppRuntimeProject_IsFrameworkDependentJit()
|
||||
{
|
||||
var project = ReadRepositoryFile("LanMountainDesktop.AirAppRuntime", "LanMountainDesktop.AirAppRuntime.csproj");
|
||||
|
||||
Assert.Contains("<PublishAot>false</PublishAot>", project);
|
||||
Assert.Contains("<SelfContained>false</SelfContained>", project);
|
||||
Assert.Contains("<PublishTrimmed>false</PublishTrimmed>", project);
|
||||
Assert.Contains("<PublishReadyToRun>false</PublishReadyToRun>", project);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Installer_DownloadsArchitectureSpecificDesktopRuntime()
|
||||
{
|
||||
|
||||
@@ -130,7 +130,7 @@ public sealed class WindowLayerIsolationTests
|
||||
{
|
||||
var optionsSource = ReadRepositoryFile("LanMountainDesktop.AirAppHost", "AirAppLaunchOptions.cs");
|
||||
var programSource = ReadRepositoryFile("LanMountainDesktop.AirAppHost", "Program.cs");
|
||||
var starterSource = ReadRepositoryFile("LanMountainDesktop.Launcher", "AirApp", "IAirAppProcessStarter.cs");
|
||||
var starterSource = ReadRepositoryFile("LanMountainDesktop.AirAppRuntime", "IAirAppProcessStarter.cs");
|
||||
var dataPathSource = ReadRepositoryFile("LanMountainDesktop", "Services", "AppDataPathProvider.cs");
|
||||
|
||||
Assert.Contains("DataRoot", optionsSource);
|
||||
|
||||
Reference in New Issue
Block a user