mirror of
https://github.com/LANCommander/GameOverlay.Capture.git
synced 2026-08-01 03:38:56 -04:00
115 lines
3.9 KiB
C#
115 lines
3.9 KiB
C#
using GameOverlay.Capture;
|
|
using Xunit;
|
|
|
|
namespace GameOverlay.Capture.Tests;
|
|
|
|
public class FrameTimeStatisticsTests
|
|
{
|
|
[Fact]
|
|
public void Empty_ReturnsEmptySummary()
|
|
{
|
|
var stats = new FrameTimeStatistics();
|
|
Assert.Equal(0, stats.Count);
|
|
Assert.Equal(MetricsSummary.Empty, stats.ComputeSummary());
|
|
}
|
|
|
|
[Fact]
|
|
public void ConstantFrameTimes_GiveExactFps()
|
|
{
|
|
var stats = new FrameTimeStatistics();
|
|
for (int i = 0; i < 100; i++)
|
|
stats.AddFrameTime(10.0); // 10 ms => 100 fps
|
|
|
|
var s = stats.ComputeSummary();
|
|
Assert.Equal(100, s.FrameCount);
|
|
Assert.Equal(100.0, s.AverageFps, 6);
|
|
Assert.Equal(100.0, s.MinFps, 6);
|
|
Assert.Equal(100.0, s.MaxFps, 6);
|
|
Assert.Equal(100.0, s.OnePercentLowFps, 6);
|
|
Assert.Equal(100.0, s.PointOnePercentLowFps, 6);
|
|
Assert.Equal(10.0, s.AverageFrameTimeMs, 6);
|
|
Assert.Equal(1.0, s.DurationSeconds, 6); // 100 * 10ms = 1s
|
|
}
|
|
|
|
[Fact]
|
|
public void NonPositiveFrameTimes_AreIgnored()
|
|
{
|
|
var stats = new FrameTimeStatistics();
|
|
stats.AddFrameTime(0);
|
|
stats.AddFrameTime(-5);
|
|
stats.AddFrameTime(double.NaN);
|
|
stats.AddFrameTime(double.PositiveInfinity);
|
|
stats.AddFrameTime(16.6);
|
|
Assert.Equal(1, stats.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void MinMaxFps_DerivedFromExtremeFrameTimes()
|
|
{
|
|
var stats = new FrameTimeStatistics();
|
|
// Mostly fast frames, a couple of slow spikes.
|
|
for (int i = 0; i < 98; i++)
|
|
stats.AddFrameTime(8.0); // 125 fps
|
|
stats.AddFrameTime(4.0); // 250 fps -> fastest frame => MaxFps
|
|
stats.AddFrameTime(50.0); // 20 fps -> slowest frame => MinFps
|
|
|
|
var s = stats.ComputeSummary();
|
|
Assert.Equal(250.0, s.MaxFps, 6);
|
|
Assert.Equal(20.0, s.MinFps, 6);
|
|
}
|
|
|
|
[Fact]
|
|
public void OnePercentLow_UsesNinetyNinthPercentileFrameTime()
|
|
{
|
|
var stats = new FrameTimeStatistics();
|
|
// 99 frames at 10 ms, 1 frame at 100 ms. Nearest-rank P99 of 100 samples = the 99th value.
|
|
for (int i = 0; i < 99; i++)
|
|
stats.AddFrameTime(10.0);
|
|
stats.AddFrameTime(100.0);
|
|
|
|
// Sorted ascending: [10 x99, 100]. rank at P99 = ceil(0.99*100)=99 => element#99 = 10ms => 100 fps.
|
|
Assert.Equal(10.0, stats.PercentileFrameTimeMs(99.0), 6);
|
|
// P99.9 = ceil(0.999*100)=100 => element#100 = 100ms => 10 fps.
|
|
Assert.Equal(100.0, stats.PercentileFrameTimeMs(99.9), 6);
|
|
|
|
var s = stats.ComputeSummary();
|
|
Assert.Equal(100.0, s.OnePercentLowFps, 6); // 1000/10
|
|
Assert.Equal(10.0, s.PointOnePercentLowFps, 6); // 1000/100
|
|
}
|
|
|
|
[Fact]
|
|
public void PresentTimestamps_ConvertToFrameTimeDeltas()
|
|
{
|
|
var stats = new FrameTimeStatistics();
|
|
const long tps = 1000; // 1 tick = 1 ms
|
|
stats.AddPresentTimestamp(0, tps); // baseline, no sample
|
|
stats.AddPresentTimestamp(16, tps); // 16 ms
|
|
stats.AddPresentTimestamp(32, tps); // 16 ms
|
|
stats.AddPresentTimestamp(50, tps); // 18 ms
|
|
|
|
Assert.Equal(3, stats.Count);
|
|
var s = stats.ComputeSummary();
|
|
Assert.Equal((16.0 + 16.0 + 18.0) / 3.0, s.AverageFrameTimeMs, 6);
|
|
}
|
|
|
|
[Fact]
|
|
public void Percentile_OutOfRange_Throws()
|
|
{
|
|
var stats = new FrameTimeStatistics();
|
|
stats.AddFrameTime(10);
|
|
Assert.Throws<ArgumentOutOfRangeException>(() => stats.PercentileFrameTimeMs(-1));
|
|
Assert.Throws<ArgumentOutOfRangeException>(() => stats.PercentileFrameTimeMs(101));
|
|
}
|
|
|
|
[Fact]
|
|
public void Reset_ClearsState()
|
|
{
|
|
var stats = new FrameTimeStatistics();
|
|
stats.AddFrameTime(10);
|
|
stats.AddPresentTimestamp(100, 1000);
|
|
stats.Reset();
|
|
Assert.Equal(0, stats.Count);
|
|
stats.AddPresentTimestamp(200, 1000); // first after reset is a baseline again
|
|
Assert.Equal(0, stats.Count);
|
|
}
|
|
}
|