frame.cpp 12 KB

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