LibMultiSense
LibMultiSense Documentation
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 
46 using namespace multisense::legacy;
47 
48 TEST(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 
59 TEST(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 
66 TEST(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 
73 TEST(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 
80 TEST(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 
87 TEST(header_valid, invalid)
88 {
89  std::vector<uint8_t> data(50, 0);
90 
91  ASSERT_FALSE(header_valid(data));
92 }
93 
94 TEST(header_valid, valid)
95 {
96  using namespace crl::multisense::details;
97 
98  wire::SysDeviceInfo info{};
99 
100  auto serialized = serialize(info, 10, 9000);
101 
102  ASSERT_TRUE(header_valid(serialized));
103 }
104 
105 TEST(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 
118 TEST(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 
125 TEST(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 
141 TEST(seralize_deseralize, 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 
165 TEST(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 
186 TEST(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 
206 TEST(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 
230 TEST(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 
252 TEST(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 
287 TEST(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 
315 TEST(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 
338 TEST(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 
359 TEST(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 
395 TEST(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 
415 TEST(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 
444 TEST(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 }
crl::multisense::details
Definition: BufferStream.hh:53
TEST
TEST(unwrap_sequence_id, null)
Definition: message_test.cc:48
crl::multisense::details::wire::SysDeviceInfo
Definition: SysDeviceInfoMessage.hh:69
crl::multisense::details::wire::SysDeviceInfo::name
std::string name
Definition: SysDeviceInfoMessage.hh:135
SysDeviceInfoMessage.hh
crl::multisense::details::wire::Header
Header
Definition: Protocol.hh:128