88 lines
4.2 KiB
C++
88 lines
4.2 KiB
C++
#include "rockstream/latency.hpp"
|
|
#include "rockstream/probe.hpp"
|
|
|
|
#include <array>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
#include <string_view>
|
|
|
|
namespace {
|
|
void expect(bool condition, const char* message) {
|
|
if (!condition) throw std::runtime_error(message);
|
|
}
|
|
template<class F> 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;
|
|
}
|
|
}
|