blob: d7b35b605c54f7d7f1fec6f22266cb3b0f40f505 [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
Brian Silvermanc64372e2019-02-17 18:07:40 -0800129// Tests parsing a few packets, one byte at a time.
130TEST(CobsPacketizerTest, BasicSingleByte) {
131 CobsPacketizer<5> packetizer;
132
133 ASSERT_TRUE(packetizer.received_packet().empty());
134 packetizer.ParseData(std::array<char, 1>{{1}});
135 ASSERT_TRUE(packetizer.received_packet().empty());
136 packetizer.ParseData(std::array<char, 1>{{2}});
137 ASSERT_TRUE(packetizer.received_packet().empty());
138 packetizer.ParseData(std::array<char, 1>{{3}});
139 ASSERT_TRUE(packetizer.received_packet().empty());
140 packetizer.ParseData(std::array<char, 1>{{0}});
141 ASSERT_FALSE(packetizer.received_packet().empty());
142 EXPECT_EQ(gsl::span<const char>(std::array<char, 3>{{1, 2, 3}}),
143 packetizer.received_packet());
144 packetizer.clear_received_packet();
145 ASSERT_TRUE(packetizer.received_packet().empty());
146
147 ASSERT_TRUE(packetizer.received_packet().empty());
148 packetizer.ParseData(std::array<char, 1>{{5}});
149 ASSERT_TRUE(packetizer.received_packet().empty());
150 packetizer.ParseData(std::array<char, 1>{{0}});
151 ASSERT_FALSE(packetizer.received_packet().empty());
152 EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
153 packetizer.received_packet());
154
155 ASSERT_FALSE(packetizer.received_packet().empty());
156 packetizer.ParseData(std::array<char, 1>{{9}});
157 ASSERT_FALSE(packetizer.received_packet().empty());
158 EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
159 packetizer.received_packet());
160 packetizer.ParseData(std::array<char, 1>{{7}});
161 ASSERT_FALSE(packetizer.received_packet().empty());
162 EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
163 packetizer.received_packet());
164 packetizer.ParseData(std::array<char, 1>{{0}});
165 ASSERT_FALSE(packetizer.received_packet().empty());
166 EXPECT_EQ(gsl::span<const char>(std::array<char, 2>{{9, 7}}),
167 packetizer.received_packet());
168}
169
170// Tests parsing a few packets, one span per packet.
171TEST(CobsPacketizerTest, BasicSinglePacket) {
172 CobsPacketizer<5> packetizer;
173
174 ASSERT_TRUE(packetizer.received_packet().empty());
175 packetizer.ParseData(std::array<char, 3>{{1, 2, 3}});
176 ASSERT_TRUE(packetizer.received_packet().empty());
177 packetizer.ParseData(std::array<char, 1>{{0}});
178 ASSERT_FALSE(packetizer.received_packet().empty());
179 EXPECT_EQ(gsl::span<const char>(std::array<char, 3>{{1, 2, 3}}),
180 packetizer.received_packet());
181 packetizer.clear_received_packet();
182 ASSERT_TRUE(packetizer.received_packet().empty());
183
184 ASSERT_TRUE(packetizer.received_packet().empty());
185 packetizer.ParseData(std::array<char, 1>{{5}});
186 ASSERT_TRUE(packetizer.received_packet().empty());
187 packetizer.ParseData(std::array<char, 1>{{0}});
188 ASSERT_FALSE(packetizer.received_packet().empty());
189 EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
190 packetizer.received_packet());
191
192 ASSERT_FALSE(packetizer.received_packet().empty());
193 packetizer.ParseData(std::array<char, 2>{{9, 7}});
194 ASSERT_FALSE(packetizer.received_packet().empty());
195 EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
196 packetizer.received_packet());
197 packetizer.ParseData(std::array<char, 1>{{0}});
198 ASSERT_FALSE(packetizer.received_packet().empty());
199 EXPECT_EQ(gsl::span<const char>(std::array<char, 2>{{9, 7}}),
200 packetizer.received_packet());
201}
202
203// Tests parsing a few packets, one span per packet including its terminator.
204TEST(CobsPacketizerTest, BasicSinglePacketWithTerminator) {
205 CobsPacketizer<5> packetizer;
206
207 ASSERT_TRUE(packetizer.received_packet().empty());
208 packetizer.ParseData(std::array<char, 4>{{1, 2, 3, 0}});
209 ASSERT_FALSE(packetizer.received_packet().empty());
210 EXPECT_EQ(gsl::span<const char>(std::array<char, 3>{{1, 2, 3}}),
211 packetizer.received_packet());
212 packetizer.clear_received_packet();
213 ASSERT_TRUE(packetizer.received_packet().empty());
214
215 ASSERT_TRUE(packetizer.received_packet().empty());
216 packetizer.ParseData(std::array<char, 2>{{5, 0}});
217 ASSERT_FALSE(packetizer.received_packet().empty());
218 EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
219 packetizer.received_packet());
220
221 ASSERT_FALSE(packetizer.received_packet().empty());
222 packetizer.ParseData(std::array<char, 3>{{9, 7, 0}});
223 ASSERT_FALSE(packetizer.received_packet().empty());
224 EXPECT_EQ(gsl::span<const char>(std::array<char, 2>{{9, 7}}),
225 packetizer.received_packet());
226}
227
228// Tests parsing a packet in the same span as the previous terminator.
229TEST(CobsPacketizerTest, OverlappingEnd) {
230 CobsPacketizer<5> packetizer;
231
232 ASSERT_TRUE(packetizer.received_packet().empty());
233 packetizer.ParseData(std::array<char, 3>{{1, 2, 3}});
234 ASSERT_TRUE(packetizer.received_packet().empty());
235
236 ASSERT_TRUE(packetizer.received_packet().empty());
237 packetizer.ParseData(std::array<char, 2>{{0, 5}});
238 ASSERT_FALSE(packetizer.received_packet().empty());
239 EXPECT_EQ(gsl::span<const char>(std::array<char, 3>{{1, 2, 3}}),
240 packetizer.received_packet());
241 packetizer.clear_received_packet();
242 ASSERT_TRUE(packetizer.received_packet().empty());
243 packetizer.ParseData(std::array<char, 1>{{0}});
244 ASSERT_FALSE(packetizer.received_packet().empty());
245 EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
246 packetizer.received_packet());
247}
248
249// Tests parsing a packet in the same span as the previous terminator, including
250// its terminator (so we skip the first packet).
251TEST(CobsPacketizerTest, OverlappingTwoEnds) {
252 CobsPacketizer<5> packetizer;
253
254 ASSERT_TRUE(packetizer.received_packet().empty());
255 packetizer.ParseData(std::array<char, 3>{{1, 2, 3}});
256 ASSERT_TRUE(packetizer.received_packet().empty());
257
258 ASSERT_TRUE(packetizer.received_packet().empty());
259 packetizer.ParseData(std::array<char, 3>{{0, 5, 0}});
260 ASSERT_FALSE(packetizer.received_packet().empty());
261 // We skip the {{1, 2, 3}} packet (arbitrarily; either that packet or this one
262 // has to be skipped).
263 EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{5}}),
264 packetizer.received_packet());
265}
266
267// Tests parsing a packet in the same span as the previous terminator, including
268// its terminator (so we skip the first packet), and then starting another new
269// packet.
270TEST(CobsPacketizerTest, OverlappingTwoEndsAndPartial) {
271 CobsPacketizer<5> packetizer;
272
273 ASSERT_TRUE(packetizer.received_packet().empty());
274 packetizer.ParseData(std::array<char, 3>{{1, 2, 3}});
275 ASSERT_TRUE(packetizer.received_packet().empty());
276
277 ASSERT_TRUE(packetizer.received_packet().empty());
278 packetizer.ParseData(std::array<char, 4>{{0, 5, 0, 8}});
279 ASSERT_FALSE(packetizer.received_packet().empty());
280 // We skip the {{5}} packet (arbitrarily; either that packet or this one has
281 // to be skipped).
282 EXPECT_EQ(gsl::span<const char>(std::array<char, 3>{{1, 2, 3}}),
283 packetizer.received_packet());
284
285 packetizer.ParseData(std::array<char, 1>{{0}});
286 ASSERT_FALSE(packetizer.received_packet().empty());
287 EXPECT_EQ(gsl::span<const char>(std::array<char, 1>{{8}}),
288 packetizer.received_packet());
289}
290
Brian Silverman41709732019-02-09 20:53:08 -0800291} // namespace jevois
292} // namespace frc971