using AcDream.App.Rendering; using AcDream.Core.Meshing; namespace AcDream.App.Tests.Rendering; /// /// S4-c2 fix round 1 (M1, blocking): /// is the pure router-input derivation the blocking fix extracted from /// DeferToRetailAlphaQueue so it is directly testable without a GPU/ /// mesh-manager harness. Before this round, a mesh-particle batch classified /// (mask 0x00) reaching DrawMesh /// row 5 (Immediate) hit an unconditional throw in the render loop — these /// tests pin the two outcomes the fix made reachable. /// public sealed class ParticleRendererRouteTests { /// M1(d) pin 1: an Opaque-classified mesh-particle batch (mask /// 0x00) with a non-fully-opaque current alpha (top ColorArgb byte != /// 0xFF, i.e. materialHasAlpha true) routes to ALPHA (Append) — retail's /// row 4 material-alpha fallback — not Immediate. Mutation check: /// reverting to the pre-fix code (which threw whenever the decision /// wasn't Append) would not distinguish this from pin 2 below at all /// (both would just throw); reverting ONLY the materialHasAlpha /// derivation to a hardcoded `false` makes this assertion fail because /// the decision becomes Immediate instead of Append. [Fact] public void OpaqueClassifiedMeshBatch_WithMaterialAlpha_RoutesToAlphaAppend() { // Top byte (alpha) = 0x80 -> not 0xFF -> materialHasAlpha = true. const uint colorArgbWithAlpha = 0x80FFFFFFu; RetailAlphaMeshDecision decision = ParticleRenderer.RouteParticleSubmission( ParticleSubmissionKind.Mesh, TranslucencyKind.Opaque, colorArgbWithAlpha); Assert.Equal(RetailAlphaMeshAction.Append, decision.Action); Assert.Equal(RetailAlphaList.Alpha, decision.List); } /// M1(d) pin 2: the SAME Opaque-classified mesh-particle batch /// with a fully-opaque current alpha (top ColorArgb byte == 0xFF, i.e. /// materialHasAlpha false) draws immediately and never enters a list — /// retail's row 5 fallthrough. Mutation check: this is the EXACT case /// that threw before the fix (mask 0x00, materialHasAlpha false -> /// row 5 Immediate -> the old "rows 1/2/4/5 unreachable" guard fired); /// reverting the throw's removal reproduces /// InvalidOperationException here, which this test would report /// as a failure (an unhandled exception) rather than an assertion /// mismatch. [Fact] public void OpaqueClassifiedMeshBatch_WithNoMaterialAlpha_RoutesImmediate() { const uint fullyOpaqueColorArgb = 0xFFFFFFFFu; RetailAlphaMeshDecision decision = ParticleRenderer.RouteParticleSubmission( ParticleSubmissionKind.Mesh, TranslucencyKind.Opaque, fullyOpaqueColorArgb); Assert.Equal(RetailAlphaMeshAction.Immediate, decision.Action); } /// A billboard submission always carries the alpha-family mask /// (0x02) regardless of the (unused) mesh parameters, and therefore /// always satisfies row 3 (Append, ALPHA) under the fixed default delay /// mask — never Immediate, never CLIP. Mutation check: swapping /// for /// in the billboard /// branch would route this to the CLIP list instead of ALPHA. [Fact] public void Billboard_AlwaysRoutesToAlphaAppend() { RetailAlphaMeshDecision decision = ParticleRenderer.RouteParticleSubmission( ParticleSubmissionKind.Billboard, default, default); Assert.Equal(RetailAlphaMeshAction.Append, decision.Action); Assert.Equal(RetailAlphaList.Alpha, decision.List); } }