transfer_receiver.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #include <algorithm>
6 #include <gtest/gtest.h>
8 #include "../clock.hpp"
10 
11 /*
12  * Beware!
13  * The code you're about to look at desperately needs some cleaning.
14  */
15 
17 {
18  SET000 = 0,
19  SET001 = 1,
20  SET010 = 2,
21  SET011 = 3,
22  SET100 = 4,
23  SET101 = 5, // Illegal
24  SET110 = 6,
25  SET111 = 7 // Illegal
26 };
27 
29 {
31  enum { TARGET_NODE_ID = 126 };
32 
35 
39  { }
40 
42  uavcan::RxFrame operator()(uint8_t iface_index, const std::string& data, SotEotToggle set,
43  uint8_t transfer_id, uint64_t ts_monotonic, uint64_t ts_utc = 0)
44  {
45  const uavcan::NodeID dst_nid =
48 
50  dst_nid, transfer_id);
51 
52  frame.setStartOfTransfer((set & (1 << 2)) != 0);
53  frame.setEndOfTransfer((set & (1 << 1)) != 0);
54 
55  if ((set & (1 << 0)) != 0)
56  {
57  frame.flipToggle();
58  }
59 
60  EXPECT_EQ(data.length(),
61  frame.setPayload(reinterpret_cast<const uint8_t*>(data.c_str()), unsigned(data.length())));
62 
64  uavcan::UtcTime::fromUSec(ts_utc), iface_index);
65  //std::cout << "Generated frame: " << output.toString() << std::endl;
66 
67  return output;
68  }
69 };
70 
72 
73 
74 template <unsigned BufSize>
75 struct Context
76 {
78  uavcan::TransferReceiver receiver; // Must be default constructible and copyable
80 
81  Context() :
82  bufmgr(BufSize, pool)
83  { }
84 
86  {
87  // We need to destroy the receiver before its buffer manager
89  }
90 };
91 
92 
93 static bool matchBufferContent(const uavcan::ITransferBuffer* tbb, const std::string& content)
94 {
95  uint8_t data[1024];
96  std::fill(data, data + sizeof(data), 0);
97  if (content.length() > sizeof(data))
98  {
99  std::cerr << "matchBufferContent(): Content is too long" << std::endl;
100  std::exit(1);
101  }
102  tbb->read(0, data, unsigned(content.length()));
103  if (std::equal(content.begin(), content.end(), data))
104  {
105  return true;
106  }
107  std::cout << "Buffer content mismatch:"
108  << "\n\tExpected: " << content
109  << "\n\tActually: " << reinterpret_cast<const char*>(data)
110  << std::endl;
111  return false;
112 }
113 
114 
115 #define CHECK_NOT_COMPLETE(x) ASSERT_EQ(uavcan::TransferReceiver::ResultNotComplete, (x))
116 #define CHECK_COMPLETE(x) ASSERT_EQ(uavcan::TransferReceiver::ResultComplete, (x))
117 #define CHECK_SINGLE_FRAME(x) ASSERT_EQ(uavcan::TransferReceiver::ResultSingleFrame, (x))
118 
119 TEST(TransferReceiver, Basic)
120 {
122  Context<32> context;
123  RxFrameGenerator gen(789);
124  uavcan::TransferReceiver& rcv = context.receiver;
125  uavcan::TransferBufferManager& bufmgr = context.bufmgr;
127 
128  std::cout << "sizeof(TransferReceiver): " << sizeof(TransferReceiver) << std::endl;
129 
130  /*
131  * Empty
132  */
133  ASSERT_EQ(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
134  ASSERT_EQ(0, rcv.getLastTransferTimestampMonotonic().toUSec());
135 
136  /*
137  * Single frame transfer with zero ts, must be ignored
138  */
139  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "Foo", SET110, 0, 0), bk));
140  ASSERT_EQ(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
141  ASSERT_EQ(0, rcv.getLastTransferTimestampMonotonic().toUSec());
142 
143  /*
144  * Valid compound transfer
145  * Args: iface_index, data, set, transfer_id, ts_monotonic
146  */
147  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "\x34\x12" "34567", SET100, 0, 100), bk));
148  CHECK_COMPLETE( rcv.addFrame(gen(0, "foo", SET011, 0, 200), bk));
149 
150  ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567foo"));
151  ASSERT_EQ(0x1234, rcv.getLastTransferCrc());
152  ASSERT_EQ(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval()); // Not initialized yet
153  ASSERT_EQ(100, rcv.getLastTransferTimestampMonotonic().toUSec());
154 
155  /*
156  * Compound transfer mixed with invalid frames; buffer was not released explicitly
157  * Args: iface_index, data, set, transfer_id, ts_monotonic
158  */
159  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwe", SET100, 0, 300), bk)); // Previous TID, rejected
160  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "rty", SET100, 0, 300), bk)); // Previous TID, wrong iface
161  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "\x9a\x78" "34567", SET100, 1, 1000), bk));
162  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwertyu", SET100, 1, 1100), bk)); // Old toggle
163  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwertyu", SET000, 1, 1100), bk)); // Old toggle
164  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "abcdefg", SET001, 1, 1200), bk));
165  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "4567891", SET001, 2, 1300), bk)); // Next TID, but not SOT
166  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "", SET010, 1, 1300), bk)); // Wrong iface
167  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "", SET001, 1, 1300), bk)); // Unexpected toggle
168  CHECK_COMPLETE( rcv.addFrame(gen(0, "", SET010, 1, 1300), bk));
169 
170  ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567abcdefg"));
171  ASSERT_EQ(0x789A, rcv.getLastTransferCrc());
172  ASSERT_GE(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
173  ASSERT_LE(TransferReceiver::getMinTransferInterval(), rcv.getInterval());
174  ASSERT_EQ(1000, rcv.getLastTransferTimestampMonotonic().toUSec());
175  ASSERT_FALSE(rcv.isTimedOut(tsMono(1000)));
176  ASSERT_FALSE(rcv.isTimedOut(tsMono(5000)));
177  ASSERT_TRUE(rcv.isTimedOut(tsMono(60000000)));
178 
179  /*
180  * Single-frame transfers
181  * Args: iface_index, data, set, transfer_id, ts_monotonic
182  */
183  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwe", SET110, 1, 2000), bk)); // Previous TID
184  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwe", SET110, 2, 2100), bk)); // Wrong iface
185  CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "qwe", SET110, 2, 2200), bk));
186 
187  ASSERT_FALSE(bufmgr.access(gen.bufmgr_key)); // Buffer must be removed
188  ASSERT_GT(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
189  ASSERT_EQ(2200, rcv.getLastTransferTimestampMonotonic().toUSec());
190 
191  CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "", SET110, 3, 2500), bk));
192  ASSERT_EQ(2500, rcv.getLastTransferTimestampMonotonic().toUSec());
193 
194  CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "", SET110, 0, 3000), bk));
195  CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "", SET110, 1, 3100), bk));
196  CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "", SET110, 3, 3200), bk));
197  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "", SET110, 0, 3300), bk)); // Old TID, wrong iface
198  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "", SET110, 2, 3400), bk)); // Old TID, wrong iface
199  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "", SET110, 3, 3500), bk)); // Old TID, wrong iface
200  CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "", SET110, 4, 3600), bk));
201  ASSERT_EQ(3600, rcv.getLastTransferTimestampMonotonic().toUSec());
202 
203  std::cout << "Interval: " << rcv.getInterval().toString() << std::endl;
204 
205  /*
206  * Timeouts
207  */
208  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwe", SET110, 1, 5000), bk)); // Wrong iface - ignored
209  CHECK_SINGLE_FRAME(rcv.addFrame(gen(1, "qwe", SET110, 6, 1500000), bk)); // Accepted due to iface timeout
210  ASSERT_EQ(1500000, rcv.getLastTransferTimestampMonotonic().toUSec());
211 
212  std::cout << "Interval: " << rcv.getInterval().toString() << std::endl;
213 
214  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwe", SET110, 7, 1500100), bk)); // Ignored - old iface 0
215  CHECK_SINGLE_FRAME(rcv.addFrame(gen(1, "qwe", SET110, 7, 1500100), bk));
216  ASSERT_EQ(1500100, rcv.getLastTransferTimestampMonotonic().toUSec());
217 
218  std::cout << "Interval: " << rcv.getInterval().toString() << std::endl;
219 
220  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwe", SET110, 7, 1500100), bk)); // Old TID
221  CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "qwe", SET110, 7, 100000000), bk)); // Accepted - global timeout
222  ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec());
223 
224  std::cout << "Interval: " << rcv.getInterval().toString() << std::endl;
225 
226  CHECK_SINGLE_FRAME(rcv.addFrame(gen(0, "qwe", SET110, 8, 100000100), bk));
227  ASSERT_EQ(100000100, rcv.getLastTransferTimestampMonotonic().toUSec());
228 
229  std::cout << "Interval: " << rcv.getInterval().toString() << std::endl;
230 
231  ASSERT_TRUE(rcv.isTimedOut(tsMono(900000000)));
232  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "\x78\x56" "34567", SET100, 0, 900000000), bk)); // Global timeout
233  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "1234567", SET100, 0, 900000100), bk)); // Wrong iface
234  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwe", SET011, 0, 900000200), bk)); // Wrong iface
235  CHECK_COMPLETE( rcv.addFrame(gen(1, "qwe", SET011, 0, 900000200), bk));
236 
237  ASSERT_EQ(900000000, rcv.getLastTransferTimestampMonotonic().toUSec());
238  std::cout << "Interval: " << rcv.getInterval().toString() << std::endl;
239 
240  ASSERT_FALSE(rcv.isTimedOut(tsMono(1000)));
241  ASSERT_FALSE(rcv.isTimedOut(tsMono(900000300)));
242  ASSERT_TRUE(rcv.isTimedOut(tsMono(9990000000)));
243 
244  ASSERT_LT(TransferReceiver::getDefaultTransferInterval(), rcv.getInterval());
245  ASSERT_LE(TransferReceiver::getMinTransferInterval(), rcv.getInterval());
246  ASSERT_GE(TransferReceiver::getMaxTransferInterval(), rcv.getInterval());
247  ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567qwe"));
248  ASSERT_EQ(0x5678, rcv.getLastTransferCrc());
249 
250  /*
251  * Destruction
252  */
253  ASSERT_TRUE(bufmgr.access(gen.bufmgr_key));
254  context.receiver.~TransferReceiver(); // TransferReceiver does not own the buffer, it must not be released!
255  ASSERT_TRUE(bufmgr.access(gen.bufmgr_key)); // Making sure that the buffer is still there
256 }
257 
258 
259 TEST(TransferReceiver, OutOfBufferSpace_32bytes)
260 {
261  Context<32> context;
262  RxFrameGenerator gen(789);
263  uavcan::TransferReceiver& rcv = context.receiver;
264  uavcan::TransferBufferManager& bufmgr = context.bufmgr;
266 
267  /*
268  * Simple transfer, maximum buffer length
269  */
270  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, 1, 100000000), bk)); // 5
271  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET001, 1, 100000100), bk)); // 12
272  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET000, 1, 100000200), bk)); // 19
273  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET001, 1, 100000300), bk)); // 26
274  CHECK_COMPLETE( rcv.addFrame(gen(1, "123456", SET010, 1, 100000400), bk)); // 32
275 
276  ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec());
277  ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567123456712345671234567123456"));
278  ASSERT_EQ(0x3231, rcv.getLastTransferCrc()); // CRC from "12", which is 0x3231 in little endian
279 
280  /*
281  * Transfer longer than available buffer space
282  */
283  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, 2, 100001000), bk)); // 5
284  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET001, 2, 100001100), bk)); // 12
285  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET000, 2, 100001200), bk)); // 19
286  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET001, 2, 100001200), bk)); // 26
287  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET010, 2, 100001300), bk)); // 33 // EOT, ignored - lost sync
288 
289  ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec()); // Timestamp will not be overriden
290  ASSERT_FALSE(bufmgr.access(gen.bufmgr_key)); // Buffer should be removed
291 
292  ASSERT_EQ(1, rcv.yieldErrorCount());
293  ASSERT_EQ(0, rcv.yieldErrorCount());
294 }
295 
296 
297 TEST(TransferReceiver, OutOfOrderFrames)
298 {
299  Context<32> context;
300  RxFrameGenerator gen(789);
301  uavcan::TransferReceiver& rcv = context.receiver;
302  uavcan::TransferBufferManager& bufmgr = context.bufmgr;
304 
305  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, 7, 100000000), bk));
306  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "-------", SET000, 7, 100000100), bk)); // Out of order
307  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "-------", SET010, 7, 100000200), bk)); // Out of order
308  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwertyu", SET001, 7, 100000300), bk));
309  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "-------", SET011, 7, 100000200), bk)); // Out of order
310  CHECK_COMPLETE( rcv.addFrame(gen(1, "abcd", SET010, 7, 100000400), bk));
311 
312  ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec());
313  ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567qwertyuabcd"));
314  ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
315 
316  ASSERT_EQ(3, rcv.yieldErrorCount());
317  ASSERT_EQ(0, rcv.yieldErrorCount());
318 }
319 
320 
321 TEST(TransferReceiver, IntervalMeasurement)
322 {
323  Context<32> context;
324  RxFrameGenerator gen(789);
325  uavcan::TransferReceiver& rcv = context.receiver;
326  uavcan::TransferBufferManager& bufmgr = context.bufmgr;
328 
329  static const int INTERVAL = 1000;
330  uavcan::TransferID tid;
331  uint64_t timestamp = 100000000;
332 
333  for (int i = 0; i < 1000; i++)
334  {
335  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, tid.get(), timestamp), bk));
336  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwertyu", SET001, tid.get(), timestamp), bk));
337  CHECK_COMPLETE( rcv.addFrame(gen(1, "abcd", SET010, tid.get(), timestamp), bk));
338 
339  ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567qwertyuabcd"));
340  ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
341  ASSERT_EQ(timestamp, rcv.getLastTransferTimestampMonotonic().toUSec());
342 
343  timestamp += uint64_t(INTERVAL);
344  tid.increment();
345  }
346 
347  ASSERT_EQ(INTERVAL, rcv.getInterval().toUSec());
348 }
349 
350 
351 TEST(TransferReceiver, Restart)
352 {
353  Context<32> context;
354  RxFrameGenerator gen(789);
355  uavcan::TransferReceiver& rcv = context.receiver;
356  uavcan::TransferBufferManager& bufmgr = context.bufmgr;
358 
359  /*
360  * This transfer looks complete, but must be ignored because of large delay after the first frame
361  * Args: iface_index, data, set, transfer_id, ts_monotonic [, ts_utc]
362  */
363  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "-------", SET100, 0, 100), bk)); // Begin
364  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "-------", SET001, 0, 100000100), bk)); // Continue 100 sec later, expired
365  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "-------", SET010, 0, 100000200), bk)); // Ignored
366 
367  /*
368  * Begins immediately after, encounters a delay 0.9 sec but completes OK
369  */
370  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, 0, 100000300), bk)); // Begin
371  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET001, 0, 100900300), bk)); // 0.9 sec later
372  CHECK_COMPLETE( rcv.addFrame(gen(1, "1234567", SET010, 0, 100900400), bk)); // OK nevertheless
373 
374  ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "3456712345671234567"));
375  ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
376 
377  std::cout << "Interval: " << rcv.getInterval().toString() << std::endl;
378 
379  /*
380  * Begins OK, gets a timeout, switches to another iface
381  */
382  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "-------", SET100, 1, 103000500), bk)); // Begin
383  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "-------", SET001, 1, 105000500), bk)); // 2 sec later, timeout
384  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "-------", SET001, 1, 105000600), bk)); // Same TID, another iface - ignore
385  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "-------", SET001, 2, 105000700), bk)); // Not first frame - ignore
386  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "1234567", SET100, 2, 105000800), bk)); // First, another iface - restart
387  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "-------", SET010, 1, 105000600), bk)); // Old iface - ignore
388  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "1234567", SET001, 2, 105000900), bk)); // Continuing
389  CHECK_COMPLETE( rcv.addFrame(gen(0, "1234567", SET010, 2, 105000910), bk)); // Done
390 
391  ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "3456712345671234567"));
392  ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
393 
394  ASSERT_EQ(4, rcv.yieldErrorCount());
395  ASSERT_EQ(0, rcv.yieldErrorCount());
396 }
397 
398 
399 TEST(TransferReceiver, UtcTransferTimestamping)
400 {
401  Context<32> context;
402  RxFrameGenerator gen(789);
403  uavcan::TransferReceiver& rcv = context.receiver;
404  uavcan::TransferBufferManager& bufmgr = context.bufmgr;
406 
407  /*
408  * Zero UTC timestamp must be preserved
409  */
410  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, 0, 1, 0), bk));
411  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwertyu", SET001, 0, 2, 0), bk));
412  CHECK_COMPLETE( rcv.addFrame(gen(1, "abcd", SET010, 0, 3, 0), bk));
413 
414  ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567qwertyuabcd"));
415  ASSERT_EQ(1, rcv.getLastTransferTimestampMonotonic().toUSec());
416  ASSERT_EQ(0, rcv.getLastTransferTimestampUtc().toUSec());
417 
418  /*
419  * Non-zero UTC timestamp
420  */
421  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, 1, 4, 123), bk)); // This UTC is going to be preserved
422  CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "qwertyu", SET001, 1, 5, 0), bk)); // Following are ignored
423  CHECK_COMPLETE( rcv.addFrame(gen(1, "abcd", SET010, 1, 6, 42), bk));
424 
425  ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567qwertyuabcd"));
426  ASSERT_EQ(4, rcv.getLastTransferTimestampMonotonic().toUSec());
427  ASSERT_EQ(123, rcv.getLastTransferTimestampUtc().toUSec());
428 
429  /*
430  * Single-frame transfers
431  * iface_index, data, set, transfer_id, ts_monotonic
432  */
433  CHECK_SINGLE_FRAME(rcv.addFrame(gen(1, "abc", SET110, 2, 10, 100000000), bk)); // Exact value is irrelevant
434  ASSERT_EQ(10, rcv.getLastTransferTimestampMonotonic().toUSec());
435  ASSERT_EQ(100000000, rcv.getLastTransferTimestampUtc().toUSec());
436 
437  /*
438  * Restart recovery
439  */
440  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "1234567", SET100, 1, 100000000, 800000000), bk));
441  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "qwertyu", SET001, 1, 100000001, 300000000), bk));
442  CHECK_COMPLETE( rcv.addFrame(gen(0, "abcd", SET010, 1, 100000002, 900000000), bk));
443 
444  ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567qwertyuabcd"));
445  ASSERT_EQ(100000000, rcv.getLastTransferTimestampMonotonic().toUSec());
446  ASSERT_EQ(800000000, rcv.getLastTransferTimestampUtc().toUSec());
447 }
448 
449 
450 TEST(TransferReceiver, HeaderParsing)
451 {
452  static const std::string SFT_PAYLOAD = "1234567";
453 
454  uavcan::TransferID tid;
455 
456  /*
457  * Broadcast
458  */
459  {
460  Context<32> context;
461  RxFrameGenerator gen(123);
462  uavcan::TransferReceiver& rcv = context.receiver;
463  uavcan::TransferBufferManager& bufmgr = context.bufmgr;
464 
465  /*
466  * MFT, message broadcasting
467  */
468  {
469  gen.bufmgr_key =
472 
473  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "1234567", SET100, tid.get(), 1), bk1));
474  CHECK_COMPLETE( rcv.addFrame(gen(0, "abcd", SET011, tid.get(), 2), bk1));
475 
476  ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567abcd"));
477  ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
478 
479  tid.increment();
480  bk1.remove();
481  }
482 
483  /*
484  * SFT, message broadcasting
485  */
486  {
487  gen.bufmgr_key =
490 
491  const uavcan::RxFrame frame = gen(0, SFT_PAYLOAD, SET110, tid.get(), 1000);
492 
494  ASSERT_EQ(0x0000, rcv.getLastTransferCrc()); // Default value - zero
495 
496  // All bytes are payload, zero overhead
497  ASSERT_TRUE(std::equal(SFT_PAYLOAD.begin(), SFT_PAYLOAD.end(), frame.getPayloadPtr()));
498 
499  tid.increment();
500  }
501  }
502 
503  /*
504  * Unicast
505  */
506  {
507  Context<32> context;
508  RxFrameGenerator gen(123);
509  uavcan::TransferReceiver& rcv = context.receiver;
510  uavcan::TransferBufferManager& bufmgr = context.bufmgr;
511 
512  static const uavcan::TransferType ADDRESSED_TRANSFER_TYPES[2] =
513  {
516  };
517 
518  /*
519  * MFT, service request/response
520  */
521  for (unsigned i = 0; i < (sizeof(ADDRESSED_TRANSFER_TYPES) / sizeof(ADDRESSED_TRANSFER_TYPES[0])); i++)
522  {
523  gen.bufmgr_key =
524  uavcan::TransferBufferManagerKey(gen.bufmgr_key.getNodeID(), ADDRESSED_TRANSFER_TYPES[i]);
526 
527  const uint64_t ts_monotonic = i + 10;
528 
529  CHECK_NOT_COMPLETE(rcv.addFrame(gen(0, "1234567", SET100, tid.get(), ts_monotonic), bk2));
530  CHECK_COMPLETE( rcv.addFrame(gen(0, "abcd", SET011, tid.get(), ts_monotonic), bk2));
531 
532  ASSERT_TRUE(matchBufferContent(bufmgr.access(gen.bufmgr_key), "34567abcd"));
533  ASSERT_EQ(0x3231, rcv.getLastTransferCrc());
534 
535  tid.increment();
536  bk2.remove();
537  }
538 
539  /*
540  * SFT, message unicast, service request/response
541  */
542  for (unsigned i = 0; i < int(sizeof(ADDRESSED_TRANSFER_TYPES) / sizeof(ADDRESSED_TRANSFER_TYPES[0])); i++)
543  {
544  gen.bufmgr_key =
545  uavcan::TransferBufferManagerKey(gen.bufmgr_key.getNodeID(), ADDRESSED_TRANSFER_TYPES[i]);
547 
548  const uavcan::RxFrame frame = gen(0, SFT_PAYLOAD, SET110, tid.get(), i + 10000U);
549 
551  ASSERT_EQ(0x0000, rcv.getLastTransferCrc()); // Default value - zero
552 
553  // First byte must be ignored
554  ASSERT_TRUE(std::equal(SFT_PAYLOAD.begin(), SFT_PAYLOAD.end(), frame.getPayloadPtr()));
555 
556  tid.increment();
557  }
558  }
559 
560 
561 }
uavcan::TransferReceiver::getLastTransferTimestampUtc
UtcTime getLastTransferTimestampUtc() const
Definition: transfer_receiver.hpp:87
uavcan::uint64_t
std::uint64_t uint64_t
Definition: std.hpp:27
RxFrameGenerator::data_type_id
uint16_t data_type_id
Definition: transfer_receiver.cpp:33
RxFrameGenerator
Definition: transfer_receiver.cpp:28
SET001
@ SET001
Definition: transfer_receiver.cpp:19
Context::receiver
uavcan::TransferReceiver receiver
Definition: transfer_receiver.cpp:78
uavcan::ITransferBuffer
Definition: abstract_transfer_buffer.hpp:16
uavcan::TransferTypeServiceResponse
@ TransferTypeServiceResponse
Definition: transfer.hpp:20
uavcan::NodeID
Definition: transfer.hpp:112
uavcan::TransferType
TransferType
Definition: transfer.hpp:18
Context
Definition: transfer_receiver.cpp:75
SET100
@ SET100
Definition: transfer_receiver.cpp:22
RxFrameGenerator::DEFAULT_KEY
static const uavcan::TransferBufferManagerKey DEFAULT_KEY
Definition: transfer_receiver.cpp:30
SET110
@ SET110
Definition: transfer_receiver.cpp:24
CHECK_COMPLETE
#define CHECK_COMPLETE(x)
Definition: transfer_receiver.cpp:116
SET011
@ SET011
Definition: transfer_receiver.cpp:21
uavcan::TransferReceiver::yieldErrorCount
uint8_t yieldErrorCount()
Definition: uc_transfer_receiver.cpp:241
uavcan::TransferBufferAccessor
Definition: transfer_buffer.hpp:180
uavcan::TransferTypeServiceRequest
@ TransferTypeServiceRequest
Definition: transfer.hpp:21
uavcan::TransferReceiver::getLastTransferTimestampMonotonic
MonotonicTime getLastTransferTimestampMonotonic() const
Definition: transfer_receiver.hpp:86
uavcan::TransferReceiver::addFrame
ResultCode addFrame(const RxFrame &frame, TransferBufferAccessor &tba)
Definition: uc_transfer_receiver.cpp:186
uavcan::TransferID::get
uint8_t get() const
Definition: transfer.hpp:99
uavcan::PoolAllocator< uavcan::MemPoolBlockSize *100, uavcan::MemPoolBlockSize >
uavcan::uint16_t
std::uint16_t uint16_t
Definition: std.hpp:25
uavcan::TransferBufferManagerKey
Definition: transfer_buffer.hpp:63
uavcan::TransferBufferManagerKey::getNodeID
NodeID getNodeID() const
Definition: transfer_buffer.hpp:89
uavcan::TransferID
Definition: transfer.hpp:71
uavcan::TimeBase< MonotonicTime, MonotonicDuration >::fromUSec
static MonotonicTime fromUSec(uint64_t us)
Definition: time.hpp:112
uavcan::TransferReceiver::getLastTransferCrc
uint16_t getLastTransferCrc() const
Definition: transfer_receiver.hpp:89
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
uavcan::TransferTypeMessageBroadcast
@ TransferTypeMessageBroadcast
Definition: transfer.hpp:22
uavcan::RxFrame
Definition: frame.hpp:104
CHECK_NOT_COMPLETE
#define CHECK_NOT_COMPLETE(x)
Definition: transfer_receiver.cpp:115
RxFrameGenerator::bufmgr_key
uavcan::TransferBufferManagerKey bufmgr_key
Definition: transfer_receiver.cpp:34
Context::pool
uavcan::PoolAllocator< uavcan::MemPoolBlockSize *100, uavcan::MemPoolBlockSize > pool
Definition: transfer_receiver.cpp:77
uavcan::equal
UAVCAN_EXPORT bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
Definition: templates.hpp:324
SET010
@ SET010
Definition: transfer_receiver.cpp:20
RxFrameGenerator::RxFrameGenerator
RxFrameGenerator(uint16_t data_type_id, const uavcan::TransferBufferManagerKey &bufmgr_key=DEFAULT_KEY)
Definition: transfer_receiver.cpp:36
uavcan::TransferBufferManager
Definition: transfer_buffer.hpp:153
SET101
@ SET101
Definition: transfer_receiver.cpp:23
SotEotToggle
SotEotToggle
Definition: transfer_receiver.cpp:16
transfer_test_helpers.hpp
SET111
@ SET111
Definition: transfer_receiver.cpp:25
RxFrameGenerator::operator()
uavcan::RxFrame operator()(uint8_t iface_index, const std::string &data, SotEotToggle set, uint8_t transfer_id, uint64_t ts_monotonic, uint64_t ts_utc=0)
iface_index, data, set, transfer_id, ts_monotonic [, ts_utc]
Definition: transfer_receiver.cpp:42
uavcan::NodeID::Broadcast
static const NodeID Broadcast
Definition: transfer.hpp:122
Context::bufmgr
uavcan::TransferBufferManager bufmgr
Definition: transfer_receiver.cpp:79
uavcan::TransferReceiver::getInterval
MonotonicDuration getInterval() const
Definition: transfer_receiver.hpp:91
uavcan::TransferReceiver
Definition: transfer_receiver.hpp:16
uavcan::ITransferBuffer::read
virtual int read(unsigned offset, uint8_t *data, unsigned len) const =0
int
int
Definition: libstubs.cpp:120
frame
uavcan::CanFrame frame
Definition: can.cpp:78
set
ROSCPP_DECL void set(const std::string &key, bool b)
uavcan::DurationBase::toString
void toString(char buf[StringBufSize]) const
Prints time in seconds with microsecond resolution.
Definition: time.hpp:224
CHECK_SINGLE_FRAME
#define CHECK_SINGLE_FRAME(x)
Definition: transfer_receiver.cpp:117
TEST
TEST(TransferReceiver, Basic)
Definition: transfer_receiver.cpp:119
tsMono
uavcan::MonotonicTime tsMono(uint64_t usec)
Definition: libuavcan/libuavcan/test/clock.hpp:97
uavcan::Frame
Definition: frame.hpp:17
Context::Context
Context()
Definition: transfer_receiver.cpp:81
Context::~Context
~Context()
Definition: transfer_receiver.cpp:85
fill
static void fill(T(&a)[Size], R value)
Definition: transfer_buffer.cpp:30
uavcan::TransferBufferManagerKey::getTransferType
TransferType getTransferType() const
Definition: transfer_buffer.hpp:90
transfer_receiver.hpp
RxFrameGenerator::TARGET_NODE_ID
@ TARGET_NODE_ID
Definition: transfer_receiver.cpp:31
matchBufferContent
static bool matchBufferContent(const uavcan::ITransferBuffer *tbb, const std::string &content)
Definition: transfer_receiver.cpp:93
uavcan::TransferReceiver::isTimedOut
bool isTimedOut(MonotonicTime current_ts) const
Definition: uc_transfer_receiver.cpp:181
uavcan::TransferID::increment
void increment()
Definition: transfer.hpp:94
uavcan::TransferBufferManager::access
ITransferBuffer * access(const TransferBufferManagerKey &key)
Definition: uc_transfer_buffer.cpp:302
uavcan::TimeBase::toUSec
uint64_t toUSec() const
Definition: time.hpp:120
uavcan::DurationBase::toUSec
int64_t toUSec() const
Definition: time.hpp:43
SET000
@ SET000
Definition: transfer_receiver.cpp:18
uavcan::TransferBufferAccessor::remove
void remove()
Definition: transfer_buffer.hpp:194


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:03