LibMultiSense
LibMultiSense Documentation
Loading...
Searching...
No Matches
message_test.cc
Go to the documentation of this file.
1
37#include <chrono>
38#include <optional>
39
40#include <gtest/gtest.h>
41
42#include <details/legacy/message.hh>
43
45
46using namespace multisense::legacy;
47
48TEST(unwrap_sequence_id, null)
49{
50 auto full_sequence_id = unwrap_sequence_id(0, -1, 0);
51
52 EXPECT_EQ(full_sequence_id, 0);
53
54 full_sequence_id = unwrap_sequence_id(0, 0, 0);
55
56 EXPECT_EQ(full_sequence_id, 0);
57}
58
59TEST(unwrap_sequence_id, no_increment)
60{
61 const auto full_sequence_id = unwrap_sequence_id(1, 1, 0);
62
63 EXPECT_EQ(full_sequence_id, 0);
64}
65
66TEST(unwrap_sequence_id, increment)
67{
68 const auto full_sequence_id = unwrap_sequence_id(1, 0, 0);
69
70 EXPECT_EQ(full_sequence_id, 1);
71}
72
73TEST(unwrap_sequence_id, rollover)
74{
75 const auto full_sequence_id = unwrap_sequence_id(0, 65535, 0);
76
77 EXPECT_EQ(full_sequence_id, 1);
78}
79
80TEST(unwrap_sequence_id, rollover_unique)
81{
82 const auto full_sequence_id = unwrap_sequence_id(0, 65535, 123456);
83
84 EXPECT_EQ(full_sequence_id, 123457);
85}
86
87TEST(header_valid, invalid)
88{
89 std::vector<uint8_t> data(50, 0);
90
91 ASSERT_FALSE(header_valid(data));
92}
93
94TEST(header_valid, valid)
95{
96 using namespace crl::multisense::details;
97
99
100 auto serialized = serialize(info, 10, 9000);
101
102 ASSERT_TRUE(header_valid(serialized));
103}
104
105TEST(get_message_type, basic)
106{
107 using namespace crl::multisense::details;
108
109 wire::SysDeviceInfo info{};
110
111 auto serialized = serialize(info, 10, 9000);
112
113 const auto type = get_message_type(serialized);
114
115 ASSERT_EQ(type, wire::SysDeviceInfo::ID);
116}
117
118TEST(get_full_message_size, invalid)
119{
120 const auto full_size = get_full_message_size({});
121
122 ASSERT_FALSE(static_cast<bool>(full_size));
123}
124
125TEST(get_full_message_size, valid)
126{
127 using namespace crl::multisense::details;
128
129 wire::SysDeviceInfo info{};
130
131 const auto serialized = serialize(info, 10, 9000);
132
133 const auto full_size = get_full_message_size(serialized);
134
135 ASSERT_TRUE(static_cast<bool>(full_size));
136
137 ASSERT_GT(full_size.value(), 20);
138 ASSERT_LT(full_size.value(), 200);
139}
140
141TEST(serialize_deserialize, roundtrip)
142{
143 using namespace crl::multisense::details;
144
145 wire::SysDeviceInfo info{};
146 info.name = "test";
147 info.numberOfPcbs = 0;
148 info.motorName = "bar";
149
150 auto serialized = serialize(info, 10, 9000);
151
152 //
153 // Remove the wire::Header we added for the MultiSense
154 //
155 serialized.erase(std::begin(serialized), std::begin(serialized) + sizeof(wire::Header));
156
157
158 const auto round_trip = deserialize<wire::SysDeviceInfo>(serialized);
159
160 ASSERT_EQ(round_trip.name, info.name);
161 ASSERT_EQ(round_trip.numberOfPcbs, info.numberOfPcbs);
162 ASSERT_EQ(round_trip.motorName, info.motorName);
163}
164
165TEST(MessageAssembler, process_notify_wait_for)
166{
167 using namespace crl::multisense::details;
168 using namespace std::chrono_literals;
169
170 wire::SysDeviceInfo info{};
171 info.name = "test";
172 auto serialized = serialize(info, 10, 9000);
173
174 MessageAssembler assembler{std::make_shared<BufferPool>(BufferPoolConfig{10, 9000, 2, 100000})};
175 auto registration = assembler.register_message(wire::SysDeviceInfo::ID);
176 ASSERT_TRUE(assembler.process_packet(serialized));
177
178 const auto output = registration->wait<wire::SysDeviceInfo>(std::make_optional(500ms));
179
180 ASSERT_TRUE(static_cast<bool>(output));
181
182 ASSERT_EQ(output->name, info.name);
183}
184
185
186TEST(MessageAssembler, process_notify_wait)
187{
188 using namespace crl::multisense::details;
189 using namespace std::chrono_literals;
190
191 wire::SysDeviceInfo info{};
192 info.name = "test_wait";
193 auto serialized = serialize(info, 10, 9000);
194
195 MessageAssembler assembler{std::make_shared<BufferPool>(BufferPoolConfig{10, 9000, 2, 100000})};
196 auto registration = assembler.register_message(wire::SysDeviceInfo::ID);
197 ASSERT_TRUE(assembler.process_packet(serialized));
198
199 const auto output = registration->wait<wire::SysDeviceInfo>();
200
201 ASSERT_TRUE(static_cast<bool>(output));
202
203 ASSERT_EQ(output->name, info.name);
204}
205
206TEST(MessageAssembler, process_notify_wait_for_multi_registrations)
207{
208 using namespace crl::multisense::details;
209 using namespace std::chrono_literals;
210
211 wire::SysDeviceInfo info{};
212 info.name = "test";
213 auto serialized = serialize(info, 10, 9000);
214
215 MessageAssembler assembler{std::make_shared<BufferPool>(BufferPoolConfig{10, 9000, 2, 100000})};
216 auto registration0 = assembler.register_message(wire::SysDeviceInfo::ID);
217 auto registration1 = assembler.register_message(wire::SysDeviceInfo::ID);
218 ASSERT_TRUE(assembler.process_packet(serialized));
219
220 const auto output0 = registration0->wait<wire::SysDeviceInfo>(std::make_optional(500ms));
221 const auto output1 = registration1->wait<wire::SysDeviceInfo>(std::make_optional(500ms));
222
223 ASSERT_TRUE(static_cast<bool>(output0));
224 ASSERT_TRUE(static_cast<bool>(output1));
225
226 ASSERT_EQ(output0->name, info.name);
227 ASSERT_EQ(output1->name, info.name);
228}
229
230TEST(MessageAssembler, process_notify_remove_registration)
231{
232 using namespace crl::multisense::details;
233 using namespace std::chrono_literals;
234
235 wire::SysDeviceInfo info{};
236 info.name = "test";
237 auto serialized = serialize(info, 10, 9000);
238
239 MessageAssembler assembler{std::make_shared<BufferPool>(BufferPoolConfig{10, 9000, 2, 100000})};
240 auto registration = assembler.register_message(wire::SysDeviceInfo::ID);
241 assembler.remove_registration(wire::SysDeviceInfo::ID);
242 ASSERT_TRUE(assembler.process_packet(serialized));
243
244 //
245 // Since we don't have an active registration we should not get a valid message
246 //
247 const auto output = registration->wait<wire::SysDeviceInfo>(std::make_optional(500ms));
248
249 ASSERT_FALSE(static_cast<bool>(output));
250}
251
252TEST(MessageAssembler, process_callback)
253{
254 using namespace crl::multisense::details;
255 using namespace std::chrono_literals;
256
257 wire::SysDeviceInfo info{};
258 info.name = "test_callback";
259 auto serialized = serialize(info, 10, 9000);
260
261 //
262 // Our lambda should be called when the packet is processed
263 //
264 wire::SysDeviceInfo output;
265 MessageAssembler assembler{std::make_shared<BufferPool>(BufferPoolConfig{10, 9000, 2, 100000})};
266 assembler.register_callback(wire::SysDeviceInfo::ID,
267 [&output](const auto &data)
268 {
269 output = deserialize<wire::SysDeviceInfo>(*data);
270 });
271 ASSERT_TRUE(assembler.process_packet(serialized));
272
273 ASSERT_EQ(output.name, info.name);
274
275 //
276 // Remove our callback and make sure our output does not get updated
277 //
278 assembler.remove_callback(wire::SysDeviceInfo::ID);
279
280 info.name = "test_callback_new";
281 serialized = serialize(info, 11, 9000);
282 ASSERT_TRUE(assembler.process_packet(serialized));
283
284 ASSERT_NE(output.name, info.name);
285}
286
287TEST(MessageAssembler, use_all_buffers)
288{
289 using namespace crl::multisense::details;
290 using namespace std::chrono_literals;
291
292 wire::SysDeviceInfo info{};
293 info.name = "test_callback";
294 auto serialized = serialize(info, 10, 9000);
295
296 //
297 // Our lambda should be called when the packet is processed
298 //
299 std::vector<std::shared_ptr<const std::vector<uint8_t>>> outputs;
300 MessageAssembler assembler{std::make_shared<BufferPool>(BufferPoolConfig{2, 9000, 1, 100000})};
301 assembler.register_callback(wire::SysDeviceInfo::ID,
302 [&outputs](const auto data)
303 {
304 outputs.push_back(data);
305 });
306 ASSERT_TRUE(assembler.process_packet(serialized));
307 ASSERT_TRUE(assembler.process_packet(serialized));
308
309 //
310 // At this point we should be out of our small buffers
311 //
312 ASSERT_FALSE(assembler.process_packet(serialized));
313}
314
315TEST(MessageAssembler, invalid_message)
316{
317 using namespace crl::multisense::details;
318 using namespace std::chrono_literals;
319
320 wire::SysDeviceInfo info{};
321 info.name = "test_callback";
322 auto serialized = serialize(info, 10, 9000);
323
324 //
325 // Mess up our message
326 //
327 serialized[0] = 123;
328
329 MessageAssembler assembler{std::make_shared<BufferPool>(BufferPoolConfig{2, 9000, 1, 100000})};
330
331 //
332 // Processing should return false
333 //
334 ASSERT_FALSE(assembler.process_packet(serialized));
335 ASSERT_FALSE(assembler.process_packet(std::vector<uint8_t>{}));
336}
337
338TEST(MessageAssembler, only_large_buffers)
339{
340 using namespace crl::multisense::details;
341 using namespace std::chrono_literals;
342
343 wire::SysDeviceInfo info{};
344 info.name = "test_callback";
345 auto serialized = serialize(info, 10, 9000);
346
347 MessageAssembler assembler{std::make_shared<BufferPool>(BufferPoolConfig{1, 1, 1, 100000})};
348 auto registration = assembler.register_message(wire::SysDeviceInfo::ID);
349
350 ASSERT_TRUE(assembler.process_packet(serialized));
351
352 const auto output = registration->wait<wire::SysDeviceInfo>(std::make_optional(500ms));
353
354 ASSERT_TRUE(static_cast<bool>(output));
355
356 ASSERT_EQ(output->name, info.name);
357}
358
359TEST(MessageAssembler, multi_large_packets)
360{
361 using namespace crl::multisense::details;
362 using namespace std::chrono_literals;
363
364 wire::SysDeviceInfo info{};
365 info.name = "test_callback";
366 auto serialized = serialize(info, 0, 9000);
367
368 //
369 // Update our message size to indicate our message is huge
370 //
371 auto sequence_id = reinterpret_cast<uint16_t*>(&serialized[8]);
372 auto message_length = reinterpret_cast<uint32_t*>(&serialized[10]);
373 *message_length = 10000;
374
375 MessageAssembler assembler{std::make_shared<BufferPool>(BufferPoolConfig{1, 1, 1, 100000})};
376 auto registration = assembler.register_message(wire::SysDeviceInfo::ID);
377
378 //
379 // We should be able to process the message, but we wont get a valid message since we messed with
380 // the message length. We should be internally dropping all these messages when a message with the
381 // next sequence id shows up
382 //
383 for (size_t i = 1 ; i < 100 ; ++i)
384 {
385 ASSERT_TRUE(assembler.process_packet(serialized));
386 {
387 const auto output = registration->wait<wire::SysDeviceInfo>(std::make_optional(1us));
388 ASSERT_FALSE(static_cast<bool>(output));
389 }
390
391 *sequence_id = i;
392 }
393}
394
395TEST(MessageAssembler, stats_valid_message)
396{
397 using namespace crl::multisense::details;
398 using namespace std::chrono_literals;
399
400 wire::SysDeviceInfo info{};
401 info.name = "test_callback";
402 auto serialized = serialize(info, 10, 9000);
403
404 MessageAssembler assembler{std::make_shared<BufferPool>(BufferPoolConfig{2, 9000, 1, 100000})};
405
406 ASSERT_TRUE(assembler.process_packet(serialized));
407
408 const auto stats = assembler.get_message_statistics();
409
410 ASSERT_EQ(stats.received_messages, 1);
411 ASSERT_EQ(stats.dropped_messages, 0);
412 ASSERT_EQ(stats.invalid_packets, 0);
413}
414
415TEST(MessageAssembler, stats_invalid_message)
416{
417 using namespace crl::multisense::details;
418 using namespace std::chrono_literals;
419
420 wire::SysDeviceInfo info{};
421 info.name = "test_callback";
422 auto serialized = serialize(info, 10, 9000);
423
424 //
425 // Mess up our message
426 //
427 serialized[0] = 123;
428
429 MessageAssembler assembler{std::make_shared<BufferPool>(BufferPoolConfig{2, 9000, 1, 100000})};
430
431 //
432 // Processing should return false
433 //
434 ASSERT_FALSE(assembler.process_packet(serialized));
435 ASSERT_FALSE(assembler.process_packet(std::vector<uint8_t>{}));
436
437 const auto stats = assembler.get_message_statistics();
438
439 ASSERT_EQ(stats.received_messages, 0);
440 ASSERT_EQ(stats.dropped_messages, 0);
441 ASSERT_EQ(stats.invalid_packets, 2);
442}
443
444TEST(MessageAssembler, stats_dropped_valid_message)
445{
446 using namespace crl::multisense::details;
447 using namespace std::chrono_literals;
448
449 wire::SysDeviceInfo info{};
450 info.name = "test_callback";
451 auto serialized = serialize(info, 10, 9000);
452
453 MessageAssembler assembler{std::make_shared<BufferPool>(BufferPoolConfig{2, 9000, 1, 100000})};
454
455 //
456 // Send in 3 messages. One valid, one of a very large size, one valid
457 //
458 ASSERT_TRUE(assembler.process_packet(serialized));
459
460 serialized = serialize(info, 11, 9000);
461 wire::Header& header = *(reinterpret_cast<wire::Header*>(serialized.data()));
462 header.messageLength = 100000;
463 ASSERT_TRUE(assembler.process_packet(serialized));
464
465 serialized = serialize(info, 12, 9000);
466 ASSERT_TRUE(assembler.process_packet(serialized));
467
468 const auto stats = assembler.get_message_statistics();
469
470 ASSERT_EQ(stats.received_messages, 2);
471 ASSERT_EQ(stats.dropped_messages, 1);
472 ASSERT_EQ(stats.invalid_packets, 0);
473}
This message contains general device information.
TEST(unwrap_sequence_id, null)