From 8c2dea744cc731797f0d8d20600b1dbfdce5c963 Mon Sep 17 00:00:00 2001 From: Ben Deane Date: Thu, 27 Mar 2025 14:53:22 -0600 Subject: [PATCH] :bug: Field matcher logs shouldn't coerce args to `std::uint32_t` Problem: - When field matchers log their match descriptions, they coerce the field types to std::uint32_t. Logging can deal with other types now. Solution: - Preserve the field types. Only log hex values for integral types. --- include/msg/field_matchers.hpp | 26 +++++++++++++++------ test/msg/field_matchers.cpp | 42 ++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/include/msg/field_matchers.hpp b/include/msg/field_matchers.hpp index 81319759..a4d10f26 100644 --- a/include/msg/field_matchers.hpp +++ b/include/msg/field_matchers.hpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -141,17 +142,28 @@ struct rel_matcher_t { } [[nodiscard]] constexpr auto describe() const { - return stdx::ct_format<"{} {} 0x{:x}">( - Field::name, detail::to_string(), - stdx::ct(ExpectedValue)>()); + if constexpr (std::integral) { + return stdx::ct_format<"{} {} 0x{:x}">(Field::name, + detail::to_string(), + stdx::ct()); + } else { + return stdx::ct_format<"{} {} {}">(Field::name, + detail::to_string(), + stdx::ct()); + } } template [[nodiscard]] constexpr auto describe_match(MsgType const &msg) const { - return stdx::ct_format<"{} (0x{:x}) {} 0x{:x}">( - Field::name, static_cast(extract_field(msg)), - detail::to_string(), - stdx::ct(ExpectedValue)>()); + if constexpr (std::integral) { + return stdx::ct_format<"{} (0x{:x}) {} 0x{:x}">( + Field::name, extract_field(msg), detail::to_string(), + stdx::ct()); + } else { + return stdx::ct_format<"{} ({}) {} {}">( + Field::name, extract_field(msg), detail::to_string(), + stdx::ct()); + } } private: diff --git a/test/msg/field_matchers.cpp b/test/msg/field_matchers.cpp index 28b01421..0dfd8c0a 100644 --- a/test/msg/field_matchers.cpp +++ b/test/msg/field_matchers.cpp @@ -2,14 +2,56 @@ #include #include +#include +#include + #include namespace { using namespace msg; using test_field = field<"test_field", std::uint32_t>::located; + +enum struct E { A, B, C }; + +using test_enum_field = + field<"enum_field", E>::located; } // namespace +TEST_CASE("matcher description", "[field matchers]") { + using namespace stdx::literals; + constexpr auto m = msg::less_than_t{}; + constexpr auto desc = m.describe(); + static_assert(desc.str == "test_field < 0x5"_ctst); +} + +TEST_CASE("matcher description of match", "[field matchers]") { + using namespace stdx::literals; + using msg_data = std::array; + + constexpr auto m = msg::less_than_t{}; + constexpr auto desc = m.describe_match(msg_data{0x01ff'ffff}); + static_assert(desc.str == "test_field (0x{:x}) < 0x5"_ctst); + static_assert(desc.args == stdx::tuple{1}); +} + +TEST_CASE("matcher description (enum field)", "[field matchers]") { + using namespace stdx::literals; + constexpr auto m = msg::less_than_t{}; + constexpr auto desc = m.describe(); + static_assert(desc.str == "enum_field < C"_ctst); +} + +TEST_CASE("matcher description of match (enum field)", "[field matchers]") { + using namespace stdx::literals; + using msg_data = std::array; + + constexpr auto m = msg::less_than_t{}; + constexpr auto desc = m.describe_match(msg_data{0x01ff'ffff}); + static_assert(desc.str == "enum_field ({}) < C"_ctst); + static_assert(desc.args == stdx::tuple{E::B}); +} + TEST_CASE("negate less_than", "[field matchers]") { constexpr auto m = msg::less_than_t{}; constexpr auto n = match::negate(m);