acdream/tests/AcDream.Content.Tests/ContentConformanceDats.cs
Erik 55f16a0205 test(pipeline): MP1b - live-vs-pak equivalence suite (dat-gated)
PakEquivalenceTests runs MeshExtractor LIVE and bakes the SAME fixture
ids to a temp pak, reads it back via PakReader, and deep-compares every
field via the Task 3 ObjectMeshDataEquality comparator. Since the bake
tool and the live client drive the identical MeshExtractor code (MP1a),
this proves the pak ROUND-TRIP preserves what extraction actually
produces on real content — the serializer's job, not a re-verification
of the extraction algorithm itself (the existing Conformance suite owns
that).

Fixture set (>= the plan's minimums): 10 GfxObjs (3 known-tricky ids
reused from Issue119UpNullGfxObjDumpTests - 0x010002B4, 0x010008A8,
0x010014C3 - plus 7 more from dat order), 3 Setups reused from door/
tower conformance fixtures (0x020019FF, 0x020005D8, 0x020003F2), 5
EnvCells walked from the Holtburg landblock 0xA9B40000's
LandBlockInfo.NumCells range (same idiom as
StipplingSurfaceEquivalenceTests).

Skips cleanly when dats are absent via ContentConformanceDats.
ResolveDatDir(), a deliberate small duplicate of
ConformanceDats.ResolveDatDir()'s exact pattern (env var then
Documents/Asheron's Call fallback) since Content.Tests cannot reference
the AcDream.Core.Tests project. ContentTestDatCollectionAdapter is a
third small copy of the IDatReaderWriter dat-access glue (alongside
AcDream.App's internal original and AcDream.Bake's copy) for the same
layering reason (structure rule 6: tests live in the project matching
the layer under test).

Ran for real against the dats on this machine (not just CI-skip path):
1 test, all fixture ids extracted live with zero failures, baked,
read back, and field-for-field identical. Full solution dotnet test:
4106 tests total (43 Content.Tests + 385 Core.Net.Tests + 425
UI.Abstractions.Tests + 722 App.Tests incl. 2 pre-existing skips + 2531
Core.Tests incl. 2 pre-existing skips) — 0 failures.
2026-07-05 21:33:32 +02:00

38 lines
1.9 KiB
C#

using System;
using System.IO;
using Microsoft.Extensions.Logging;
namespace AcDream.Content.Tests;
/// <summary>
/// Dat-dir resolution for the Content.Tests dat-gated equivalence suite.
/// Mirrors the exact pattern used by
/// tests/AcDream.Core.Tests/Conformance/ConformanceDats.ResolveDatDir and
/// tests/AcDream.Core.Tests/Conformance/DatConcurrencyStressTests
/// ("dats absent (CI) -- skip, matching suite convention"). Content.Tests
/// cannot reference AcDream.Core.Tests (a test project, not a library), so
/// this is a deliberate small duplication of the resolution logic — not a
/// new convention.
/// </summary>
public static class ContentConformanceDats {
public static string? ResolveDatDir() {
var fromEnv = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR");
if (!string.IsNullOrWhiteSpace(fromEnv) && Directory.Exists(fromEnv)) return fromEnv;
var def = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"Documents", "Asheron's Call");
return Directory.Exists(def) ? def : null;
}
}
/// <summary>Minimal ILogger writing to Console — surfaces MeshExtractor failures during the equivalence sweep instead of silently swallowing them (NullLogger would hide the exact failure this suite exists to catch).</summary>
internal sealed class TestConsoleLogger : ILogger {
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null;
public bool IsEnabled(LogLevel logLevel) => logLevel >= LogLevel.Warning;
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter) {
if (!IsEnabled(logLevel)) return;
Console.WriteLine($"[{logLevel}] MeshExtractor: {formatter(state, exception)}");
if (exception is not null) Console.WriteLine(exception);
}
}