using AcDream.App.Rendering;
namespace AcDream.App.Tests.Rendering;
///
/// S4-c2 fix round 1 (M6, contract C4):
/// is the queue-facing half of an EnvCell transparent shell's detail-off
/// submission — one token per CELL, replayed through a caller-supplied
/// delegate (production wiring:
/// )
/// at whatever flush site the shared drains
/// at. These tests exercise the REAL production class end-to-end against a
/// real queue — only the render destination is faked (a delegate recording
/// what it was asked to draw), so the GPU-backed EnvCellRenderer
/// never needs to be constructed to pin the queue mechanics.
///
public sealed class EnvCellAlphaDrawSourceTests
{
/// Mutation check: if SubmitOrDrawTransparentCellShell
/// drew the cell immediately instead of appending it when detail is off
/// (the M1/M3 bug class this chunk fixes elsewhere), the drawn list
/// would already contain an entry BEFORE Flush runs — the
/// Assert.Empty(drawn) line fails against that mutation.
[Fact]
public void PendingCellToken_IsDrainedAtTheFlushAndNeverBeforeIt()
{
var drawn = new List>();
var source = new RetailPViewPassExecutor.EnvCellAlphaDrawSource(
cells => drawn.Add(cells.ToArray()));
var queue = new RetailAlphaQueue();
queue.BeginFrame();
int token = source.AddPendingCellId(0x1234u);
Assert.True(queue.TryAppend(RetailAlphaList.Alpha, source, token, false));
Assert.Empty(drawn);
queue.Flush(RetailAlphaFlushSite.DrawBuilding, 0f);
IReadOnlyList singleDraw = Assert.Single(drawn);
Assert.Equal(new uint[] { 0x1234u }, singleDraw);
queue.EndFrame();
}
/// Two cell tokens from the SAME ,
/// with an unrelated source's entry appended between them, must still
/// produce TWO separate single-cell draw calls around the interposed
/// entry — 's "only adjacent
/// same-source entries batch" invariant (the queue never groups across
/// another entry, which is what keeps compositing order exact). Mutation
/// check: an implementation that draws every prepared cell id in one
/// call regardless of the requested (first, count) range would
/// print both cell ids together on EACH of the two
/// DrawPreparedAlphaBatch invocations instead of once each — the
/// exact sequence assertion below fails against that mutation.
[Fact]
public void ParticleAppendedBetweenTwoCellTokens_KeepsItsPositionInTheCombinedDrain()
{
var log = new List();
var cellSource = new RetailPViewPassExecutor.EnvCellAlphaDrawSource(
cells => log.Add($"cell:{string.Join(',', cells)}"));
var particleSource = new RecordingSource("particle", log);
var queue = new RetailAlphaQueue();
queue.BeginFrame();
int cell1Token = cellSource.AddPendingCellId(0x100u);
Assert.True(queue.TryAppend(RetailAlphaList.Alpha, cellSource, cell1Token, false));
Assert.True(queue.TryAppend(RetailAlphaList.Alpha, particleSource, 7, false));
int cell2Token = cellSource.AddPendingCellId(0x200u);
Assert.True(queue.TryAppend(RetailAlphaList.Alpha, cellSource, cell2Token, false));
queue.EndFrame();
Assert.Equal(new[] { "cell:256", "particle:7", "cell:512" }, log);
}
private sealed class RecordingSource(string name, List log) : IRetailAlphaDrawSource
{
private int[] _prepared = [];
public void PrepareAlphaDraws(ReadOnlySpan tokens) => _prepared = tokens.ToArray();
public void DrawPreparedAlphaBatch(int firstPreparedDraw, int drawCount)
{
for (int i = 0; i < drawCount; i++)
log.Add($"{name}:{_prepared[firstPreparedDraw + i]}");
}
public void ResetAlphaSubmissions()
{
}
}
}