acdream/tests/AcDream.App.Tests/UI/Layout/LayoutImporterInvisibleSweepTests.cs
Erik f7aa8e0eb7
All checks were successful
CI / linux-portable (push) Successful in 3m41s
CI / windows-gate (push) Successful in 6m49s
CI / release (push) Successful in 3m22s
fix: complete retail parity stability pass
2026-08-28 20:01:39 +02:00

106 lines
4.1 KiB
C#

using System.IO;
using System.Linq;
using AcDream.App.UI;
using AcDream.App.UI.Layout;
using AcDream.Content;
using DatReaderWriter;
using DatReaderWriter.DBObjs;
using DatReaderWriter.Options;
namespace AcDream.App.Tests.UI.Layout;
/// <summary>
/// #408 client-wide blast-radius gate for DAT property 0x3B (Invisible).
/// Retail applies the property in UIElement::OnSetAttribute for every imported
/// element. Enumerate every installed LayoutDesc, then prove every corresponding
/// widget which survives importer child-consumption starts hidden.
/// </summary>
[Trait("Lane", "InstalledDat")]
public sealed class LayoutImporterInvisibleSweepTests
{
private static string DatDirectory =>
System.Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(
System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile),
"Documents",
"Asheron's Call");
private readonly record struct Finding(uint LayoutId, uint ElementId);
[InstalledDatFact]
public void EveryAuthoredInvisibleWidget_StartsHiddenAcrossAllLayouts()
{
using var dats = new DatCollection(DatDirectory, DatAccessType.Read);
var authored = new List<Finding>();
var built = new List<Finding>();
var incorrectlyVisible = new List<Finding>();
foreach (uint layoutId in dats.GetAllIdsOfType<LayoutDesc>().OrderBy(static id => id))
{
ElementInfo? tree = LayoutImporter.ImportInfos(dats, layoutId);
if (tree is null) continue;
CollectAuthored(layoutId, tree, authored);
ImportedLayout layout = LayoutImporter.Build(
tree, _ => (0u, 0, 0), datFont: null, sourceLayoutDid: layoutId);
CollectBuilt(layoutId, layout.Root, built, incorrectlyVisible);
}
foreach (IGrouping<uint, Finding> group in authored
.GroupBy(static f => f.LayoutId)
.OrderBy(static g => g.Key))
{
Console.WriteLine(
$"[INVISIBLE] layout=0x{group.Key:X8} count={group.Count()} ids=["
+ string.Join(",", group.Select(static f => $"0x{f.ElementId:X8}"))
+ "]");
}
Console.WriteLine(
$"[INVISIBLE] authored={authored.Count} layouts="
+ $"{authored.Select(static f => f.LayoutId).Distinct().Count()} "
+ $"built={built.Count} incorrectlyVisible={incorrectlyVisible.Count}");
// Keep the global threshold resilient to an installed DAT revision while
// pinning landmarks from independent screens in both data and widgets.
Assert.True(authored.Count >= 1_000,
$"Expected the known client-wide 0x3B population, found {authored.Count}.");
Assert.Contains(authored, static f => f.ElementId == 0x10000403u); // chargen GM label
Assert.Contains(authored, static f => f.ElementId == 0x10000494u); // chargen envoy label
Assert.Contains(authored, static f => f.ElementId == 0x100006A4u); // combat root
Assert.Contains(authored, static f => f.ElementId == 0x1000048Cu); // chat new-text indicator
Assert.Contains(built, static f => f.ElementId == 0x100006A4u);
Assert.Contains(built, static f => f.ElementId == 0x1000048Cu);
Assert.Empty(incorrectlyVisible);
}
private static void CollectAuthored(uint layoutId, ElementInfo node, List<Finding> findings)
{
if (node.Invisible)
findings.Add(new Finding(layoutId, node.Id));
foreach (ElementInfo child in node.Children)
CollectAuthored(layoutId, child, findings);
}
private static void CollectBuilt(
uint layoutId,
UiElement node,
List<Finding> built,
List<Finding> incorrectlyVisible)
{
if (node.AuthoredInvisible)
{
var finding = new Finding(layoutId, node.DatElementId);
built.Add(finding);
if (node.Visible)
incorrectlyVisible.Add(finding);
}
foreach (UiElement child in node.Children)
CollectBuilt(layoutId, child, built, incorrectlyVisible);
}
}