The launcher (LA3/LA4) needs the XDG/Windows path contract (ApplicationPathSet/IApplicationPathEnvironment) without pulling in any gameplay assembly. Move it out of AcDream.Runtime into a new BCL-only AcDream.Platform project so the launcher-side Launcher.Core project can reference it directly per the campaign plan (docs/plans/2026-08-14-launcher-campaign.md, LA0). Namespace renamed AcDream.Runtime.Platform -> AcDream.Platform; code is otherwise byte-identical (no logic changes). AcDream.Runtime now carries a ProjectReference to AcDream.Platform and re-exports it transitively, so App and Headless keep resolving the type without a direct reference and K0's Headless single-ProjectReference guard (HeadlessAssemblyReferencesOnlyTheRuntimeProject) stands unchanged. The sibling Runtime dependency-boundary guard (RuntimeProjectDeclaresOnlyApprovedProjectDependencies) does assert Runtime's own project-reference set, so it needed a deliberate, documented addition of AcDream.Platform to its expected list. Moved tests/AcDream.Runtime.Tests/Platform/ApplicationPathSetTests.cs to a new tests/AcDream.Platform.Tests/ project (namespace AcDream.Platform.Tests) referencing only AcDream.Platform. Registered both new projects in AcDream.slnx. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
162 lines
5.4 KiB
C#
162 lines
5.4 KiB
C#
using AcDream.Platform;
|
|
|
|
namespace AcDream.Platform.Tests;
|
|
|
|
public sealed class ApplicationPathSetTests
|
|
{
|
|
[Fact]
|
|
public void LinuxUsesXdgRootsAndPublishesFeaturePaths()
|
|
{
|
|
string root = Path.GetFullPath(
|
|
Path.Combine(Path.GetTempPath(), "acdream-runtime-xdg"));
|
|
var platform = new FixtureEnvironment(isWindows: false)
|
|
{
|
|
CurrentDirectoryValue = Path.Combine(root, "work"),
|
|
UserProfile = Path.Combine(root, "home"),
|
|
Variables =
|
|
{
|
|
["XDG_CONFIG_HOME"] = Path.Combine(root, "cfg"),
|
|
["XDG_DATA_HOME"] = Path.Combine(root, "data"),
|
|
["XDG_CACHE_HOME"] = Path.Combine(root, "cache"),
|
|
},
|
|
};
|
|
|
|
ApplicationPathSet paths = ApplicationPathSet.Resolve(
|
|
platform: platform);
|
|
|
|
Assert.Equal(
|
|
Path.Combine(root, "cfg", "acdream"),
|
|
paths.ConfigDirectory);
|
|
Assert.Equal(
|
|
Path.Combine(root, "data", "acdream"),
|
|
paths.DataDirectory);
|
|
Assert.Equal(
|
|
Path.Combine(root, "cache", "acdream"),
|
|
paths.CacheDirectory);
|
|
Assert.Equal(
|
|
Path.Combine(paths.ConfigDirectory, "settings.json"),
|
|
paths.SettingsFile);
|
|
Assert.Equal(
|
|
Path.Combine(paths.ConfigDirectory, "keybinds.json"),
|
|
paths.KeyBindingsFile);
|
|
Assert.Equal(
|
|
Path.Combine(paths.DataDirectory, "plugins"),
|
|
paths.PluginsDirectory);
|
|
Assert.Equal(
|
|
Path.Combine(paths.CacheDirectory, "diagnostics"),
|
|
paths.DiagnosticsDirectory);
|
|
Assert.Null(paths.LegacyConfigDirectory);
|
|
}
|
|
|
|
[Fact]
|
|
public void LinuxFallsBackToHomeAndNormalizesOverrides()
|
|
{
|
|
string root = Path.GetFullPath(
|
|
Path.Combine(Path.GetTempPath(), "acdream runtime paths"));
|
|
var platform = new FixtureEnvironment(isWindows: false)
|
|
{
|
|
CurrentDirectoryValue = Path.Combine(root, "work"),
|
|
UserProfile = Path.Combine(root, "home"),
|
|
};
|
|
|
|
ApplicationPathSet paths = ApplicationPathSet.Resolve(
|
|
"relative config",
|
|
"dåta",
|
|
"cache",
|
|
platform);
|
|
|
|
Assert.Equal(
|
|
Path.GetFullPath(
|
|
"relative config",
|
|
platform.CurrentDirectoryValue),
|
|
paths.ConfigDirectory);
|
|
Assert.Equal(
|
|
Path.GetFullPath("dåta", platform.CurrentDirectoryValue),
|
|
paths.DataDirectory);
|
|
Assert.Equal(
|
|
Path.GetFullPath("cache", platform.CurrentDirectoryValue),
|
|
paths.CacheDirectory);
|
|
}
|
|
|
|
[Fact]
|
|
public void WindowsUsesRoamingConfigAndLocalData()
|
|
{
|
|
string root = Path.GetFullPath(
|
|
Path.Combine(Path.GetTempPath(), "acdream-runtime-windows"));
|
|
var platform = new FixtureEnvironment(isWindows: true)
|
|
{
|
|
CurrentDirectoryValue = Path.Combine(root, "work"),
|
|
ApplicationData = Path.Combine(root, "AppData", "Roaming"),
|
|
LocalApplicationData =
|
|
Path.Combine(root, "AppData", "Local"),
|
|
};
|
|
|
|
ApplicationPathSet paths = ApplicationPathSet.Resolve(
|
|
platform: platform);
|
|
|
|
Assert.Equal(
|
|
Path.Combine(
|
|
platform.ApplicationData,
|
|
"acdream"),
|
|
paths.ConfigDirectory);
|
|
Assert.Equal(
|
|
Path.Combine(
|
|
platform.LocalApplicationData,
|
|
"acdream"),
|
|
paths.DataDirectory);
|
|
Assert.Equal(
|
|
Path.Combine(
|
|
platform.LocalApplicationData,
|
|
"acdream",
|
|
"cache"),
|
|
paths.CacheDirectory);
|
|
Assert.Equal(
|
|
Path.Combine(
|
|
platform.LocalApplicationData,
|
|
"acdream"),
|
|
paths.LegacyConfigDirectory);
|
|
}
|
|
|
|
private sealed class FixtureEnvironment(bool isWindows)
|
|
: IApplicationPathEnvironment
|
|
{
|
|
public bool IsWindows { get; } = isWindows;
|
|
|
|
public string CurrentDirectoryValue { get; init; } =
|
|
Environment.CurrentDirectory;
|
|
|
|
public string CurrentDirectory => CurrentDirectoryValue;
|
|
|
|
public string UserProfile { get; init; } =
|
|
Environment.GetFolderPath(
|
|
Environment.SpecialFolder.UserProfile);
|
|
|
|
public string ApplicationData { get; init; } =
|
|
Environment.GetFolderPath(
|
|
Environment.SpecialFolder.ApplicationData);
|
|
|
|
public string LocalApplicationData { get; init; } =
|
|
Environment.GetFolderPath(
|
|
Environment.SpecialFolder.LocalApplicationData);
|
|
|
|
public Dictionary<string, string> Variables { get; } =
|
|
new(StringComparer.Ordinal);
|
|
|
|
public string? GetEnvironmentVariable(string name) =>
|
|
Variables.TryGetValue(name, out string? value)
|
|
? value
|
|
: null;
|
|
|
|
public string GetFolderPath(
|
|
Environment.SpecialFolder folder) =>
|
|
folder switch
|
|
{
|
|
Environment.SpecialFolder.UserProfile => UserProfile,
|
|
Environment.SpecialFolder.ApplicationData =>
|
|
ApplicationData,
|
|
Environment.SpecialFolder.LocalApplicationData =>
|
|
LocalApplicationData,
|
|
_ => string.Empty,
|
|
};
|
|
}
|
|
}
|