Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UAVCAN UAVCAN_Subscriber
frame.cpp
00001 /* 00002 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> 00003 */ 00004 00005 #include <string> 00006 #include <gtest/gtest.h> 00007 #include <uavcan/transport/transfer.hpp> 00008 #include <uavcan/transport/crc.hpp> 00009 #include "../clock.hpp" 00010 #include "can/can.hpp" 00011 00012 00013 TEST(Frame, MessageParseCompile) 00014 { 00015 using uavcan::Frame; 00016 using uavcan::CanFrame; 00017 using uavcan::TransferID; 00018 using uavcan::TransferType; 00019 00020 Frame frame; 00021 00022 /* 00023 * Priority 00024 * Message Type ID 00025 * Service Not Message 00026 * Source Node ID 00027 */ 00028 const uint32_t can_id = 00029 (16 << 24) | // Priority 00030 (20000 << 8) | // Message Type ID 00031 (0 << 7) | // Service Not Message 00032 (42 << 0); // Source Node ID 00033 00034 const std::string payload_string = "hello\xD4"; // SET = 110, TID = 20 00035 00036 /* 00037 * Parse 00038 */ 00039 // Invalid CAN frames 00040 ASSERT_FALSE(frame.parse(CanFrame(can_id | CanFrame::FlagRTR, reinterpret_cast<const uint8_t*>(""), 0))); 00041 ASSERT_FALSE(frame.parse(makeCanFrame(can_id, payload_string, STD))); 00042 00043 // Valid 00044 ASSERT_TRUE(frame.parse(makeCanFrame(can_id, payload_string, EXT))); 00045 00046 EXPECT_EQ(TransferID(20), frame.getTransferID()); 00047 EXPECT_TRUE(frame.isStartOfTransfer()); 00048 EXPECT_TRUE(frame.isEndOfTransfer()); 00049 EXPECT_FALSE(frame.getToggle()); 00050 EXPECT_EQ(uavcan::NodeID(42), frame.getSrcNodeID()); 00051 EXPECT_TRUE(frame.getDstNodeID().isBroadcast()); 00052 EXPECT_EQ(uavcan::TransferTypeMessageBroadcast, frame.getTransferType()); 00053 EXPECT_EQ(20000, frame.getDataTypeID().get()); 00054 EXPECT_EQ(16, frame.getPriority().get()); 00055 00056 EXPECT_EQ(payload_string.length() - 1, frame.getPayloadLen()); 00057 EXPECT_TRUE(std::equal(frame.getPayloadPtr(), frame.getPayloadPtr() + frame.getPayloadLen(), 00058 payload_string.begin())); 00059 00060 std::cout << frame.toString() << std::endl; 00061 00062 /* 00063 * Compile 00064 */ 00065 CanFrame can_frame; 00066 ASSERT_TRUE(frame.parse(makeCanFrame(can_id, payload_string, EXT))); 00067 00068 ASSERT_TRUE(frame.compile(can_frame)); 00069 ASSERT_EQ(can_frame, makeCanFrame(can_id, payload_string, EXT)); 00070 00071 EXPECT_EQ(payload_string.length(), can_frame.dlc); 00072 std::cout << can_frame.toString() << std::endl; 00073 /* 00074 * FUN FACT: comparison of uint8_t with char may fail on the character 0xD4 (depending on the locale), 00075 * because it will be considered a Unicode character. Hence, we do reinterpret_cast<>. 00076 */ 00077 EXPECT_TRUE(std::equal(can_frame.data, can_frame.data + can_frame.dlc, 00078 reinterpret_cast<const uint8_t*>(&payload_string[0]))); 00079 00080 /* 00081 * Comparison 00082 */ 00083 ASSERT_FALSE(Frame() == frame); 00084 ASSERT_TRUE(Frame() != frame); 00085 frame = Frame(); 00086 ASSERT_TRUE(Frame() == frame); 00087 ASSERT_FALSE(Frame() != frame); 00088 } 00089 00090 00091 TEST(Frame, ServiceParseCompile) 00092 { 00093 using uavcan::Frame; 00094 using uavcan::CanFrame; 00095 using uavcan::TransferID; 00096 using uavcan::TransferType; 00097 00098 Frame frame; 00099 00100 /* 00101 * Priority 00102 * Service Type ID 00103 * Request Not Response 00104 * Destination Node ID 00105 * Service Not Message 00106 * Source Node ID 00107 */ 00108 const uint32_t can_id = 00109 (31 << 24) | // Priority 00110 (200 << 16) | // Service Type ID 00111 (1 << 15) | // Request Not Response 00112 (0x42 << 8) | // Destination Node ID 00113 (1 << 7) | // Service Not Message 00114 (42 << 0); // Source Node ID 00115 00116 const std::string payload_string = "hello\x6a"; // SET = 011, TID = 10 00117 00118 /* 00119 * Parse 00120 */ 00121 // Invalid CAN frames 00122 ASSERT_FALSE(frame.parse(CanFrame(can_id | CanFrame::FlagRTR, reinterpret_cast<const uint8_t*>(""), 0))); 00123 ASSERT_FALSE(frame.parse(makeCanFrame(can_id, payload_string, STD))); 00124 00125 // Valid 00126 ASSERT_TRUE(frame.parse(makeCanFrame(can_id, payload_string, EXT))); 00127 00128 EXPECT_EQ(TransferID(10), frame.getTransferID()); 00129 EXPECT_FALSE(frame.isStartOfTransfer()); 00130 EXPECT_TRUE(frame.isEndOfTransfer()); 00131 EXPECT_TRUE(frame.getToggle()); 00132 EXPECT_EQ(uavcan::NodeID(42), frame.getSrcNodeID()); 00133 EXPECT_EQ(uavcan::NodeID(0x42), frame.getDstNodeID()); 00134 EXPECT_EQ(uavcan::TransferTypeServiceRequest, frame.getTransferType()); 00135 EXPECT_EQ(200, frame.getDataTypeID().get()); 00136 EXPECT_EQ(31, frame.getPriority().get()); 00137 00138 EXPECT_EQ(payload_string.length(), frame.getPayloadLen() + 1); 00139 EXPECT_TRUE(std::equal(frame.getPayloadPtr(), frame.getPayloadPtr() + frame.getPayloadLen(), 00140 reinterpret_cast<const uint8_t*>(&payload_string[0]))); 00141 00142 std::cout << frame.toString() << std::endl; 00143 00144 /* 00145 * Compile 00146 */ 00147 CanFrame can_frame; 00148 ASSERT_TRUE(frame.parse(makeCanFrame(can_id, payload_string, EXT))); 00149 00150 ASSERT_TRUE(frame.compile(can_frame)); 00151 ASSERT_EQ(can_frame, makeCanFrame(can_id, payload_string, EXT)); 00152 00153 EXPECT_EQ(payload_string.length(), can_frame.dlc); 00154 EXPECT_TRUE(std::equal(can_frame.data, can_frame.data + can_frame.dlc, 00155 reinterpret_cast<const uint8_t*>(&payload_string[0]))); 00156 00157 /* 00158 * Comparison 00159 */ 00160 ASSERT_FALSE(Frame() == frame); 00161 ASSERT_TRUE(Frame() != frame); 00162 frame = Frame(); 00163 ASSERT_TRUE(Frame() == frame); 00164 ASSERT_FALSE(Frame() != frame); 00165 } 00166 00167 00168 TEST(Frame, AnonymousParseCompile) 00169 { 00170 using uavcan::Frame; 00171 using uavcan::CanFrame; 00172 using uavcan::TransferID; 00173 using uavcan::TransferType; 00174 00175 Frame frame; 00176 00177 /* 00178 * Priority 00179 * Discriminator 00180 * Message Type ID 00181 * Service Not Message 00182 * Source Node ID 00183 */ 00184 const uint32_t can_id = 00185 (16383 << 10) | // Discriminator 00186 (1 << 8); // Message Type ID 00187 00188 const std::string payload_string = "hello\xd4"; // SET = 110, TID = 20 00189 00190 uavcan::TransferCRC payload_crc; 00191 payload_crc.add(reinterpret_cast<const uint8_t*>(payload_string.c_str()), unsigned(payload_string.length())); 00192 00193 /* 00194 * Parse 00195 */ 00196 ASSERT_TRUE(frame.parse(makeCanFrame(can_id, payload_string, EXT))); 00197 00198 EXPECT_EQ(TransferID(20), frame.getTransferID()); 00199 EXPECT_TRUE(frame.isStartOfTransfer()); 00200 EXPECT_TRUE(frame.isEndOfTransfer()); 00201 EXPECT_FALSE(frame.getToggle()); 00202 EXPECT_TRUE(frame.getSrcNodeID().isBroadcast()); 00203 EXPECT_TRUE(frame.getDstNodeID().isBroadcast()); 00204 EXPECT_EQ(uavcan::TransferTypeMessageBroadcast, frame.getTransferType()); 00205 EXPECT_EQ(1, frame.getDataTypeID().get()); 00206 EXPECT_EQ(0, frame.getPriority().get()); 00207 00208 EXPECT_EQ(payload_string.length() - 1, frame.getPayloadLen()); 00209 EXPECT_TRUE(std::equal(frame.getPayloadPtr(), frame.getPayloadPtr() + frame.getPayloadLen(), 00210 reinterpret_cast<const uint8_t*>(&payload_string[0]))); 00211 00212 std::cout << frame.toString() << std::endl; 00213 00214 /* 00215 * Compile 00216 */ 00217 const uint32_t DiscriminatorMask = 0x00FFFC00; 00218 const uint32_t NoDiscriminatorMask = 0xFF0003FF; 00219 00220 CanFrame can_frame; 00221 ASSERT_TRUE(frame.parse(makeCanFrame(can_id, payload_string, EXT))); 00222 00223 ASSERT_TRUE(frame.compile(can_frame)); 00224 ASSERT_EQ(can_id & NoDiscriminatorMask & uavcan::CanFrame::MaskExtID, 00225 can_frame.id & NoDiscriminatorMask & uavcan::CanFrame::MaskExtID); 00226 00227 EXPECT_EQ(payload_string.length(), can_frame.dlc); 00228 EXPECT_TRUE(std::equal(can_frame.data, can_frame.data + can_frame.dlc, 00229 reinterpret_cast<const uint8_t*>(&payload_string[0]))); 00230 00231 EXPECT_EQ((can_frame.id & DiscriminatorMask & uavcan::CanFrame::MaskExtID) >> 10, payload_crc.get() & 16383); 00232 00233 /* 00234 * Comparison 00235 */ 00236 ASSERT_FALSE(Frame() == frame); 00237 ASSERT_TRUE(Frame() != frame); 00238 frame = Frame(); 00239 ASSERT_TRUE(Frame() == frame); 00240 ASSERT_FALSE(Frame() != frame); 00241 } 00242 00243 00244 TEST(Frame, FrameParsing) 00245 { 00246 using uavcan::Frame; 00247 using uavcan::CanFrame; 00248 using uavcan::NodeID; 00249 using uavcan::TransferID; 00250 00251 CanFrame can; 00252 Frame frame; 00253 ASSERT_FALSE(frame.parse(can)); 00254 00255 for (unsigned i = 0; i < sizeof(CanFrame::data); i++) 00256 { 00257 can.data[i] = uint8_t(i | (i << 4)); 00258 } 00259 00260 /* 00261 * Message CAN ID fields and offsets: 00262 * 24 Priority 00263 * 8 Message Type ID 00264 * 7 Service Not Message (0) 00265 * 0 Source Node ID 00266 * 00267 * Service CAN ID fields and offsets: 00268 * 24 Priority 00269 * 16 Service Type ID 00270 * 15 Request Not Response 00271 * 8 Destination Node ID 00272 * 7 Service Not Message (1) 00273 * 0 Source Node ID 00274 */ 00275 00276 /* 00277 * SFT message broadcast 00278 */ 00279 can.id = CanFrame::FlagEFF | 00280 (2 << 24) | 00281 (456 << 8) | 00282 (0 << 7) | 00283 (42 << 0); 00284 00285 can.data[7] = 0xcf; // SET=110, TID=0 00286 00287 ASSERT_FALSE(frame.parse(can)); 00288 can.dlc = 8; 00289 00290 ASSERT_TRUE(frame.parse(can)); 00291 EXPECT_TRUE(frame.isStartOfTransfer()); 00292 EXPECT_TRUE(frame.isEndOfTransfer()); 00293 EXPECT_FALSE(frame.getToggle()); 00294 ASSERT_EQ(2, frame.getPriority().get()); 00295 ASSERT_EQ(NodeID(42), frame.getSrcNodeID()); 00296 ASSERT_EQ(NodeID::Broadcast, frame.getDstNodeID()); 00297 ASSERT_EQ(456, frame.getDataTypeID().get()); 00298 ASSERT_EQ(TransferID(15), frame.getTransferID()); 00299 ASSERT_EQ(uavcan::TransferTypeMessageBroadcast, frame.getTransferType()); 00300 00301 // TODO: test service frames 00302 // TODO: test malformed frames 00303 } 00304 00305 00306 TEST(Frame, RxFrameParse) 00307 { 00308 using uavcan::Frame; 00309 using uavcan::RxFrame; 00310 using uavcan::CanFrame; 00311 using uavcan::CanRxFrame; 00312 00313 CanRxFrame can_rx_frame; 00314 RxFrame rx_frame; 00315 00316 // Failure 00317 ASSERT_FALSE(rx_frame.parse(can_rx_frame)); 00318 00319 // Valid 00320 can_rx_frame.ts_mono = uavcan::MonotonicTime::fromUSec(1); // Zero is not allowed 00321 can_rx_frame.id = CanFrame::FlagEFF | 00322 (2 << 24) | 00323 (456 << 8) | 00324 (0 << 7) | 00325 (42 << 0); 00326 00327 ASSERT_FALSE(rx_frame.parse(can_rx_frame)); 00328 00329 can_rx_frame.data[0] = 0xc0; // SOT, EOT 00330 can_rx_frame.dlc = 1; 00331 00332 ASSERT_TRUE(rx_frame.parse(can_rx_frame)); 00333 ASSERT_EQ(1, rx_frame.getMonotonicTimestamp().toUSec()); 00334 ASSERT_EQ(0, rx_frame.getIfaceIndex()); 00335 00336 can_rx_frame.ts_mono = tsMono(123); 00337 can_rx_frame.iface_index = 2; 00338 00339 Frame frame(456, uavcan::TransferTypeMessageBroadcast, 1, uavcan::NodeID::Broadcast, 0); 00340 ASSERT_TRUE(frame.compile(can_rx_frame)); 00341 00342 ASSERT_TRUE(rx_frame.parse(can_rx_frame)); 00343 ASSERT_EQ(123, rx_frame.getMonotonicTimestamp().toUSec()); 00344 ASSERT_EQ(2, rx_frame.getIfaceIndex()); 00345 ASSERT_EQ(456, rx_frame.getDataTypeID().get()); 00346 ASSERT_EQ(uavcan::TransferTypeMessageBroadcast, rx_frame.getTransferType()); 00347 } 00348 00349 00350 TEST(Frame, FrameToString) 00351 { 00352 using uavcan::Frame; 00353 using uavcan::RxFrame; 00354 00355 // RX frame default 00356 RxFrame rx_frame; 00357 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", 00358 rx_frame.toString()); 00359 00360 // RX frame max len 00361 rx_frame = RxFrame(Frame(uavcan::DataTypeID::MaxPossibleDataTypeIDValue, uavcan::TransferTypeMessageBroadcast, 00362 uavcan::NodeID::Max, 0, uavcan::TransferID::Max), 00363 uavcan::MonotonicTime::getMax(), uavcan::UtcTime::getMax(), 3); 00364 00365 uint8_t data[8]; 00366 for (unsigned i = 0; i < sizeof(data); i++) 00367 { 00368 data[i] = uint8_t(i); 00369 } 00370 rx_frame.setPayload(data, sizeof(data)); 00371 00372 rx_frame.setStartOfTransfer(true); 00373 rx_frame.setEndOfTransfer(true); 00374 rx_frame.flipToggle(); 00375 rx_frame.setPriority(uavcan::TransferPriority::NumericallyMax); 00376 00377 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] " 00378 "ts_m=18446744073709.551615 ts_utc=18446744073709.551615 iface=3", 00379 rx_frame.toString()); 00380 00381 // Plain frame default 00382 Frame frame; 00383 EXPECT_EQ("prio=255 dtid=65535 tt=3 snid=255 dnid=255 sot=0 eot=0 togl=0 tid=0 payload=[]", frame.toString()); 00384 00385 // Plain frame max len 00386 frame = rx_frame; 00387 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]", 00388 frame.toString()); 00389 }
Generated on Tue Jul 12 2022 17:17:32 by
