Skip to content

Unit tests for PerfTelemetry #2500

Description

@ten9876

Follow-up to #2480 (merge commit 59c1c378).

PerfTelemetry is the diagnostic singleton @jensenpat just landed, and the public API is deterministic enough to unit-test in isolation:

  • Inputs are explicit recording calls (recordFrameAge, recordPanUpdate, recordUdpBatch, etc.) with caller-supplied numeric values
  • Window aggregation runs on a 1-second cadence triggered by maybeLogSummary(now) — tests can drive now directly
  • Output goes through the lcPerf logging category — capturable via a Qt message handler hook for the duration of the test

Suggested test cases

Disabled hot-path is no-op:

  • With lcPerf disabled, calling recordPanUpdate(50.0) repeatedly emits no log lines, mutates no observable state.

Window aggregation:

  • Enable lcPerf. Feed N pan-update samples at known values. Advance to T+1s. Verify the emitted PerfSummary line contains the correct count, p95, max.
  • Window resets after summary: subsequent samples don't carry old state.

Stall thresholds:

  • recordPanUpdate(9.0) → emits a PerfStall line with kind=panUpdate. Threshold is 8.0 ms.
  • recordPanUpdate(7.0) → no stall line.
  • Same matrix for the other thresholds (frameAge, render, udpDrain, etc.).

Drag-aware UI lag thresholds:

  • setDragActive(false) then recordUiHeartbeat() with a 40 ms gap → no stall (idle threshold is 50 ms).
  • setDragActive(true) same input → emits a stall (drag threshold is 33 ms).

Frame-restart counter:

  • recordFrameRestart(Panadapter) × 3 → counter shows 3 in the next summary.

Percentile-95 boundary cases:

  • Empty input → returns 0.0
  • Single value → returns that value
  • 100 values [1..100] → returns 95
  • Already-sorted input → result matches unsorted

Window timing:

  • Records spread across 950 ms → no summary yet
  • One more record at 1100 ms → triggers summary with full count

Test infrastructure

The Qt message handler hook is the standard way to capture log output:

QString lastLine;
qInstallMessageHandler([](QtMsgType, const QMessageLogContext& ctx, const QString& msg) {
    if (QString::fromUtf8(ctx.category) == "aether.perf")
        lastLine = msg;
});

Test file at tests/perf_telemetry_test.cpp, registered in CMakeLists.txt as add_executable(perf_telemetry_test ...) per the existing test pattern.

Priority

Low. The class is exercised continuously when telemetry is enabled in production runs, so behavioral regressions surface fast. But unit coverage would catch threshold/percentile/aggregation regressions before a release ships, and the threshold values themselves are likely to be tuned over time — tests prevent silent drift.

73, Jeremy KK7GWY & Claude (AI dev partner)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementImprovement to existing featuremaintainer-reviewRequires maintainer review before any action is takenpriority: lowLow priority

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions