blob: 320bde3c579483f6eb1263b3eb11fcea2561bd73 [file] [log] [blame]
Brian Silverman41709732019-02-09 20:53:08 -08001#include "y2019/jevois/cobs.h"
2
3#include "aos/testing/test_logging.h"
4#include "gtest/gtest.h"
5#include "third_party/GSL/include/gsl/gsl"
6
7namespace frc971 {
8namespace jevois {
9
10// Tests the size conversions for some known, simple values.
11TEST(CobsMaxEncodedSizeTest, Simple) {
12 EXPECT_EQ(0u, CobsMaxEncodedSize(0));
13 EXPECT_EQ(2u, CobsMaxEncodedSize(1));
14 EXPECT_EQ(3u, CobsMaxEncodedSize(2));
15
16 EXPECT_EQ(254u, CobsMaxEncodedSize(253));
17 EXPECT_EQ(255u, CobsMaxEncodedSize(254));
18 EXPECT_EQ(257u, CobsMaxEncodedSize(255));
19}
20
21class CobsTest : public ::testing::Test {
22 public:
23 CobsTest() { aos::testing::EnableTestLogging(); }
24
25 template <size_t min_buffer_size = 0, size_t number_elements>
26 void EncodeAndDecode(const char (&input_data)[number_elements]) {
27 static constexpr size_t input_size =
28 (min_buffer_size > number_elements) ? min_buffer_size : number_elements;
29 EncodeAndDecode<input_size>(gsl::span<const char>(input_data));
30 }
31
32 template <size_t max_decoded_size>
33 void EncodeAndDecode(const gsl::span<const char> decoded_input) {
34 std::array<char, CobsMaxEncodedSize(max_decoded_size)> encoded_buffer;
35 const auto encoded =
36 CobsEncode<max_decoded_size>(decoded_input, &encoded_buffer);
37 ASSERT_LE(encoded.size(), encoded_buffer.size());
38 ASSERT_EQ(encoded.data(), &encoded_buffer.front());
39
40 std::array<char, max_decoded_size> decoded_buffer;
41 const auto decoded = CobsDecode<max_decoded_size>(encoded, &decoded_buffer);
42 ASSERT_LE(decoded.size(), decoded_buffer.size());
43 ASSERT_EQ(decoded.data(), &decoded_buffer.front());
44 ASSERT_EQ(decoded.size(), decoded_input.size());
45 for (int i = 0; i < decoded.size(); ++i) {
46 EXPECT_EQ(decoded[i], decoded_input[i]);
47 }
48 }
49};
50
51// Tests various small buffers.
52TEST_F(CobsTest, Small) {
53 EncodeAndDecode<1>(std::array<char, 0>{});
54 EncodeAndDecode<5>(std::array<char, 0>{});
55 {
56 const char data[] = {0};
57 EncodeAndDecode(data);
58 }
59 {
60 const char data[] = {1};
61 EncodeAndDecode(data);
62 }
63 {
64 const char data[] = {static_cast<char>(254)};
65 EncodeAndDecode(data);
66 }
67 {
68 const char data[] = {static_cast<char>(255)};
69 EncodeAndDecode(data);
70 }
71 {
72 const char data[] = {0, 1};
73 EncodeAndDecode(data);
74 }
75 {
76 const char data[] = {0, static_cast<char>(254)};
77 EncodeAndDecode(data);
78 }
79 {
80 const char data[] = {0, static_cast<char>(255)};
81 EncodeAndDecode(data);
82 }
83 {
84 const char data[] = {0, 1, static_cast<char>(254)};
85 EncodeAndDecode(data);
86 }
87 {
88 const char data[] = {0, 1, static_cast<char>(255)};
89 EncodeAndDecode(data);
90 }
91 {
92 const char data[] = {static_cast<char>(254), 1};
93 EncodeAndDecode(data);
94 }
95 {
96 const char data[] = {static_cast<char>(255), 1};
97 EncodeAndDecode(data);
98 }
99 {
100 const char data[] = {static_cast<char>(254), 0};
101 EncodeAndDecode(data);
102 }
103 {
104 const char data[] = {static_cast<char>(255), 0};
105 EncodeAndDecode(data);
106 }
107}
108
109// Tests encoding arrays with approximately one full chunk. This exposes some
110// corner cases in the binary format.
111TEST_F(CobsTest, AroundOneChunk) {
112 char data[256];
113 for (size_t i = 0; i < sizeof(data); ++i) {
114 data[i] = (i * 7) & 0xFF;
115 }
116 const gsl::span<char> data_span = data;
117 for (int i = 253; i <= 256; ++i) {
118 EncodeAndDecode<256>(data_span.subspan(0, i));
119 }
120 for (int i = 253; i <= 255; ++i) {
121 EncodeAndDecode<255>(data_span.subspan(0, i));
122 }
123 for (int i = 253; i <= 254; ++i) {
124 EncodeAndDecode<254>(data_span.subspan(0, i));
125 }
126 EncodeAndDecode<253>(data_span.subspan(0, 253));
127}
128
129} // namespace jevois
130} // namespace frc971