acdream/tests/AcDream.App.Tests/Diagnostics/WorldLifecycleAutomationControllerTests.cs

153 lines
5.3 KiB
C#

using System.Text.Json;
using AcDream.App.Diagnostics;
using AcDream.App.Streaming;
using SixLabors.ImageSharp;
namespace AcDream.App.Tests.Diagnostics;
public sealed class WorldLifecycleAutomationControllerTests
{
[Fact]
public void ScreenshotCapture_FlipsGlRowsAndWritesACompletePng()
{
string directory = NewDirectory();
// GL order: bottom row red/green, top row blue/white.
byte[] rgba =
[
255, 0, 0, 255, 0, 255, 0, 255,
0, 0, 255, 255, 255, 255, 255, 255,
];
var logs = new List<string>();
var controller = new FrameScreenshotController(
() => (2, 2),
(_, _) => rgba,
directory,
logs.Add);
try
{
Assert.True(controller.TryRequest("login_stable", out string error), error);
Assert.False(controller.IsComplete("login_stable"));
Assert.True(controller.CapturePending());
Assert.True(controller.IsComplete("login_stable"));
string path = Path.Combine(directory, "login_stable.png");
using Image image = Image.Load(path);
Assert.Equal(2, image.Width);
Assert.Equal(2, image.Height);
Assert.Contains(logs, line => line.Contains("screenshot-complete", StringComparison.Ordinal));
byte[] flipped = FrameScreenshotController.FlipRows(rgba, 2, 2);
Assert.Equal(rgba.AsSpan(8, 8).ToArray(), flipped.AsSpan(0, 8).ToArray());
Assert.Equal(rgba.AsSpan(0, 8).ToArray(), flipped.AsSpan(8, 8).ToArray());
}
finally
{
Directory.Delete(directory, recursive: true);
}
}
[Fact]
public void ScreenshotCapture_ReportsNoWorkAndFailedCapture()
{
string directory = NewDirectory();
var controller = new FrameScreenshotController(
() => (0, 0),
(_, _) => [],
directory);
try
{
Assert.False(controller.CapturePending());
Assert.True(controller.TryRequest("bad_frame", out string error), error);
Assert.False(controller.CapturePending());
Assert.False(controller.IsComplete("bad_frame"));
}
finally
{
if (Directory.Exists(directory))
Directory.Delete(directory, recursive: true);
}
}
[Theory]
[InlineData("")]
[InlineData("../escape")]
[InlineData("has spaces")]
[InlineData("name.png")]
public void ArtifactNames_RejectPathsAndAmbiguousCharacters(string name)
{
Assert.False(AutomationArtifactName.TryValidate(name, out string error));
Assert.NotEmpty(error);
}
[Fact]
public void Checkpoint_WritesCanonicalRevealAndResourceSnapshot()
{
string directory = NewDirectory();
var reveal = new WorldRevealLifecycleSnapshot(
Generation: 7,
Kind: WorldRevealKind.Portal,
Readiness: new WorldRevealReadinessSnapshot(
0x8A020164u,
IsIndoor: true,
IsUnhydratable: false,
RequiredRenderRadius: 0,
IsRenderNeighborhoodReady: true,
AreCompositeTexturesReady: true,
IsCollisionReady: true),
Materialized: true,
Completed: true,
Cancelled: false,
WorldViewportObserved: true,
InvariantFailureCount: 0);
var resources = EmptyResources() with
{
LoadedLandblocks = 1,
WorldEntities = 42,
TrackedGpuBytes = 1234,
};
var screenshots = new FrameScreenshotController(
() => (1, 1),
(_, _) => [0, 0, 0, 255],
Path.Combine(directory, "screenshots"));
var controller = new WorldLifecycleAutomationController(
() => reveal,
() => 3,
() => resources,
screenshots,
directory);
try
{
Assert.True(controller.IsWorldReady);
Assert.True(controller.IsWorldViewportVisible);
Assert.Equal(3, controller.PortalMaterializationCount);
Assert.True(controller.TryWriteCheckpoint("dungeon", out string error), error);
string line = Assert.Single(File.ReadAllLines(
Path.Combine(directory, "world-lifecycle.checkpoints.jsonl")));
using JsonDocument json = JsonDocument.Parse(line);
Assert.Equal("dungeon", json.RootElement.GetProperty("name").GetString());
Assert.Equal(7, json.RootElement.GetProperty("reveal").GetProperty("generation").GetInt64());
Assert.Equal(42, json.RootElement.GetProperty("resources").GetProperty("worldEntities").GetInt32());
Assert.True(File.Exists(Path.Combine(directory, "checkpoint-dungeon.json")));
}
finally
{
Directory.Delete(directory, recursive: true);
}
}
private static WorldLifecycleResourceSnapshot EmptyResources() => new(
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0L, 0, 0L, 0L, 0, 0, 0, 0, 0, 0, 0, 0L, 0L, 0d, 0d, null);
private static string NewDirectory()
{
string path = Path.Combine(Path.GetTempPath(), "acdream-world-gate-" + Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(path);
return path;
}
}