#include #include #include #include #include "dpf.hpp" #include "dpf/json.hpp" namespace { // Round-trip a comparison-only multi-level key through JSON and confirm the // (public) comparison channel still reconstructs after deserialization. TEST(IncrementalJsonTest, CmpKeyRoundTrips) { const uint32_t alpha = 0x00abcdefu; const uint64_t yt = 42u; auto [k0, k1] = dpf::make_dpf(alpha, dpf::lt(yt)); using KT = std::decay_t; static_assert(KT::is_multilevel, "cmp key must be multi-level"); ASSERT_EQ(KT::num_outputs, 0u); const std::string s0 = dpf::json::to_json(k0); const std::string s1 = dpf::json::to_json(k1); auto r0 = dpf::json::from_json(s0); auto r1 = dpf::json::from_json(s1); const uint64_t mask = k0.cmp().mask; EXPECT_EQ(r0.cmp().nbits, k0.cmp().nbits); EXPECT_EQ(r0.cmp().mask, k0.cmp().mask); EXPECT_EQ(r0.cw_last(), k0.cw_last()); EXPECT_EQ(r0.cmp_addend(), k0.cmp_addend()); auto recon_cmp = [&](uint32_t q) { return dpf::reconstruct(dpf::eval_point(dpf::cmp, r0, q), dpf::eval_point(dpf::cmp, r1, q)) & mask; }; EXPECT_EQ(recon_cmp(alpha - 1u), yt); EXPECT_EQ(recon_cmp(0u), yt); EXPECT_EQ(recon_cmp(alpha), 0u); EXPECT_EQ(recon_cmp(alpha + 1u), 0u); } // A geq comparison (inverted path-sum) must also survive the round-trip. TEST(IncrementalJsonTest, CmpGeqRoundTrips) { const uint32_t alpha = 100u; const uint64_t yt = 5u, yf = 9u; auto [k0, k1] = dpf::make_dpf(alpha, dpf::geq(yt, yf)); using KT = std::decay_t; auto r0 = dpf::json::from_json(dpf::json::to_json(k0)); auto r1 = dpf::json::from_json(dpf::json::to_json(k1)); const uint64_t mask = k0.cmp().mask; auto r = [&](uint32_t q) { return dpf::reconstruct(dpf::eval_point(dpf::cmp, r0, q), dpf::eval_point(dpf::cmp, r1, q)) & mask; }; EXPECT_EQ(r(99u), yf); EXPECT_EQ(r(100u), yt); EXPECT_EQ(r(101u), yt); } } // namespace