Deterministic render ordering
This commit is contained in:
@@ -7,7 +7,9 @@
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <latch>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
@@ -657,3 +659,98 @@ TEST_CASE("memory management") {
|
||||
CHECK(final_output.size() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("render output deterministic order golden test") {
|
||||
// Clean slate - reset all metrics before this test
|
||||
metric::reset_metrics_for_testing();
|
||||
|
||||
ArenaAllocator arena;
|
||||
|
||||
// Create a comprehensive set of metrics with deliberate ordering
|
||||
// to test deterministic output
|
||||
|
||||
// Create counters with different family names and labels
|
||||
auto z_counter_family =
|
||||
metric::create_counter("z_last_counter", "Last counter alphabetically");
|
||||
auto z_counter =
|
||||
z_counter_family.create({{"method", "POST"}, {"handler", "api"}});
|
||||
z_counter.inc(42.0);
|
||||
|
||||
auto a_counter_family =
|
||||
metric::create_counter("a_first_counter", "First counter alphabetically");
|
||||
auto a_counter1 = a_counter_family.create({{"status", "200"}});
|
||||
auto a_counter2 = a_counter_family.create(
|
||||
{{"method", "GET"}}); // Should come before status lexicographically
|
||||
a_counter1.inc(100.0);
|
||||
a_counter2.inc(200.0);
|
||||
|
||||
// Create gauges with different orderings
|
||||
auto m_gauge_family = metric::create_gauge("m_middle_gauge", "Middle gauge");
|
||||
auto m_gauge = m_gauge_family.create({{"type", "memory"}});
|
||||
m_gauge.set(1024.0);
|
||||
|
||||
auto b_gauge_family = metric::create_gauge("b_second_gauge", "Second gauge");
|
||||
auto b_gauge = b_gauge_family.create({{"region", "us-west"}});
|
||||
b_gauge.set(256.0);
|
||||
|
||||
// Create histograms
|
||||
auto x_hist_family = metric::create_histogram("x_histogram", "Test histogram",
|
||||
{0.1, 0.5, 1.0});
|
||||
auto x_hist = x_hist_family.create({{"endpoint", "/api/v1"}});
|
||||
x_hist.observe(0.25);
|
||||
x_hist.observe(0.75);
|
||||
|
||||
// Add some callbacks to test callback ordering
|
||||
a_counter_family.register_callback({{"callback", "test"}},
|
||||
[]() { return 123.0; });
|
||||
m_gauge_family.register_callback({{"callback", "dynamic"}},
|
||||
[]() { return 456.0; });
|
||||
|
||||
// Render the metrics
|
||||
auto output = metric::render(arena);
|
||||
|
||||
// Concatenate all output into a single string
|
||||
std::ostringstream oss;
|
||||
for (const auto &line : output) {
|
||||
oss << line;
|
||||
}
|
||||
std::string actual_output = oss.str();
|
||||
|
||||
// Define expected golden output - this represents the exact expected
|
||||
// deterministic order
|
||||
std::string expected_golden =
|
||||
"# HELP a_first_counter First counter alphabetically\n"
|
||||
"# TYPE a_first_counter counter\n"
|
||||
"a_first_counter{callback=\"test\"} 123\n"
|
||||
"a_first_counter{method=\"GET\"} 200\n"
|
||||
"a_first_counter{status=\"200\"} 100\n"
|
||||
"# HELP z_last_counter Last counter alphabetically\n"
|
||||
"# TYPE z_last_counter counter\n"
|
||||
"z_last_counter{handler=\"api\",method=\"POST\"} 42\n"
|
||||
"# HELP b_second_gauge Second gauge\n"
|
||||
"# TYPE b_second_gauge gauge\n"
|
||||
"b_second_gauge{region=\"us-west\"} 256\n"
|
||||
"# HELP m_middle_gauge Middle gauge\n"
|
||||
"# TYPE m_middle_gauge gauge\n"
|
||||
"m_middle_gauge{callback=\"dynamic\"} 456\n"
|
||||
"m_middle_gauge{type=\"memory\"} 1024\n"
|
||||
"# HELP x_histogram Test histogram\n"
|
||||
"# TYPE x_histogram histogram\n"
|
||||
"x_histogram_bucket{endpoint=\"/api/v1\",le=\"0.1\"} 0\n"
|
||||
"x_histogram_bucket{endpoint=\"/api/v1\",le=\"0.5\"} 1\n"
|
||||
"x_histogram_bucket{endpoint=\"/api/v1\",le=\"1.0\"} 2\n"
|
||||
"x_histogram_bucket{endpoint=\"/api/v1\",le=\"+Inf\"} 2\n"
|
||||
"x_histogram_sum{endpoint=\"/api/v1\"} 1\n"
|
||||
"x_histogram_count{endpoint=\"/api/v1\"} 2\n";
|
||||
|
||||
// Check if output matches golden file
|
||||
if (actual_output != expected_golden) {
|
||||
MESSAGE("Render output does not match expected golden output.");
|
||||
MESSAGE("This indicates the deterministic ordering has changed.");
|
||||
MESSAGE("Expected output:\n" << expected_golden);
|
||||
MESSAGE("Actual output:\n" << actual_output);
|
||||
CHECK(false); // Force test failure
|
||||
} else {
|
||||
CHECK(true); // Test passes
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user