diff --git a/.github/workflows/headless-portability.yml b/.github/workflows/headless-portability.yml index a24ae829..6facc5ed 100644 --- a/.github/workflows/headless-portability.yml +++ b/.github/workflows/headless-portability.yml @@ -6,6 +6,7 @@ on: - ".github/workflows/headless-portability.yml" - "AcDream.slnx" - "src/AcDream.Platform/**" + - "src/AcDream.Launcher.Core/**" - "src/AcDream.Core/**" - "src/AcDream.Core.Net/**" - "src/AcDream.Content/**" @@ -15,6 +16,7 @@ on: - "src/AcDream.App/**" - "src/AcDream.UI.Abstractions/**" - "tests/AcDream.Platform.Tests/**" + - "tests/AcDream.Launcher.Core.Tests/**" - "tests/AcDream.Core.Tests/**" - "tests/AcDream.Core.Net.Tests/**" - "tests/AcDream.Content.Tests/**" @@ -22,6 +24,7 @@ on: - "tests/AcDream.Headless.Tests/**" - "tests/AcDream.App.Tests/**" - "tests/AcDream.UI.Abstractions.Tests/**" + - "tests/Fixtures/campaign-la/**" - "tools/ShaderCompiler/**" - "tools/compile-shaders.ps1" push: @@ -29,6 +32,7 @@ on: - ".github/workflows/headless-portability.yml" - "AcDream.slnx" - "src/AcDream.Platform/**" + - "src/AcDream.Launcher.Core/**" - "src/AcDream.Core/**" - "src/AcDream.Core.Net/**" - "src/AcDream.Content/**" @@ -38,6 +42,7 @@ on: - "src/AcDream.App/**" - "src/AcDream.UI.Abstractions/**" - "tests/AcDream.Platform.Tests/**" + - "tests/AcDream.Launcher.Core.Tests/**" - "tests/AcDream.Core.Tests/**" - "tests/AcDream.Core.Net.Tests/**" - "tests/AcDream.Content.Tests/**" @@ -45,6 +50,7 @@ on: - "tests/AcDream.Headless.Tests/**" - "tests/AcDream.App.Tests/**" - "tests/AcDream.UI.Abstractions.Tests/**" + - "tests/Fixtures/campaign-la/**" - "tools/ShaderCompiler/**" - "tools/compile-shaders.ps1" workflow_dispatch: @@ -83,6 +89,7 @@ jobs: run: | $projects = @( "src/AcDream.Platform/AcDream.Platform.csproj", + "src/AcDream.Launcher.Core/AcDream.Launcher.Core.csproj", "src/AcDream.Plugin.Abstractions/AcDream.Plugin.Abstractions.csproj", "src/AcDream.Core/AcDream.Core.csproj", "src/AcDream.Core.Net/AcDream.Core.Net.csproj", @@ -104,6 +111,7 @@ jobs: run: | $projects = @( "tests/AcDream.Platform.Tests/AcDream.Platform.Tests.csproj", + "tests/AcDream.Launcher.Core.Tests/AcDream.Launcher.Core.Tests.csproj", "tests/AcDream.Core.Net.Tests/AcDream.Core.Net.Tests.csproj", "tests/AcDream.Content.Tests/AcDream.Content.Tests.csproj", "tests/AcDream.Runtime.Tests/AcDream.Runtime.Tests.csproj", diff --git a/tests/AcDream.App.Tests/AcDream.App.Tests.csproj b/tests/AcDream.App.Tests/AcDream.App.Tests.csproj index 186d903d..6760881b 100644 --- a/tests/AcDream.App.Tests/AcDream.App.Tests.csproj +++ b/tests/AcDream.App.Tests/AcDream.App.Tests.csproj @@ -22,6 +22,12 @@ + + + + + diff --git a/tests/AcDream.App.Tests/Configuration/SessionConfigurationSharedFixtureTests.cs b/tests/AcDream.App.Tests/Configuration/SessionConfigurationSharedFixtureTests.cs index 1760946b..c37ce9fe 100644 --- a/tests/AcDream.App.Tests/Configuration/SessionConfigurationSharedFixtureTests.cs +++ b/tests/AcDream.App.Tests/Configuration/SessionConfigurationSharedFixtureTests.cs @@ -1,5 +1,6 @@ using System.Runtime.CompilerServices; using AcDream.App.Configuration; +using AcDream.Tests.Fixtures.CampaignLa; namespace AcDream.App.Tests.Configuration; @@ -18,6 +19,43 @@ namespace AcDream.App.Tests.Configuration; /// public sealed class SessionConfigurationSharedFixtureTests { + [Fact] + public void AppReaderAcceptsLauncherCoreComposerDocument() + { + using TemporaryFile file = TemporaryFile.Create( + LauncherCoreSessionConfigFixture.Compose()); + + (SessionConfiguration configuration, SessionDescriptor session) = + SessionConfigurationLoader.Load(file.Path); + + Assert.Equal("composer-contract", session.Id); + Assert.Equal("composer.example", session.Endpoint.Host); + Assert.Equal(9010, session.Endpoint.Port); + Assert.Equal("composer-account", session.Account); + Assert.Equal(0x50000001u, session.Character?.Id); + Assert.Equal("idle", session.Policy?.Id); + Assert.Equal( + SessionCredentialProviderKind.StandardInput, + session.Credential.Provider); + Assert.Equal("session", session.Credential.Reference); + Assert.Equal("composer-dats", configuration.Process?.Content?.DatDirectory); + Assert.Equal( + "composer-dats/acdream.pak", + configuration.Process?.Content?.PreparedAssetPath); + Assert.Equal(["ComposerPlugin"], session.Plugins); + Assert.Equal(["/composer command"], session.LoginCommands); + Assert.Equal(625, session.LoginCommandDelayMs); + string statusFile = Assert.IsType(session.StatusFile); + Assert.EndsWith( + Path.Combine("composer-contract", "status.jsonl"), + statusFile, + StringComparison.Ordinal); + Assert.DoesNotContain( + LauncherCoreSessionConfigFixture.Password, + File.ReadAllText(file.Path), + StringComparison.Ordinal); + } + [Fact] public void AppReaderAcceptsTheProductionShapedSharedFixture() { diff --git a/tests/AcDream.Headless.Tests/AcDream.Headless.Tests.csproj b/tests/AcDream.Headless.Tests/AcDream.Headless.Tests.csproj index 8a17a145..9591a359 100644 --- a/tests/AcDream.Headless.Tests/AcDream.Headless.Tests.csproj +++ b/tests/AcDream.Headless.Tests/AcDream.Headless.Tests.csproj @@ -21,5 +21,11 @@ + + + + + diff --git a/tests/AcDream.Headless.Tests/SessionConfigurationSharedFixtureTests.cs b/tests/AcDream.Headless.Tests/SessionConfigurationSharedFixtureTests.cs index 20a86697..5a8a3aa1 100644 --- a/tests/AcDream.Headless.Tests/SessionConfigurationSharedFixtureTests.cs +++ b/tests/AcDream.Headless.Tests/SessionConfigurationSharedFixtureTests.cs @@ -1,5 +1,6 @@ using System.Runtime.CompilerServices; using AcDream.Headless.Configuration; +using AcDream.Tests.Fixtures.CampaignLa; namespace AcDream.Headless.Tests; @@ -17,6 +18,44 @@ namespace AcDream.Headless.Tests; /// public sealed class SessionConfigurationSharedFixtureTests { + [Fact] + public void HeadlessReaderAcceptsLauncherCoreComposerDocument() + { + using TemporaryFile file = TemporaryFile.Create( + LauncherCoreSessionConfigFixture.Compose()); + + HeadlessConfiguration configuration = + HeadlessConfigurationLoader.Load(file.Path); + + HeadlessSessionDescriptor session = Assert.Single(configuration.Sessions)!; + Assert.Equal("composer-contract", session.Id); + Assert.Equal("composer.example", session.Endpoint.Host); + Assert.Equal(9010, session.Endpoint.Port); + Assert.Equal("composer-account", session.Account); + Assert.Equal(0x50000001u, session.Character.Id); + Assert.Equal("idle", session.Policy.Id); + Assert.Equal( + HeadlessCredentialProviderKind.StandardInput, + session.Credential.Provider); + Assert.Equal("session", session.Credential.Reference); + Assert.Equal("composer-dats", configuration.Process.Content?.DatDirectory); + Assert.Equal( + "composer-dats/acdream.pak", + configuration.Process.Content?.PreparedAssetPath); + Assert.Equal(["ComposerPlugin"], session.Plugins); + Assert.Equal(["/composer command"], session.LoginCommands); + Assert.Equal(625, session.LoginCommandDelayMs); + string statusFile = Assert.IsType(session.StatusFile); + Assert.EndsWith( + Path.Combine("composer-contract", "status.jsonl"), + statusFile, + StringComparison.Ordinal); + Assert.DoesNotContain( + LauncherCoreSessionConfigFixture.Password, + File.ReadAllText(file.Path), + StringComparison.Ordinal); + } + [Fact] public void HeadlessReaderAcceptsTheProductionShapedSharedFixture() { diff --git a/tests/Fixtures/campaign-la/LauncherCoreSessionConfigFixture.cs b/tests/Fixtures/campaign-la/LauncherCoreSessionConfigFixture.cs new file mode 100644 index 00000000..71b6581e --- /dev/null +++ b/tests/Fixtures/campaign-la/LauncherCoreSessionConfigFixture.cs @@ -0,0 +1,58 @@ +using AcDream.Launcher.Core.Launching; +using AcDream.Launcher.Core.Profiles; +using AcDream.Platform; + +namespace AcDream.Tests.Fixtures.CampaignLa; + +/// +/// Produces one real Launcher.Core session document that is compiled into +/// both host test suites. Keeping composition in one linked fixture makes the +/// LA1/LA3 anti-drift gate prove that App and Headless accept the identical +/// composer output rather than two hand-maintained lookalikes. +/// +internal static class LauncherCoreSessionConfigFixture +{ + internal const string Password = "must-not-be-serialized"; + + internal static string Compose() + { + var server = new ServerProfile + { + Name = "Composer Server", + Host = "composer.example", + Port = 9010, + }; + var account = new AccountProfile + { + Account = "composer-account", + Password = Password, + }; + var character = new CharacterProfile + { + Name = "Composer Character", + Id = "0x50000001", + LaunchMode = LaunchMode.Headless, + Plugins = ["ComposerPlugin"], + LoginCommands = ["/composer command"], + }; + var install = new LauncherInstallRecord( + "composer-dats", + "composer-dats/acdream.pak"); + var paths = new ApplicationPathSet( + Path.Combine(Path.GetTempPath(), "composer-config"), + Path.Combine(Path.GetTempPath(), "composer-data"), + Path.Combine(Path.GetTempPath(), "composer-cache"), + LegacyConfigDirectory: null); + + ComposedSessionConfig composed = SessionConfigComposer.Compose( + server, + account, + character, + install, + paths, + "composer-contract", + loginCommandDelayMs: 625); + + return SessionConfigComposer.Serialize(composed.Document); + } +}