// Copyright (c) FIRST and other WPILib contributors. // Open Source Software; you can modify and/or share it under the terms of // the WPILib BSD license file in the root directory of this project. #include #include #include "wpi/DataLog.h" namespace { struct ThingA { int x = 0; }; struct ThingB { int x = 0; }; struct ThingC { int x = 0; }; struct Info1 { int info = 0; }; struct Info2 { int info = 0; }; } // namespace template <> struct wpi::Struct { static constexpr std::string_view GetTypeString() { return "struct:ThingA"; } static constexpr size_t GetSize() { return 1; } static constexpr std::string_view GetSchema() { return "uint8 value"; } static ThingA Unpack(std::span data) { return ThingA{.x = data[0]}; } static void Pack(std::span data, const ThingA& value) { data[0] = value.x; } }; template <> struct wpi::Struct { static constexpr std::string_view GetTypeString(const Info1&) { return "struct:ThingB"; } static constexpr size_t GetSize(const Info1&) { return 1; } static constexpr std::string_view GetSchema(const Info1&) { return "uint8 value"; } static ThingB Unpack(std::span data, const Info1&) { return ThingB{.x = data[0]}; } static void Pack(std::span data, const ThingB& value, const Info1&) { data[0] = value.x; } }; template <> struct wpi::Struct { static constexpr std::string_view GetTypeString() { return "struct:ThingC"; } static constexpr size_t GetSize() { return 1; } static constexpr std::string_view GetSchema() { return "uint8 value"; } static ThingC Unpack(std::span data) { return ThingC{.x = data[0]}; } static void Pack(std::span data, const ThingC& value) { data[0] = value.x; } }; template <> struct wpi::Struct { static constexpr std::string_view GetTypeString(const Info1&) { return "struct:ThingC"; } static constexpr size_t GetSize(const Info1&) { return 1; } static constexpr std::string_view GetSchema(const Info1&) { return "uint8 value"; } static ThingC Unpack(std::span data, const Info1&) { return ThingC{.x = data[0]}; } static void Pack(std::span data, const ThingC& value, const Info1&) { data[0] = value.x; } }; template <> struct wpi::Struct { static constexpr std::string_view GetTypeString(const Info2&) { return "struct:ThingC"; } static constexpr size_t GetSize(const Info2&) { return 1; } static constexpr std::string_view GetSchema(const Info2&) { return "uint8 value"; } static ThingC Unpack(std::span data, const Info2&) { return ThingC{.x = data[0]}; } static void Pack(std::span data, const ThingC& value, const Info2&) { data[0] = value.x; } }; static_assert(wpi::StructSerializable); static_assert(!wpi::StructSerializable); static_assert(!wpi::StructSerializable); static_assert(wpi::StructSerializable); static_assert(!wpi::StructSerializable); static_assert(wpi::StructSerializable); static_assert(wpi::StructSerializable); static_assert(wpi::StructSerializable); TEST(DataLogTest, SimpleInt) { std::vector data; { wpi::log::DataLog log{ [&](auto out) { data.insert(data.end(), out.begin(), out.end()); }}; int entry = log.Start("test", "int64"); log.AppendInteger(entry, 1, 0); } ASSERT_EQ(data.size(), 66u); } TEST(DataLogTest, StructA) { wpi::log::DataLog log{[](auto) {}}; [[maybe_unused]] wpi::log::StructLogEntry entry0; wpi::log::StructLogEntry entry{log, "a", 5}; entry.Append(ThingA{}); entry.Append(ThingA{}, 7); } TEST(DataLogTest, StructArrayA) { wpi::log::DataLog log{[](auto) {}}; [[maybe_unused]] wpi::log::StructArrayLogEntry entry0; wpi::log::StructArrayLogEntry entry{log, "a", 5}; entry.Append({{ThingA{}, ThingA{}}}); entry.Append({{ThingA{}, ThingA{}}}, 7); } TEST(DataLogTest, StructFixedArrayA) { wpi::log::DataLog log{[](auto) {}}; [[maybe_unused]] wpi::log::StructArrayLogEntry> entry0; wpi::log::StructLogEntry> entry{log, "a", 5}; std::array arr; entry.Append(arr); entry.Append(arr, 7); } TEST(DataLogTest, StructB) { wpi::log::DataLog log{[](auto) {}}; Info1 info; [[maybe_unused]] wpi::log::StructLogEntry entry0; wpi::log::StructLogEntry entry{log, "b", info, 5}; entry.Append(ThingB{}); entry.Append(ThingB{}, 7); } TEST(DataLogTest, StructArrayB) { wpi::log::DataLog log{[](auto) {}}; Info1 info; [[maybe_unused]] wpi::log::StructArrayLogEntry entry0; wpi::log::StructArrayLogEntry entry{log, "a", info, 5}; entry.Append({{ThingB{}, ThingB{}}}); entry.Append({{ThingB{}, ThingB{}}}, 7); } TEST(DataLogTest, StructFixedArrayB) { wpi::log::DataLog log{[](auto) {}}; Info1 info; wpi::log::StructLogEntry, Info1> entry{log, "a", info, 5}; std::array arr; entry.Append(arr); entry.Append(arr, 7); } TEST(DataLogTest, StructC) { wpi::log::DataLog log{[](auto) {}}; { wpi::log::StructLogEntry entry{log, "c", 5}; entry.Append(ThingC{}); entry.Append(ThingC{}, 7); } { Info1 info; wpi::log::StructLogEntry entry{log, "c1", info, 5}; entry.Append(ThingC{}); entry.Append(ThingC{}, 7); } { Info2 info; wpi::log::StructLogEntry entry{log, "c2", info, 5}; entry.Append(ThingC{}); entry.Append(ThingC{}, 7); } } TEST(DataLogTest, StructArrayC) { wpi::log::DataLog log{[](auto) {}}; { wpi::log::StructArrayLogEntry entry{log, "c", 5}; entry.Append({{ThingC{}, ThingC{}}}); entry.Append({{ThingC{}, ThingC{}}}, 7); } { Info1 info; wpi::log::StructArrayLogEntry entry{log, "c1", info, 5}; entry.Append({{ThingC{}, ThingC{}}}); entry.Append({{ThingC{}, ThingC{}}}, 7); } { Info2 info; wpi::log::StructArrayLogEntry entry{log, "c2", info, 5}; entry.Append({{ThingC{}, ThingC{}}}); entry.Append({{ThingC{}, ThingC{}}}, 7); } } TEST(DataLogTest, StructFixedArrayC) { wpi::log::DataLog log{[](auto) {}}; std::array arr; { wpi::log::StructLogEntry> entry{log, "c", 5}; entry.Append(arr); entry.Append(arr, 7); } { Info1 info; wpi::log::StructLogEntry, Info1> entry{log, "c1", info, 5}; entry.Append(arr); entry.Append(arr, 7); } { Info2 info; wpi::log::StructLogEntry, Info2> entry{log, "c2", info, 5}; entry.Append(arr); entry.Append(arr, 7); } }