frame.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #include <string>
6 #include <gtest/gtest.h>
9 #include "../clock.hpp"
10 #include "can/can.hpp"
11 
12 
13 TEST(Frame, MessageParseCompile)
14 {
15  using uavcan::Frame;
16  using uavcan::CanFrame;
17  using uavcan::TransferID;
19 
20  Frame frame;
21 
22  /*
23  * Priority
24  * Message Type ID
25  * Service Not Message
26  * Source Node ID
27  */
28  const uint32_t can_id =
29  (16 << 24) | // Priority
30  (20000 << 8) | // Message Type ID
31  (0 << 7) | // Service Not Message
32  (42 << 0); // Source Node ID
33 
34  const std::string payload_string = "hello\xD4"; // SET = 110, TID = 20
35 
36  /*
37  * Parse
38  */
39  // Invalid CAN frames
40  ASSERT_FALSE(frame.parse(CanFrame(can_id | CanFrame::FlagRTR, reinterpret_cast<const uint8_t*>(""), 0)));
41  ASSERT_FALSE(frame.parse(makeCanFrame(can_id, payload_string, STD)));
42 
43  // Valid
44  ASSERT_TRUE(frame.parse(makeCanFrame(can_id, payload_string, EXT)));
45 
46  EXPECT_EQ(TransferID(20), frame.getTransferID());
47  EXPECT_TRUE(frame.isStartOfTransfer());
48  EXPECT_TRUE(frame.isEndOfTransfer());
49  EXPECT_FALSE(frame.getToggle());
50  EXPECT_EQ(uavcan::NodeID(42), frame.getSrcNodeID());
51  EXPECT_TRUE(frame.getDstNodeID().isBroadcast());
52  EXPECT_EQ(uavcan::TransferTypeMessageBroadcast, frame.getTransferType());
53  EXPECT_EQ(20000, frame.getDataTypeID().get());
54  EXPECT_EQ(16, frame.getPriority().get());
55 
56  EXPECT_EQ(payload_string.length() - 1, frame.getPayloadLen());
57  EXPECT_TRUE(std::equal(frame.getPayloadPtr(), frame.getPayloadPtr() + frame.getPayloadLen(),
58  payload_string.begin()));
59 
60  std::cout << frame.toString() << std::endl;
61 
62  /*
63  * Compile
64  */
65  CanFrame can_frame;
66  ASSERT_TRUE(frame.parse(makeCanFrame(can_id, payload_string, EXT)));
67 
68  ASSERT_TRUE(frame.compile(can_frame));
69  ASSERT_EQ(can_frame, makeCanFrame(can_id, payload_string, EXT));
70 
71  EXPECT_EQ(payload_string.length(), can_frame.dlc);
72  std::cout << can_frame.toString() << std::endl;
73  /*
74  * FUN FACT: comparison of uint8_t with char may fail on the character 0xD4 (depending on the locale),
75  * because it will be considered a Unicode character. Hence, we do reinterpret_cast<>.
76  */
77  EXPECT_TRUE(std::equal(can_frame.data, can_frame.data + can_frame.dlc,
78  reinterpret_cast<const uint8_t*>(&payload_string[0])));
79 
80  /*
81  * Comparison
82  */
83  ASSERT_FALSE(Frame() == frame);
84  ASSERT_TRUE(Frame() != frame);
85  frame = Frame();
86  ASSERT_TRUE(Frame() == frame);
87  ASSERT_FALSE(Frame() != frame);
88 }
89 
90 
91 TEST(Frame, ServiceParseCompile)
92 {
93  using uavcan::Frame;
94  using uavcan::CanFrame;
95  using uavcan::TransferID;
97 
98  Frame frame;
99 
100  /*
101  * Priority
102  * Service Type ID
103  * Request Not Response
104  * Destination Node ID
105  * Service Not Message
106  * Source Node ID
107  */
108  const uint32_t can_id =
109  (31 << 24) | // Priority
110  (200 << 16) | // Service Type ID
111  (1 << 15) | // Request Not Response
112  (0x42 << 8) | // Destination Node ID
113  (1 << 7) | // Service Not Message
114  (42 << 0); // Source Node ID
115 
116  const std::string payload_string = "hello\x6a"; // SET = 011, TID = 10
117 
118  /*
119  * Parse
120  */
121  // Invalid CAN frames
122  ASSERT_FALSE(frame.parse(CanFrame(can_id | CanFrame::FlagRTR, reinterpret_cast<const uint8_t*>(""), 0)));
123  ASSERT_FALSE(frame.parse(makeCanFrame(can_id, payload_string, STD)));
124 
125  // Valid
126  ASSERT_TRUE(frame.parse(makeCanFrame(can_id, payload_string, EXT)));
127 
128  EXPECT_EQ(TransferID(10), frame.getTransferID());
129  EXPECT_FALSE(frame.isStartOfTransfer());
130  EXPECT_TRUE(frame.isEndOfTransfer());
131  EXPECT_TRUE(frame.getToggle());
132  EXPECT_EQ(uavcan::NodeID(42), frame.getSrcNodeID());
133  EXPECT_EQ(uavcan::NodeID(0x42), frame.getDstNodeID());
134  EXPECT_EQ(uavcan::TransferTypeServiceRequest, frame.getTransferType());
135  EXPECT_EQ(200, frame.getDataTypeID().get());
136  EXPECT_EQ(31, frame.getPriority().get());
137 
138  EXPECT_EQ(payload_string.length(), frame.getPayloadLen() + 1);
139  EXPECT_TRUE(std::equal(frame.getPayloadPtr(), frame.getPayloadPtr() + frame.getPayloadLen(),
140  reinterpret_cast<const uint8_t*>(&payload_string[0])));
141 
142  std::cout << frame.toString() << std::endl;
143 
144  /*
145  * Compile
146  */
147  CanFrame can_frame;
148  ASSERT_TRUE(frame.parse(makeCanFrame(can_id, payload_string, EXT)));
149 
150  ASSERT_TRUE(frame.compile(can_frame));
151  ASSERT_EQ(can_frame, makeCanFrame(can_id, payload_string, EXT));
152 
153  EXPECT_EQ(payload_string.length(), can_frame.dlc);
154  EXPECT_TRUE(std::equal(can_frame.data, can_frame.data + can_frame.dlc,
155  reinterpret_cast<const uint8_t*>(&payload_string[0])));
156 
157  /*
158  * Comparison
159  */
160  ASSERT_FALSE(Frame() == frame);
161  ASSERT_TRUE(Frame() != frame);
162  frame = Frame();
163  ASSERT_TRUE(Frame() == frame);
164  ASSERT_FALSE(Frame() != frame);
165 }
166 
167 
168 TEST(Frame, AnonymousParseCompile)
169 {
170  using uavcan::Frame;
171  using uavcan::CanFrame;
172  using uavcan::TransferID;
173  using uavcan::TransferType;
174 
175  Frame frame;
176 
177  /*
178  * Priority
179  * Discriminator
180  * Message Type ID
181  * Service Not Message
182  * Source Node ID
183  */
184  const uint32_t can_id =
185  (16383 << 10) | // Discriminator
186  (1 << 8); // Message Type ID
187 
188  const std::string payload_string = "hello\xd4"; // SET = 110, TID = 20
189 
190  uavcan::TransferCRC payload_crc;
191  payload_crc.add(reinterpret_cast<const uint8_t*>(payload_string.c_str()), unsigned(payload_string.length()));
192 
193  /*
194  * Parse
195  */
196  ASSERT_TRUE(frame.parse(makeCanFrame(can_id, payload_string, EXT)));
197 
198  EXPECT_EQ(TransferID(20), frame.getTransferID());
199  EXPECT_TRUE(frame.isStartOfTransfer());
200  EXPECT_TRUE(frame.isEndOfTransfer());
201  EXPECT_FALSE(frame.getToggle());
202  EXPECT_TRUE(frame.getSrcNodeID().isBroadcast());
203  EXPECT_TRUE(frame.getDstNodeID().isBroadcast());
204  EXPECT_EQ(uavcan::TransferTypeMessageBroadcast, frame.getTransferType());
205  EXPECT_EQ(1, frame.getDataTypeID().get());
206  EXPECT_EQ(0, frame.getPriority().get());
207 
208  EXPECT_EQ(payload_string.length() - 1, frame.getPayloadLen());
209  EXPECT_TRUE(std::equal(frame.getPayloadPtr(), frame.getPayloadPtr() + frame.getPayloadLen(),
210  reinterpret_cast<const uint8_t*>(&payload_string[0])));
211 
212  std::cout << frame.toString() << std::endl;
213 
214  /*
215  * Compile
216  */
217  const uint32_t DiscriminatorMask = 0x00FFFC00;
218  const uint32_t NoDiscriminatorMask = 0xFF0003FF;
219 
220  CanFrame can_frame;
221  ASSERT_TRUE(frame.parse(makeCanFrame(can_id, payload_string, EXT)));
222 
223  ASSERT_TRUE(frame.compile(can_frame));
224  ASSERT_EQ(can_id & NoDiscriminatorMask & uavcan::CanFrame::MaskExtID,
225  can_frame.id & NoDiscriminatorMask & uavcan::CanFrame::MaskExtID);
226 
227  EXPECT_EQ(payload_string.length(), can_frame.dlc);
228  EXPECT_TRUE(std::equal(can_frame.data, can_frame.data + can_frame.dlc,
229  reinterpret_cast<const uint8_t*>(&payload_string[0])));
230 
231  EXPECT_EQ((can_frame.id & DiscriminatorMask & uavcan::CanFrame::MaskExtID) >> 10, payload_crc.get() & 16383);
232 
233  /*
234  * Comparison
235  */
236  ASSERT_FALSE(Frame() == frame);
237  ASSERT_TRUE(Frame() != frame);
238  frame = Frame();
239  ASSERT_TRUE(Frame() == frame);
240  ASSERT_FALSE(Frame() != frame);
241 }
242 
243 
244 TEST(Frame, FrameParsing)
245 {
246  using uavcan::Frame;
247  using uavcan::CanFrame;
248  using uavcan::NodeID;
249  using uavcan::TransferID;
250 
251  CanFrame can;
252  Frame frame;
253  ASSERT_FALSE(frame.parse(can));
254 
255  for (unsigned i = 0; i < sizeof(CanFrame::data); i++)
256  {
257  can.data[i] = uint8_t(i | (i << 4));
258  }
259 
260  /*
261  * Message CAN ID fields and offsets:
262  * 24 Priority
263  * 8 Message Type ID
264  * 7 Service Not Message (0)
265  * 0 Source Node ID
266  *
267  * Service CAN ID fields and offsets:
268  * 24 Priority
269  * 16 Service Type ID
270  * 15 Request Not Response
271  * 8 Destination Node ID
272  * 7 Service Not Message (1)
273  * 0 Source Node ID
274  */
275 
276  /*
277  * SFT message broadcast
278  */
279  can.id = CanFrame::FlagEFF |
280  (2 << 24) |
281  (456 << 8) |
282  (0 << 7) |
283  (42 << 0);
284 
285  can.data[7] = 0xcf; // SET=110, TID=0
286 
287  ASSERT_FALSE(frame.parse(can));
288  can.dlc = 8;
289 
290  ASSERT_TRUE(frame.parse(can));
291  EXPECT_TRUE(frame.isStartOfTransfer());
292  EXPECT_TRUE(frame.isEndOfTransfer());
293  EXPECT_FALSE(frame.getToggle());
294  ASSERT_EQ(2, frame.getPriority().get());
295  ASSERT_EQ(NodeID(42), frame.getSrcNodeID());
296  ASSERT_EQ(NodeID::Broadcast, frame.getDstNodeID());
297  ASSERT_EQ(456, frame.getDataTypeID().get());
298  ASSERT_EQ(TransferID(15), frame.getTransferID());
299  ASSERT_EQ(uavcan::TransferTypeMessageBroadcast, frame.getTransferType());
300 
301  // TODO: test service frames
302  // TODO: test malformed frames
303 }
304 
305 
306 TEST(Frame, RxFrameParse)
307 {
308  using uavcan::Frame;
309  using uavcan::RxFrame;
310  using uavcan::CanFrame;
311  using uavcan::CanRxFrame;
312 
313  CanRxFrame can_rx_frame;
314  RxFrame rx_frame;
315 
316  // Failure
317  ASSERT_FALSE(rx_frame.parse(can_rx_frame));
318 
319  // Valid
320  can_rx_frame.ts_mono = uavcan::MonotonicTime::fromUSec(1); // Zero is not allowed
321  can_rx_frame.id = CanFrame::FlagEFF |
322  (2 << 24) |
323  (456 << 8) |
324  (0 << 7) |
325  (42 << 0);
326 
327  ASSERT_FALSE(rx_frame.parse(can_rx_frame));
328 
329  can_rx_frame.data[0] = 0xc0; // SOT, EOT
330  can_rx_frame.dlc = 1;
331 
332  ASSERT_TRUE(rx_frame.parse(can_rx_frame));
333  ASSERT_EQ(1, rx_frame.getMonotonicTimestamp().toUSec());
334  ASSERT_EQ(0, rx_frame.getIfaceIndex());
335 
336  can_rx_frame.ts_mono = tsMono(123);
337  can_rx_frame.iface_index = 2;
338 
340  ASSERT_TRUE(frame.compile(can_rx_frame));
341 
342  ASSERT_TRUE(rx_frame.parse(can_rx_frame));
343  ASSERT_EQ(123, rx_frame.getMonotonicTimestamp().toUSec());
344  ASSERT_EQ(2, rx_frame.getIfaceIndex());
345  ASSERT_EQ(456, rx_frame.getDataTypeID().get());
346  ASSERT_EQ(uavcan::TransferTypeMessageBroadcast, rx_frame.getTransferType());
347 }
348 
349 
350 TEST(Frame, FrameToString)
351 {
352  using uavcan::Frame;
353  using uavcan::RxFrame;
354 
355  // RX frame default
356  RxFrame rx_frame;
357  EXPECT_EQ("prio=255 dtid=65535 tt=3 snid=255 dnid=255 sot=0 eot=0 togl=0 tid=0 payload=[] ts_m=0.000000 ts_utc=0.000000 iface=0",
358  rx_frame.toString());
359 
360  // RX frame max len
364 
365  uint8_t data[8];
366  for (unsigned i = 0; i < sizeof(data); i++)
367  {
368  data[i] = uint8_t(i);
369  }
370  rx_frame.setPayload(data, sizeof(data));
371 
372  rx_frame.setStartOfTransfer(true);
373  rx_frame.setEndOfTransfer(true);
374  rx_frame.flipToggle();
375  rx_frame.setPriority(uavcan::TransferPriority::NumericallyMax);
376 
377  EXPECT_EQ("prio=31 dtid=65535 tt=2 snid=127 dnid=0 sot=1 eot=1 togl=1 tid=31 payload=[00 01 02 03 04 05 06] "
378  "ts_m=18446744073709.551615 ts_utc=18446744073709.551615 iface=3",
379  rx_frame.toString());
380 
381  // Plain frame default
382  Frame frame;
383  EXPECT_EQ("prio=255 dtid=65535 tt=3 snid=255 dnid=255 sot=0 eot=0 togl=0 tid=0 payload=[]", frame.toString());
384 
385  // Plain frame max len
386  frame = rx_frame;
387  EXPECT_EQ("prio=31 dtid=65535 tt=2 snid=127 dnid=0 sot=1 eot=1 togl=1 tid=31 payload=[00 01 02 03 04 05 06]",
388  frame.toString());
389 }
uavcan::DataTypeID::MaxPossibleDataTypeIDValue
static const uint16_t MaxPossibleDataTypeIDValue
Definition: data_type.hpp:54
uavcan::TransferPriority::NumericallyMax
static const uint8_t NumericallyMax
Definition: transfer.hpp:34
crc.hpp
uavcan::uint32_t
std::uint32_t uint32_t
Definition: std.hpp:26
uavcan::NodeID
Definition: transfer.hpp:112
uavcan::TransferType
TransferType
Definition: transfer.hpp:18
uavcan::TransferCRC::add
void add(uint8_t byte)
Definition: crc.hpp:60
makeCanFrame
uavcan::CanFrame makeCanFrame(uint32_t id, const std::string &str_data, FrameType type)
Definition: libuavcan/libuavcan/test/transport/can/can.hpp:278
uavcan::CanFrame
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:24
uavcan::CanRxFrame
Definition: can_io.hpp:25
uavcan::TransferID::Max
static const uint8_t Max
Definition: transfer.hpp:77
uavcan::TransferTypeServiceRequest
@ TransferTypeServiceRequest
Definition: transfer.hpp:21
uavcan::TransferID
Definition: transfer.hpp:71
uavcan::TimeBase< MonotonicTime, MonotonicDuration >::fromUSec
static MonotonicTime fromUSec(uint64_t us)
Definition: time.hpp:112
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
transfer.hpp
uavcan::TimeBase< MonotonicTime, MonotonicDuration >::getMax
static MonotonicTime getMax()
Definition: time.hpp:110
uavcan::equal
UAVCAN_EXPORT bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
Definition: templates.hpp:324
TEST
TEST(Frame, MessageParseCompile)
Definition: frame.cpp:13
uavcan::CanFrame::MaskExtID
static const uint32_t MaskExtID
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:27
can.hpp
uavcan::NodeID::Broadcast
static const NodeID Broadcast
Definition: transfer.hpp:122
STD
@ STD
Definition: libuavcan/libuavcan/test/transport/can/can.hpp:277
frame
uavcan::CanFrame frame
Definition: can.cpp:78
tsMono
uavcan::MonotonicTime tsMono(uint64_t usec)
Definition: libuavcan/libuavcan/test/clock.hpp:97
uavcan::Frame
Definition: frame.hpp:17
uavcan::NodeID::Max
static const uint8_t Max
Definition: transfer.hpp:120
EXT
@ EXT
Definition: libuavcan/libuavcan/test/transport/can/can.hpp:277
uavcan::TransferCRC
Definition: crc.hpp:28
uavcan::TransferCRC::get
uint16_t get() const
Definition: crc.hpp:75


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