// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include #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, 0.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(); CHECK(s.expected_collection_s.value() == Catch::Approx(0.11)); 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::nullopt, std::chrono::steady_clock::now() - 2s); status.Step("waiting"); const auto s = status.Get(); CHECK(!s.start_to_first_image_s); CHECK(!s.expected_collection_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("RugnuxLiveStatus_Clear", "[RugnuxLive]") { RugnuxLiveStatus status; status.Start(10, 1.0, std::chrono::steady_clock::now() - 2s); status.ImageReceived(std::chrono::steady_clock::now() - 1s); status.Step("indexing"); status.Probe("lattice found"); status.Result("OK", "fine", {{"Space group", "P 1"}}, {"a warning"}); status.Finish(RugnuxLiveState::Done); REQUIRE(status.LastImage()); status.Clear(); const auto s = status.Get(); CHECK(s.state == RugnuxLiveState::Idle); CHECK(s.images_expected == 0); CHECK(s.images_received == 0); CHECK(s.steps.empty()); CHECK(s.probe.empty()); CHECK(s.verdict.empty()); CHECK(s.summary.empty()); CHECK(s.warnings.empty()); CHECK(!s.start_to_first_image_s); CHECK(!s.last_image_s); CHECK(s.elapsed_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); }