| #include "y2019/jevois/cobs.h" |
| |
| #include "aos/testing/test_logging.h" |
| #include "gtest/gtest.h" |
| #include "third_party/GSL/include/gsl/gsl" |
| |
| namespace frc971 { |
| namespace jevois { |
| |
| // Tests the size conversions for some known, simple values. |
| TEST(CobsMaxEncodedSizeTest, Simple) { |
| EXPECT_EQ(0u, CobsMaxEncodedSize(0)); |
| EXPECT_EQ(2u, CobsMaxEncodedSize(1)); |
| EXPECT_EQ(3u, CobsMaxEncodedSize(2)); |
| |
| EXPECT_EQ(254u, CobsMaxEncodedSize(253)); |
| EXPECT_EQ(255u, CobsMaxEncodedSize(254)); |
| EXPECT_EQ(257u, CobsMaxEncodedSize(255)); |
| } |
| |
| class CobsTest : public ::testing::Test { |
| public: |
| CobsTest() { aos::testing::EnableTestLogging(); } |
| |
| template <size_t min_buffer_size = 0, size_t number_elements> |
| void EncodeAndDecode(const char (&input_data)[number_elements]) { |
| static constexpr size_t input_size = |
| (min_buffer_size > number_elements) ? min_buffer_size : number_elements; |
| EncodeAndDecode<input_size>(gsl::span<const char>(input_data)); |
| } |
| |
| template <size_t max_decoded_size> |
| void EncodeAndDecode(const gsl::span<const char> decoded_input) { |
| std::array<char, CobsMaxEncodedSize(max_decoded_size)> encoded_buffer; |
| const auto encoded = |
| CobsEncode<max_decoded_size>(decoded_input, &encoded_buffer); |
| ASSERT_LE(encoded.size(), encoded_buffer.size()); |
| ASSERT_EQ(encoded.data(), &encoded_buffer.front()); |
| |
| std::array<char, max_decoded_size> decoded_buffer; |
| const auto decoded = CobsDecode<max_decoded_size>(encoded, &decoded_buffer); |
| ASSERT_LE(decoded.size(), decoded_buffer.size()); |
| ASSERT_EQ(decoded.data(), &decoded_buffer.front()); |
| ASSERT_EQ(decoded.size(), decoded_input.size()); |
| for (int i = 0; i < decoded.size(); ++i) { |
| EXPECT_EQ(decoded[i], decoded_input[i]); |
| } |
| } |
| }; |
| |
| // Tests various small buffers. |
| TEST_F(CobsTest, Small) { |
| EncodeAndDecode<1>(std::array<char, 0>{}); |
| EncodeAndDecode<5>(std::array<char, 0>{}); |
| { |
| const char data[] = {0}; |
| EncodeAndDecode(data); |
| } |
| { |
| const char data[] = {1}; |
| EncodeAndDecode(data); |
| } |
| { |
| const char data[] = {static_cast<char>(254)}; |
| EncodeAndDecode(data); |
| } |
| { |
| const char data[] = {static_cast<char>(255)}; |
| EncodeAndDecode(data); |
| } |
| { |
| const char data[] = {0, 1}; |
| EncodeAndDecode(data); |
| } |
| { |
| const char data[] = {0, static_cast<char>(254)}; |
| EncodeAndDecode(data); |
| } |
| { |
| const char data[] = {0, static_cast<char>(255)}; |
| EncodeAndDecode(data); |
| } |
| { |
| const char data[] = {0, 1, static_cast<char>(254)}; |
| EncodeAndDecode(data); |
| } |
| { |
| const char data[] = {0, 1, static_cast<char>(255)}; |
| EncodeAndDecode(data); |
| } |
| { |
| const char data[] = {static_cast<char>(254), 1}; |
| EncodeAndDecode(data); |
| } |
| { |
| const char data[] = {static_cast<char>(255), 1}; |
| EncodeAndDecode(data); |
| } |
| { |
| const char data[] = {static_cast<char>(254), 0}; |
| EncodeAndDecode(data); |
| } |
| { |
| const char data[] = {static_cast<char>(255), 0}; |
| EncodeAndDecode(data); |
| } |
| } |
| |
| // Tests encoding arrays with approximately one full chunk. This exposes some |
| // corner cases in the binary format. |
| TEST_F(CobsTest, AroundOneChunk) { |
| char data[256]; |
| for (size_t i = 0; i < sizeof(data); ++i) { |
| data[i] = (i * 7) & 0xFF; |
| } |
| const gsl::span<char> data_span = data; |
| for (int i = 253; i <= 256; ++i) { |
| EncodeAndDecode<256>(data_span.subspan(0, i)); |
| } |
| for (int i = 253; i <= 255; ++i) { |
| EncodeAndDecode<255>(data_span.subspan(0, i)); |
| } |
| for (int i = 253; i <= 254; ++i) { |
| EncodeAndDecode<254>(data_span.subspan(0, i)); |
| } |
| EncodeAndDecode<253>(data_span.subspan(0, 253)); |
| } |
| |
| } // namespace jevois |
| } // namespace frc971 |