Files
vdm/gui/tests/tst_speedgraphwidget.cpp
samiandClaude Sonnet 5 41bce91770 gui: add SegmentBarsWidget and SpeedGraphWidget
Per-connection progress bars and the 60 s rolling speed graph the progress
dialog needs (docs/03-gui-spec.md §3). Both reuse row/widget state across
ticks instead of rebuilding, matching the discipline DownloadTableModel
already uses for progress patches.

SpeedGraphWidget keeps a fixed ring buffer and one reused QPainterPath —
no allocation in paintEvent or addSample. Fixed a real bug found while
writing tst_speedgraphwidget: the elapsed timer was started in the
constructor, so the very first sample after construction would silently
wait up to 1 s to be recorded instead of landing immediately.

Tested against mockd (both offline via QTest/offscreen, and manually
against a running mockd instance through ProgressDialog once that lands).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NSCdCWFXBTSBBK3MzWtJiC
2026-09-11 12:10:06 +04:00

74 lines
2.0 KiB
C++

// SpeedGraphWidget unit tests. Lane GUI.
//
// Red when: addSample stops throttling to 1 Hz (a burst of ticks would flood the ring
// buffer and skew the 60 s window), the sample count stops saturating at the window size,
// or painting crashes before two samples have been recorded (the "collecting…" branch).
#include <QtTest>
#include "widgets/SpeedGraphWidget.hpp"
using velox::gui::SpeedGraphWidget;
class TstSpeedGraphWidget : public QObject {
Q_OBJECT
private slots:
void burstsWithinASecondCountOnce();
void separatedSamplesEachCount();
void clearResetsCount();
void paintDoesNotCrashBeforeTwoSamples();
};
void TstSpeedGraphWidget::burstsWithinASecondCountOnce() {
SpeedGraphWidget w;
QCOMPARE(w.debugSampleCount(), 0);
// The first call always records (no prior bucket); the rest land inside the same
// second and must be coalesced into that one bucket.
for (int i = 0; i < 20; ++i) {
w.addSample(1000 + i);
}
QCOMPARE(w.debugSampleCount(), 1);
}
void TstSpeedGraphWidget::separatedSamplesEachCount() {
SpeedGraphWidget w;
w.addSample(100);
QCOMPARE(w.debugSampleCount(), 1);
QTest::qWait(1100);
w.addSample(200);
QCOMPARE(w.debugSampleCount(), 2);
QTest::qWait(1100);
w.addSample(300);
QCOMPARE(w.debugSampleCount(), 3);
}
void TstSpeedGraphWidget::clearResetsCount() {
SpeedGraphWidget w;
w.addSample(100);
QTest::qWait(1100);
w.addSample(200);
QVERIFY(w.debugSampleCount() > 0);
w.clear();
QCOMPARE(w.debugSampleCount(), 0);
}
void TstSpeedGraphWidget::paintDoesNotCrashBeforeTwoSamples() {
SpeedGraphWidget w;
w.resize(200, 60);
const QPixmap empty = w.grab();
QVERIFY(!empty.isNull());
w.addSample(500);
const QPixmap oneSample = w.grab();
QVERIFY(!oneSample.isNull());
QTest::qWait(1100);
w.addSample(700);
const QPixmap twoSamples = w.grab();
QVERIFY(!twoSamples.isNull());
}
QTEST_MAIN(TstSpeedGraphWidget)
#include "tst_speedgraphwidget.moc"