// Copyright Epic Games, Inc. All Rights Reserved. #include namespace zen { void hyperloglog_forcelink() { } } // namespace zen #if ZEN_WITH_TESTS # include # include # include # include namespace zen::tests { TEST_SUITE_BEGIN("telemetry.hyperloglog"); TEST_CASE("hyperloglog.empty") { metrics::HyperLogLog<> Hll; CHECK_EQ(Hll.Count(), 0); } TEST_CASE("hyperloglog.single_element") { metrics::HyperLogLog<> Hll; Hll.Add("hello"); CHECK(Hll.Count() >= 1); CHECK(Hll.Count() <= 2); } TEST_CASE("hyperloglog.duplicates") { metrics::HyperLogLog<> Hll; for (int i = 0; i < 1000; ++i) { Hll.Add("same_value"); } CHECK_EQ(Hll.Count(), 1); } TEST_CASE("hyperloglog.estimate_accuracy") { // With precision 14, expected error is ~0.81% // Use a generous margin (5%) for the test to be reliable constexpr uint64_t N = 100000; metrics::HyperLogLog<14> Hll; for (uint64_t i = 0; i < N; ++i) { std::string Value = fmt::format("item_{}", i); Hll.Add(Value); } uint64_t Estimate = Hll.Count(); double Error = std::abs(static_cast(Estimate) - static_cast(N)) / static_cast(N); CHECK(Error < 0.05); } TEST_CASE("hyperloglog.small_cardinality") { metrics::HyperLogLog<> Hll; for (int i = 0; i < 10; ++i) { std::string Value = fmt::format("key_{}", i); Hll.Add(Value); } uint64_t Estimate = Hll.Count(); CHECK(Estimate >= 8); CHECK(Estimate <= 12); } TEST_CASE("hyperloglog.clear") { metrics::HyperLogLog<> Hll; for (int i = 0; i < 100; ++i) { std::string Value = fmt::format("v_{}", i); Hll.Add(Value); } CHECK(Hll.Count() > 0); Hll.Clear(); CHECK_EQ(Hll.Count(), 0); } TEST_CASE("hyperloglog.merge") { constexpr uint64_t N = 50000; metrics::HyperLogLog<14> A; metrics::HyperLogLog<14> B; // A gets even numbers, B gets odd numbers for (uint64_t i = 0; i < N; ++i) { std::string Value = fmt::format("item_{}", i * 2); A.Add(Value); } for (uint64_t i = 0; i < N; ++i) { std::string Value = fmt::format("item_{}", i * 2 + 1); B.Add(Value); } A.Merge(B); uint64_t Estimate = A.Count(); double Error = std::abs(static_cast(Estimate) - static_cast(N * 2)) / static_cast(N * 2); CHECK(Error < 0.05); } TEST_SUITE_END(); } // namespace zen::tests #endif // ZEN_WITH_TESTS