#include "rockstream/latency.hpp" #include "rockstream/probe.hpp" #include #include #include #include #include namespace { void expect(bool condition, const char* message) { if (!condition) throw std::runtime_error(message); } template void rejects(F action) { try { action(); } catch (const std::exception&) { return; } throw std::runtime_error("Expected rejection"); } } int main() { try { using namespace rockstream; using namespace std::literals; const auto parsed = parse_probe_options(std::array{"--tiles"sv, "off"sv, "--mode"sv, "unpaced"sv, "--split-ctus"sv, "60"sv, "--inflight"sv, "2"sv, "--dry-run"sv}); expect(!parsed.tiles && !parsed.paced && parsed.split_ctus == 60 && parsed.inflight == 2 && parsed.dry_run, "Probe configuration did not parse correctly"); rejects([] { parse_probe_options(std::array{"--width"sv, "3839"sv}); }); rejects([] { parse_probe_options(std::array{"--fps"sv, "0"sv}); }); rejects([] { parse_probe_options(std::array{"--frames"sv, "4294967296"sv}); }); rejects([] { parse_probe_options(std::array{"--inflight"sv, "-1"sv}); }); rejects([] { parse_probe_options(std::array{"--split-ctus"sv, "2x"sv}); }); rejects([] { parse_probe_options(std::array{"--tiles"sv, "maybe"sv}); }); rejects([] { parse_probe_options(std::array{"--frames"sv}); }); rejects([] { parse_probe_options(std::array{"--unknown"sv, "1"sv}); }); rejects([] { parse_probe_options(std::array{"--output"sv, "same"sv, "--csv"sv, "same"sv}); }); LatencyLog log(3); log.submitted(1, 90, 100, 110); log.submitted(2, 190, 200, 210); log.packet(1, 120, 20, false, true); expect(!log.complete(1), "First partition must not complete a frame"); log.reclaimed(1, 130); expect(!log.complete(1), "Reclaim alone must not complete a partitioned frame"); log.packet(2, 220, 50, true, false); expect(!log.complete(2), "EOI must not imply buffer reclamation"); log.packet(1, 240, 30, true, false); log.reclaimed(2, 250); expect(log.complete(1) && log.complete(2), "Completion state lost"); expect(log.at(1).first == 120 && log.at(1).final == 240 && log.at(1).bytes == 50 && log.at(1).packets == 2 && log.at(1).intra == 1, "Partition aggregation failed"); rejects([&] { log.reclaimed(1, 260); }); rejects([&] { log.packet(1, 260, 1, false, false); }); rejects([&] { log.submitted(1, 1, 2, 3); }); rejects([&] { log.packet(0, 260, 1, true, false); }); rejects([&] { log.packet(3, 260, 1, true, false); }); log.submitted(3, 290, 300, 310); rejects([&] { log.packet(3, 320, 0, true, false); }); rejects([&] { log.packet(3, 305, 1, true, false); }); expect(percentile({1, 2, 3, 4}, 50) == 2 && percentile({1, 2, 3, 4}, 99) == 4, "Nearest-rank percentiles incorrect"); rejects([] { percentile({}, 50); }); rejects([] { percentile({1}, 101); }); std::ostringstream csv, report; write_latency_csv(csv, log, 1); expect(csv.str().find("1,1,1,90,100,110,120,240,130,50,2") != std::string::npos, "CSV lost raw timestamps or warmup/intra flags"); print_latency_report(report, log, 1); expect(report.str().find("Measured completed frames=1") != std::string::npos, "Report included warmup or incomplete frames"); LatencyLog missing_metadata(1); missing_metadata.submitted(1, 100, 100, 110); missing_metadata.packet(1, 120, 1, true, -1); missing_metadata.reclaimed(1, 130); std::ostringstream unclassified; print_latency_report(unclassified, missing_metadata, 0); expect(unclassified.str().find("Unclassified final output") != std::string::npos && unclassified.str().find("Non-intra final output") == std::string::npos, "Missing intra metadata was misclassified"); std::cout << "Probe configuration, frame lifecycle, CSV and percentile checks passed.\n"; return 0; } catch (const std::exception& e) { std::cerr << e.what() << '\n'; return 1; } }