#include "RenderCadenceClock.h" #include #include namespace { int gFailures = 0; void Expect(bool condition, const char* message) { if (condition) return; std::cerr << "FAIL: " << message << "\n"; ++gFailures; } void TestEarlyPollWaitsWithoutAdvancing() { using Clock = RenderCadenceClock::Clock; RenderCadenceClock cadence(16.0); const auto start = Clock::now(); cadence.Reset(start); const auto tick = cadence.Poll(start - std::chrono::milliseconds(1)); Expect(!tick.due, "early poll is not due"); Expect(tick.sleepFor > RenderCadenceClock::Duration::zero(), "early poll returns a sleep duration"); Expect(cadence.OverrunCount() == 0, "early poll does not count overrun"); Expect(cadence.SkippedFrameCount() == 0, "early poll does not skip frames"); } void TestDuePollRendersWithoutSkipping() { using Clock = RenderCadenceClock::Clock; RenderCadenceClock cadence(16.0); const auto start = Clock::now(); cadence.Reset(start); const auto tick = cadence.Poll(start); Expect(tick.due, "exact cadence time is due"); Expect(tick.skippedFrames == 0, "exact cadence time skips no frames"); Expect(cadence.OverrunCount() == 0, "exact cadence time is not an overrun"); cadence.MarkRendered(start); Expect(cadence.NextRenderTime() > start, "mark rendered advances next render time"); } void TestLatePollRecordsSkippedFrames() { using Clock = RenderCadenceClock::Clock; RenderCadenceClock cadence(10.0); const auto start = Clock::now(); cadence.Reset(start); const auto tick = cadence.Poll(start + std::chrono::milliseconds(35)); Expect(tick.due, "late poll is due"); Expect(tick.skippedFrames == 3, "late poll records skipped frame intervals"); Expect(cadence.OverrunCount() == 1, "late poll records overrun"); Expect(cadence.SkippedFrameCount() == 3, "late poll accumulates skipped frames"); } void TestLatePollSkipsMissedIntervalsInsteadOfCatchingUp() { using Clock = RenderCadenceClock::Clock; RenderCadenceClock cadence(10.0); const auto start = Clock::now(); cadence.Reset(start); const auto late = start + std::chrono::milliseconds(35); const auto tick = cadence.Poll(late); Expect(tick.due, "late skipped-interval poll is due"); Expect(tick.skippedFrames == 3, "late skipped-interval poll counts missed frames"); cadence.MarkRendered(late); Expect(cadence.NextRenderTime() > late, "late render schedules the next tick in the future"); Expect(cadence.NextRenderTime() - late <= std::chrono::milliseconds(6), "late render does not leave catch-up frames due immediately"); const auto immediateFollowup = cadence.Poll(late); Expect(!immediateFollowup.due, "cadence does not allow an immediate catch-up render after a late frame"); Expect(immediateFollowup.sleepFor > RenderCadenceClock::Duration::zero(), "cadence reports wait time after skipping missed intervals"); } void TestMarkRenderedRebasesAfterLargeStall() { using Clock = RenderCadenceClock::Clock; RenderCadenceClock cadence(10.0); const auto start = Clock::now(); cadence.Reset(start); const auto stalled = start + std::chrono::milliseconds(100); cadence.MarkRendered(stalled); const auto next = cadence.NextRenderTime(); Expect(next > stalled, "large stall rebases next render time after now"); Expect(next - stalled <= std::chrono::milliseconds(11), "large stall rebases to roughly one frame ahead"); } } int main() { TestEarlyPollWaitsWithoutAdvancing(); TestDuePollRendersWithoutSkipping(); TestLatePollRecordsSkippedFrames(); TestLatePollSkipsMissedIntervalsInsteadOfCatchingUp(); TestMarkRenderedRebasesAfterLargeStall(); if (gFailures != 0) { std::cerr << gFailures << " cadence clock test failure(s).\n"; return 1; } std::cout << "RenderCadenceCompositor cadence clock tests passed.\n"; return 0; }