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);
+ }
+}