Optimize prepared asset package v2

This commit is contained in:
Erik 2026-08-27 20:09:09 +02:00
parent d123c4b67c
commit 0dd966f3a0
28 changed files with 1277 additions and 106 deletions

View file

@ -0,0 +1,29 @@
using AcDream.Launcher.Core.Installation;
namespace AcDream.Launcher.Core.Tests.Installation;
public sealed class ContentMigrationCatalogTests
{
[Fact]
public void RecipeFiveToSixRequiresOneExplicitFullRebuild()
{
ContentMigrationPlan plan = ContentMigrationCatalog.Resolve(5, 6);
Assert.Equal(ContentWorkKind.FullRebuild, plan.Kind);
Assert.Equal(5u, plan.FromRecipeVersion);
Assert.Equal(6u, plan.TargetRecipeVersion);
Assert.Contains("pak v2", plan.Reason, StringComparison.OrdinalIgnoreCase);
Assert.Empty(plan.EffectiveDatIds);
Assert.Empty(plan.EffectiveLandblocks);
}
[Fact]
public void AnyOlderRecipeToSixCollapsesToOneFullRebuild()
{
ContentMigrationPlan plan = ContentMigrationCatalog.Resolve(1, 6);
Assert.Equal(ContentWorkKind.FullRebuild, plan.Kind);
Assert.Equal(6u, plan.TargetRecipeVersion);
Assert.Contains("pak v2", plan.Reason, StringComparison.OrdinalIgnoreCase);
}
}

View file

@ -133,7 +133,7 @@ public sealed class LauncherContentStateStoreTests : IDisposable
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
byte[] bytes = new byte[64];
BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(0, 4), 0x4B504341u);
BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(4, 4), 1);
BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(4, 4), 2);
BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(8, 4), 100);
BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(12, 4), 200);
BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(16, 4), 300);

View file

@ -147,6 +147,33 @@ public sealed class LauncherInstallerTests : IDisposable
StringComparison.Ordinal);
}
[Fact]
public async Task InsufficientFreeSpaceStopsBeforeBakeAndReportsExactRequirement()
{
bool childStarted = false;
var runner = new FakeBakeProcessRunner((_, _, _) =>
{
childStarted = true;
return Task.FromResult(new BakeProcessResult(0, string.Empty));
});
var installer = new LauncherInstaller(
_paths,
_bakeExecutable,
processRunner: runner,
availableFreeSpace: _ =>
LauncherInstaller.FullRebuildRequiredFreeBytes - 1);
LauncherInstallException error = await Assert.ThrowsAsync<LauncherInstallException>(
() => installer.InstallAsync(_dats, threads: 2));
Assert.False(childStarted);
Assert.Contains("2.0 GiB", error.Message, StringComparison.Ordinal);
Assert.Contains("active package", error.Message, StringComparison.Ordinal);
Assert.False(File.Exists(
LauncherInstaller.GetFullRebuildCandidatePath(
Path.Combine(_paths.DataDirectory, "pak", "acdream.pak"))));
}
[Fact]
public async Task FullContentMigrationPersistsClientGateAcrossLauncherRestart()
{

View file

@ -58,8 +58,8 @@ public sealed class LauncherOverlayInstallerTests : IDisposable
request.OutputPath,
LauncherInstallRecordStore.CurrentBakeToolVersion);
long bytes = new FileInfo(request.OutputPath).Length;
output($"{{\"v\":1,\"e\":\"started\",\"bakeToolVersion\":5}}\n");
output($"{{\"v\":1,\"e\":\"completed\",\"bakeToolVersion\":5,"
output($"{{\"v\":1,\"e\":\"started\",\"bakeToolVersion\":{LauncherInstallRecordStore.CurrentBakeToolVersion}}}\n");
output($"{{\"v\":1,\"e\":\"completed\",\"bakeToolVersion\":{LauncherInstallRecordStore.CurrentBakeToolVersion},"
+ $"\"outputBytes\":{bytes},\"failures\":0}}\n");
await Task.Yield();
return new BakeProcessResult(0, string.Empty);
@ -70,8 +70,8 @@ public sealed class LauncherOverlayInstallerTests : IDisposable
recordStore: recordStore,
processRunner: runner);
var migration = new ContentMigrationPlan(
4,
5,
LauncherInstallRecordStore.CurrentBakeToolVersion - 1,
LauncherInstallRecordStore.CurrentBakeToolVersion,
ContentWorkKind.Overlay,
"bounded fixture update",
[0x01001234u, 0x02005678u],
@ -93,7 +93,9 @@ public sealed class LauncherOverlayInstallerTests : IDisposable
observed.Arguments.SkipWhile(value => value != "--landblocks").Take(2));
Assert.NotNull(result.Record.PreparedAssetOverlayPath);
Assert.True(File.Exists(result.Record.PreparedAssetOverlayPath));
Assert.Equal(5u, result.Record.ResolvedBakeToolVersion);
Assert.Equal(
LauncherInstallRecordStore.CurrentBakeToolVersion,
result.Record.ResolvedBakeToolVersion);
Assert.True(result.Record.RequiresClientCompatibilityConfirmation);
Assert.False(File.Exists(
new LauncherContentStateStore(_paths).OverlayCandidatePath));
@ -145,7 +147,9 @@ public sealed class LauncherOverlayInstallerTests : IDisposable
TaskCreationOptions.RunContinuationsAsynchronously);
var runner = new FakeRunner(async (request, _, cancellationToken) =>
{
LauncherContentStateStoreTests.WritePakHeader(request.OutputPath, 5);
LauncherContentStateStoreTests.WritePakHeader(
request.OutputPath,
LauncherInstallRecordStore.CurrentBakeToolVersion);
entered.SetResult();
await Task.Delay(Timeout.InfiniteTimeSpan, cancellationToken);
return new BakeProcessResult(0, string.Empty);
@ -160,8 +164,8 @@ public sealed class LauncherOverlayInstallerTests : IDisposable
_dats,
2,
new ContentMigrationPlan(
4,
5,
LauncherInstallRecordStore.CurrentBakeToolVersion - 1,
LauncherInstallRecordStore.CurrentBakeToolVersion,
ContentWorkKind.Overlay,
"bounded fixture update",
[0x01001234u]),
@ -189,11 +193,11 @@ public sealed class LauncherOverlayInstallerTests : IDisposable
{
LauncherContentStateStoreTests.WritePakHeader(
recordStore.PreparedAssetPath,
recipe: 4);
recipe: LauncherInstallRecordStore.CurrentBakeToolVersion - 1);
LauncherInstallRecord baseRecord =
await LauncherContentStateStoreTests.RecordAsync(
recordStore.PreparedAssetPath,
recipe: 4,
recipe: LauncherInstallRecordStore.CurrentBakeToolVersion - 1,
datDirectory: Path.GetFullPath(_dats));
Directory.CreateDirectory(_paths.DataDirectory);
await File.WriteAllTextAsync(