2026-09-20 01:15:52 +02:00
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
|
|
|
|
namespace VoiceCat.Tests;
|
|
|
|
|
|
|
|
|
|
public class PublishServerScriptTests
|
|
|
|
|
{
|
2026-09-21 02:12:03 +02:00
|
|
|
[Theory]
|
|
|
|
|
[InlineData("clients/windows/publish-client.ps1")]
|
|
|
|
|
[InlineData("scripts/publish-server.ps1")]
|
|
|
|
|
public async Task PublishUsesRegeneratedIntermediateRuntimeLock(string relativePath)
|
|
|
|
|
{
|
|
|
|
|
string script = await File.ReadAllTextAsync(Path.Combine(FindRoot(), relativePath.Replace('/', Path.DirectorySeparatorChar)));
|
|
|
|
|
|
|
|
|
|
Assert.Contains("NuGetLockFilePath=obj/packages.publish.", script);
|
|
|
|
|
Assert.Contains("RestoreLockedMode=false", script);
|
|
|
|
|
Assert.DoesNotContain("NuGetLockFilePath=packages.publish.", script);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public async Task LicenseAuditIgnoresGeneratedBuildLocks()
|
|
|
|
|
{
|
|
|
|
|
string script = await File.ReadAllTextAsync(Path.Combine(FindRoot(), "scripts", "check-licenses.ps1"));
|
|
|
|
|
|
|
|
|
|
Assert.Contains("(?:bin|obj)", script);
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-21 02:53:27 +02:00
|
|
|
[Fact]
|
|
|
|
|
public async Task MacPublishPreservesAppEntitlementsAndReplacesBrokenWorkloadBundle()
|
|
|
|
|
{
|
|
|
|
|
string root = FindRoot();
|
|
|
|
|
string script = await File.ReadAllTextAsync(Path.Combine(root, "clients", "apple", "publish-macos.sh"));
|
|
|
|
|
string entitlements = await File.ReadAllTextAsync(Path.Combine(
|
|
|
|
|
root, "clients", "apple", "VoiceCat.Mac", "VoiceCat.Mac.entitlements"));
|
|
|
|
|
|
|
|
|
|
Assert.Contains("sign_nested_code", script);
|
|
|
|
|
Assert.Contains("--entitlements \"$entitlements\"", script);
|
|
|
|
|
Assert.Contains("install_verified_primary_bundle", script);
|
|
|
|
|
Assert.DoesNotContain("codesign --force --deep", script);
|
|
|
|
|
Assert.Contains("com.apple.security.cs.allow-jit", entitlements);
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-21 03:10:25 +02:00
|
|
|
[Fact]
|
|
|
|
|
public async Task IosDeviceBuildUsesAnIntermediateDeviceLockAndScopesKnownTrimWarnings()
|
|
|
|
|
{
|
|
|
|
|
string root = FindRoot();
|
|
|
|
|
string script = await File.ReadAllTextAsync(Path.Combine(root, "clients", "apple", "build-ios-device.sh"));
|
|
|
|
|
string project = await File.ReadAllTextAsync(Path.Combine(
|
|
|
|
|
root, "clients", "apple", "VoiceCat.iOS", "VoiceCat.iOS.csproj"));
|
|
|
|
|
|
|
|
|
|
Assert.Contains("NuGetLockFilePath=\"$device_lock\"", script);
|
|
|
|
|
Assert.Contains("RestoreLockedMode=false", script);
|
|
|
|
|
Assert.Contains("<WarningsNotAsErrors>$(WarningsNotAsErrors);IL2104</WarningsNotAsErrors>", project);
|
|
|
|
|
Assert.DoesNotContain("<TreatWarningsAsErrors>false</TreatWarningsAsErrors>", project);
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-20 01:15:52 +02:00
|
|
|
[Fact]
|
|
|
|
|
public async Task DefaultPublishTargetsWindowsAndLinuxWhileRuntimeCanSelectOne()
|
|
|
|
|
{
|
2026-09-21 00:11:01 +02:00
|
|
|
string script = Path.Combine(FindRoot(), "scripts", "publish-server.ps1");
|
2026-09-20 01:15:52 +02:00
|
|
|
|
|
|
|
|
string allTargets = await RunWhatIf(script);
|
|
|
|
|
Assert.Contains("win-x64", allTargets);
|
|
|
|
|
Assert.Contains("linux-x64", allTargets);
|
|
|
|
|
|
|
|
|
|
string linuxOnly = await RunWhatIf(script, "-Runtime", "linux-x64");
|
|
|
|
|
Assert.Contains("linux-x64", linuxOnly);
|
|
|
|
|
Assert.DoesNotContain("win-x64", linuxOnly);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static async Task<string> RunWhatIf(string script, params string[] arguments)
|
|
|
|
|
{
|
|
|
|
|
string powerShell = OperatingSystem.IsWindows() ? "powershell.exe" : "pwsh";
|
|
|
|
|
var start = new ProcessStartInfo(powerShell)
|
|
|
|
|
{
|
|
|
|
|
UseShellExecute = false,
|
|
|
|
|
CreateNoWindow = true,
|
|
|
|
|
RedirectStandardOutput = true,
|
|
|
|
|
RedirectStandardError = true,
|
|
|
|
|
};
|
|
|
|
|
foreach (string argument in new[] { "-NoProfile", "-NonInteractive", "-File", script, "-WhatIf" }.Concat(arguments))
|
|
|
|
|
start.ArgumentList.Add(argument);
|
|
|
|
|
|
|
|
|
|
using Process process = Process.Start(start) ?? throw new InvalidOperationException("Could not start PowerShell.");
|
|
|
|
|
Task<string> stdout = process.StandardOutput.ReadToEndAsync();
|
|
|
|
|
Task<string> stderr = process.StandardError.ReadToEndAsync();
|
|
|
|
|
await process.WaitForExitAsync();
|
|
|
|
|
string output = await stdout + await stderr;
|
|
|
|
|
Assert.True(process.ExitCode == 0, output);
|
|
|
|
|
return output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string FindRoot()
|
|
|
|
|
{
|
|
|
|
|
DirectoryInfo? directory = new(AppContext.BaseDirectory);
|
2026-09-21 00:11:01 +02:00
|
|
|
while (directory is not null && !File.Exists(Path.Combine(directory.FullName, "VoiceCat.slnx")))
|
2026-09-20 01:15:52 +02:00
|
|
|
directory = directory.Parent;
|
|
|
|
|
return directory?.FullName ?? throw new DirectoryNotFoundException("Repository root not found.");
|
|
|
|
|
}
|
|
|
|
|
}
|