// 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 #include "wpi/DataLogWriter.h" #include "wpi/Logger.h" #include "wpi/raw_ostream.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); class DataLogTest : public ::testing::Test { public: wpi::Logger msglog; std::vector data; wpi::log::DataLogWriter log{msglog, std::make_unique(data)}; }; TEST_F(DataLogTest, SimpleInt) { int entry = log.Start("test", "int64"); log.AppendInteger(entry, 1, 0); log.Flush(); ASSERT_EQ(data.size(), 66u); } TEST_F(DataLogTest, StructA) { [[maybe_unused]] wpi::log::StructLogEntry entry0; wpi::log::StructLogEntry entry{log, "a", 5}; entry.Append(ThingA{}); entry.Append(ThingA{}, 7); } TEST_F(DataLogTest, StructArrayA) { [[maybe_unused]] wpi::log::StructArrayLogEntry entry0; wpi::log::StructArrayLogEntry entry{log, "a", 5}; entry.Append({{ThingA{}, ThingA{}}}); entry.Append({{ThingA{}, ThingA{}}}, 7); } TEST_F(DataLogTest, StructFixedArrayA) { [[maybe_unused]] wpi::log::StructArrayLogEntry> entry0; wpi::log::StructLogEntry> entry{log, "a", 5}; std::array arr; entry.Append(arr); entry.Append(arr, 7); } TEST_F(DataLogTest, StructB) { Info1 info; [[maybe_unused]] wpi::log::StructLogEntry entry0; wpi::log::StructLogEntry entry{log, "b", info, 5}; entry.Append(ThingB{}); entry.Append(ThingB{}, 7); } TEST_F(DataLogTest, StructArrayB) { 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_F(DataLogTest, StructFixedArrayB) { Info1 info; wpi::log::StructLogEntry, Info1> entry{log, "a", info, 5}; std::array arr; entry.Append(arr); entry.Append(arr, 7); } TEST_F(DataLogTest, StructC) { { 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_F(DataLogTest, StructArrayC) { { 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_F(DataLogTest, StructFixedArrayC) { 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); } }