Files
YMhut-box-C-/src/YMhut.Box.Tests/InstallLayoutPathsTests.cs
T
QWQLwToo 7ecc6a8923
build-winui / winui (push) Has been cancelled
Add WinUI and core source
2026-06-26 13:27:13 +08:00

267 lines
9.8 KiB
C#

using Microsoft.VisualStudio.TestTools.UnitTesting;
using YMhut.Box.Core.App;
namespace YMhut.Box.Tests;
[TestClass]
[DoNotParallelize]
public sealed class InstallLayoutPathsTests
{
[TestMethod]
public void ResolveInstallRootPrefersCurrentInstallRootEnvironment()
{
using var workspace = TestWorkspace.Create("ymhut-install-root-tests");
var installRoot = workspace.CreateDirectory("install");
var baseRoot = workspace.CreateDirectory("runtime");
using var environment = EnvironmentScope.Capture(
InstallLayoutPaths.InstallRootEnvironmentVariable,
InstallLayoutPaths.ArchivedLayoutEnvironmentVariable);
environment.Set(InstallLayoutPaths.InstallRootEnvironmentVariable, installRoot);
environment.Set(InstallLayoutPaths.ArchivedLayoutEnvironmentVariable, null);
Assert.AreEqual(installRoot, InstallLayoutPaths.ResolveInstallRoot(baseRoot));
Assert.AreEqual(installRoot, InstallLayoutPaths.CandidateRoots(baseRoot).First());
}
[TestMethod]
public void ResolveInstallRootIgnoresLegacyArchivedLayoutForHealth()
{
using var workspace = TestWorkspace.Create("ymhut-archived-layout-tests");
var archivedRoot = workspace.CreateDirectory("archived");
var baseRoot = workspace.CreateDirectory("runtime");
workspace.CreateFile(["runtime", "YMhutBox.exe"], string.Empty);
using var environment = EnvironmentScope.Capture(
InstallLayoutPaths.InstallRootEnvironmentVariable,
InstallLayoutPaths.ArchivedLayoutEnvironmentVariable);
environment.Set(InstallLayoutPaths.InstallRootEnvironmentVariable, null);
environment.Set(InstallLayoutPaths.ArchivedLayoutEnvironmentVariable, archivedRoot);
Assert.AreEqual(baseRoot, InstallLayoutPaths.ResolveInstallRoot(baseRoot));
Assert.IsFalse(InstallLayoutPaths.CandidateRoots(baseRoot).Contains(archivedRoot));
Assert.AreEqual(archivedRoot, InstallLayoutPaths.ResolveArchivedLayoutRoot());
}
[TestMethod]
public void ResolveAssetsRootAndExecutableUseInstallRoot()
{
using var workspace = TestWorkspace.Create("ymhut-install-assets-tests");
var installRoot = workspace.CreateDirectory("install");
var assetsRoot = workspace.CreateDirectory("install", "Assets");
var executable = workspace.CreateFile(["install", "YMhutBox.exe"], string.Empty);
var runtimeRoot = workspace.CreateDirectory("runtime");
using var environment = EnvironmentScope.Capture(
InstallLayoutPaths.InstallRootEnvironmentVariable,
InstallLayoutPaths.ArchivedLayoutEnvironmentVariable);
environment.Set(InstallLayoutPaths.InstallRootEnvironmentVariable, installRoot);
environment.Set(InstallLayoutPaths.ArchivedLayoutEnvironmentVariable, null);
Assert.AreEqual(assetsRoot, InstallLayoutPaths.ResolveAssetsRoot(runtimeRoot));
Assert.AreEqual(executable, InstallLayoutPaths.ResolveInstalledExecutablePath(runtimeRoot));
}
[TestMethod]
public void RuntimeLayoutPolicySkipsLargeToolsAndUserDataRoots()
{
foreach (var relativePath in new[]
{
"Tools/vendor/tool.exe",
"Metadata/tools.json",
"data/settings.json",
"FeedbackPackages/feedback.zip"
})
{
Assert.IsTrue(RuntimeLayoutPolicy.ShouldSkipRelativePath(relativePath), relativePath);
Assert.IsFalse(RuntimeLayoutPolicy.ShouldCopyFile(relativePath), relativePath);
}
Assert.IsFalse(RuntimeLayoutPolicy.ShouldCopyFile("unins000.exe"));
Assert.IsFalse(RuntimeLayoutPolicy.ShouldCopyFile("YMhutBox.exe"));
Assert.IsFalse(RuntimeLayoutPolicy.ShouldCopyFile("YMhutBox.dll"));
Assert.IsFalse(RuntimeLayoutPolicy.ShouldCopyFile("resources.pri"));
Assert.IsFalse(RuntimeLayoutPolicy.ShouldCopyFile("zh-CN/Microsoft.ui.xaml.dll.mui"));
Assert.IsFalse(RuntimeLayoutPolicy.ShouldCopyFile("lang/zh-CN/Microsoft.ui.xaml.dll.mui"));
Assert.IsFalse(RuntimeLayoutPolicy.ShouldCopyFile("runtimes/win-x64/native/Microsoft.ui.xaml.dll"));
}
[TestMethod]
public void InstallManifestParserReadsReleaseRequiredFilesAndPayloadFiles()
{
var manifest = InstallManifest.Parse(
"""
[Release]
Version=2.0.6
Build=2
Channel=stable
PackageVersion=2.0.6.2
[RequiredFiles]
YMhutBox.exe
YMhutBox.dll
[Files]
YMhutBox.exe
lang/zh-CN/Microsoft.ui.xaml.dll.mui
Tools/SampleTool/tool.exe
""");
Assert.IsNotNull(manifest.Release);
Assert.AreEqual("2.0.6", manifest.Release.Version);
Assert.AreEqual("2", manifest.Release.Build);
Assert.AreEqual("stable", manifest.Release.Channel);
Assert.AreEqual("2.0.6.2", manifest.Release.PackageVersion);
Assert.IsTrue(manifest.RequiredFiles.SequenceEqual(["YMhutBox.exe", "YMhutBox.dll"]));
Assert.IsTrue(manifest.ContainsFile(@"lang\zh-CN\Microsoft.ui.xaml.dll.mui"));
Assert.IsTrue(manifest.ContainsFile("Tools/SampleTool/tool.exe"));
}
[TestMethod]
public void RuntimeLayoutPolicySkipsRuntimePayloadRoots()
{
foreach (var relativePath in new[]
{
"lang/en-US/Microsoft.UI.Xaml.Phone.dll.mui",
"Microsoft.UI.Xaml/Microsoft.UI.Xaml.dll",
"runtimes/win-x64/native/WebView2Loader.dll",
"worker/YMhut.Box.Worker.exe"
})
{
Assert.IsFalse(RuntimeLayoutPolicy.ShouldCopyFile(relativePath), relativePath);
}
}
[TestMethod]
public void SourceFilesDoNotContainCommonMojibakeSequences()
{
var root = FindRepositoryRoot();
var scanRoots = new[]
{
Path.Combine(root, "src", "YMhut.Box.Core"),
Path.Combine(root, "src", "box-winUI"),
Path.Combine(root, "installer")
};
var extensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".cs", ".xaml", ".iss" };
var mojibakeMarkers = new[]
{
"Ã",
"Â",
"â",
"鈥",
"锛",
"銆",
"鐑",
"澶",
"璁",
"鏍",
"棰",
"缃"
};
var offenders = scanRoots
.Where(Directory.Exists)
.SelectMany(scanRoot => Directory.EnumerateFiles(scanRoot, "*.*", SearchOption.AllDirectories))
.Where(path => extensions.Contains(Path.GetExtension(path)))
.Where(path => !path.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}", StringComparison.OrdinalIgnoreCase))
.Where(path => !path.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}", StringComparison.OrdinalIgnoreCase))
.SelectMany(path => FindMojibakeMarkers(path, mojibakeMarkers))
.Take(12)
.ToArray();
Assert.IsEmpty(offenders, string.Join(Environment.NewLine, offenders));
}
private static IEnumerable<string> FindMojibakeMarkers(string path, IReadOnlyList<string> markers)
{
var text = File.ReadAllText(path);
foreach (var marker in markers)
{
if (text.Contains(marker, StringComparison.Ordinal))
{
yield return $"{Path.GetFileName(path)} contains '{marker}'";
}
}
}
private static string FindRepositoryRoot()
{
var directory = new DirectoryInfo(AppContext.BaseDirectory);
while (directory is not null)
{
if (Directory.Exists(Path.Combine(directory.FullName, "src")) &&
Directory.Exists(Path.Combine(directory.FullName, "installer")))
{
return directory.FullName;
}
directory = directory.Parent;
}
Assert.Fail("Repository root could not be found from test output directory.");
return AppContext.BaseDirectory;
}
private sealed class EnvironmentScope : IDisposable
{
private readonly Dictionary<string, string?> _snapshot;
private EnvironmentScope(IEnumerable<string> names)
{
_snapshot = names.ToDictionary(name => name, Environment.GetEnvironmentVariable, StringComparer.Ordinal);
}
public static EnvironmentScope Capture(params string[] names) => new(names);
public void Set(string name, string? value) => Environment.SetEnvironmentVariable(name, value);
public void Dispose()
{
foreach (var item in _snapshot)
{
Environment.SetEnvironmentVariable(item.Key, item.Value);
}
}
}
private sealed class TestWorkspace : IDisposable
{
private TestWorkspace(string root)
{
Root = root;
}
public string Root { get; }
public static TestWorkspace Create(string prefix)
{
var root = Path.Combine(Path.GetTempPath(), prefix, Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(root);
return new TestWorkspace(root);
}
public string CreateDirectory(params string[] parts)
{
var directory = Path.Combine([Root, .. parts]);
Directory.CreateDirectory(directory);
return directory;
}
public string CreateFile(string[] parts, string contents)
{
var path = Path.Combine([Root, .. parts]);
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
File.WriteAllText(path, contents);
return path;
}
public void Dispose()
{
if (Directory.Exists(Root))
{
Directory.Delete(Root, recursive: true);
}
}
}
}