The live panel showed ~80 Hz on a 100 Hz collection. Its clock started when the receiver had applied and forwarded the START message, so the START -> first image gap counted as collection time; the images were stamped when a forward thread dequeued them, and the last image only after END and the thread joins; and N images were divided by a span holding N-1 intervals. - ImagePullerOutput carries `received`, a steady_clock time set by the TCP and ZeroMQ pullers as the message comes off the socket, before it is queued or deserialised (TestImagePuller stamps it on Put when unset). - RugnuxLiveStatus takes those times: START's for its origin, each image's for the first and last image (min/max, as forward threads report out of order). last_image_s is the last data image's puller time. - Zero of every reported time (elapsed_s, steps' started_s, probe_s, last_image_s, cut_s) is now the FIRST IMAGE, as the frontend already said; before the first image arrives "now" is 0 and earlier steps are negative. The START -> first image time is recorded on its own as start_to_first_image_s (snapshot, OpenAPI rugnux_live_status, regenerated C++ model and frontend client, OpenAPIConvert). - The frontend rate is (images_received - 1) / (last - first image); the panel headers show "START -> first image X.X s". - The broker logs "rugnux live: START -> first image ..., N images in T s from the first to the last (R Hz)"; "done X s after the last image" and last_image_to_written_s run from the puller time of the last image. The deadline timer is unchanged (it still starts once the forward threads have joined). No analysis result changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXc1zD1yxHqaR1DGdCTHL4
61 lines
2.0 KiB
C++
61 lines
2.0 KiB
C++
// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include <catch2/catch_all.hpp>
|
|
|
|
#include "../receiver/RugnuxLiveStatus.h"
|
|
#include "../image_puller/TestImagePuller.h"
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
TEST_CASE("RugnuxLiveStatus_TimesFromFirstImage", "[RugnuxLive]") {
|
|
// 11 images at 100 Hz, the first 3 s after START, reported out of order as several forward threads do
|
|
const auto start = std::chrono::steady_clock::now() - 10s;
|
|
const auto first = start + 3s;
|
|
|
|
RugnuxLiveStatus status;
|
|
status.Start(11, start);
|
|
for (int i: {1, 0, 2, 3, 4, 5, 6, 7, 8, 10, 9})
|
|
status.ImageReceived(first + i * 10ms);
|
|
|
|
auto s = status.Get();
|
|
REQUIRE(s.images_received == 11);
|
|
REQUIRE(s.start_to_first_image_s.value() == Catch::Approx(3.0));
|
|
CHECK(!s.last_image_s);
|
|
// "now" is 10 s after START, 7 s after the first image
|
|
CHECK(s.elapsed_s == Catch::Approx(7.0).margin(0.5));
|
|
|
|
REQUIRE(status.LastImage() == first + 100ms);
|
|
s = status.Get();
|
|
REQUIRE(s.last_image_s.value() == Catch::Approx(0.1));
|
|
CHECK((s.images_received - 1) / s.last_image_s.value() == Catch::Approx(100.0));
|
|
}
|
|
|
|
TEST_CASE("RugnuxLiveStatus_BeforeFirstImage", "[RugnuxLive]") {
|
|
RugnuxLiveStatus status;
|
|
status.Start(10, std::chrono::steady_clock::now() - 2s);
|
|
status.Step("waiting");
|
|
|
|
const auto s = status.Get();
|
|
CHECK(!s.start_to_first_image_s);
|
|
CHECK(s.elapsed_s == 0.0);
|
|
REQUIRE(s.steps.size() == 1);
|
|
CHECK(s.steps[0].started_s <= 0.0);
|
|
CHECK(!status.LastImage());
|
|
}
|
|
|
|
TEST_CASE("TestImagePuller_SetsReceiveTime", "[RugnuxLive]") {
|
|
TestImagePuller puller;
|
|
const auto before = std::chrono::steady_clock::now();
|
|
puller.Put(ImagePullerOutput{});
|
|
const auto given = before - 5s;
|
|
puller.Put(ImagePullerOutput{.received = given});
|
|
|
|
auto out = puller.PollImage();
|
|
REQUIRE(out);
|
|
CHECK(out->received >= before);
|
|
out = puller.PollImage();
|
|
REQUIRE(out);
|
|
CHECK(out->received == given);
|
|
}
|