test(engine): cover scaler zero-dimension source guard
All checks were successful
CI / build-and-test (push) Successful in 30s

Verifies a source frame with height==0, width==0, or both does not throw
(previously a divide-by-zero / NaN extents in ComputeFitRect) and instead
yields a black, fully-opaque frame at the target resolution.
This commit is contained in:
Zac Gaetano 2026-06-13 00:25:30 -04:00
parent 5b3bf7d5e8
commit 874f90d123

View file

@ -69,4 +69,41 @@ public class ManagedNearestNeighborFrameScalerTests
var centerOffset = (1080 / 2 * 1920 + 1920 / 2) * 4;
dst.Pixels.Span[centerOffset].Should().Be(0x10);
}
// ============================================================
// Zero-dimension source guard
// ============================================================
//
// A malformed/glitched NDI frame can report a zero dimension. Pre-fix this
// divided by zero in ComputeFitRect (Pillarbox/Letterbox) or drove a
// degenerate copy loop (Stretch). The guard must absorb it as a black frame
// at the target size rather than throw into the pipeline supervisor.
[Theory]
[InlineData(0, 100)]
[InlineData(100, 0)]
[InlineData(0, 0)]
public void ZeroDimensionSource_DoesNotThrow_AndYieldsBlackTargetSizedFrame(int srcW, int srcH)
{
var scaler = new ManagedNearestNeighborFrameScaler();
var src = Solid(Math.Max(srcW, 1), Math.Max(srcH, 1), 0x10, 0x20, 0x30, 0xFF) with
{
Width = srcW,
Height = srcH,
};
ProcessedFrame dst = default!;
var act = () => dst = scaler.Scale(src, 1280, 720, AspectMode.Pillarbox, 77);
act.Should().NotThrow();
dst.Width.Should().Be(1280);
dst.Height.Should().Be(720);
dst.Pixels.Length.Should().Be(1280 * 720 * 4);
dst.TimestampTicks.Should().Be(77);
// Black, fully opaque: B=G=R=0, A=0xFF.
dst.Pixels.Span[0].Should().Be(0x00);
dst.Pixels.Span[1].Should().Be(0x00);
dst.Pixels.Span[2].Should().Be(0x00);
dst.Pixels.Span[3].Should().Be(0xFF);
}
}