transfer_sender.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
  3. */
  4. #include <algorithm>
  5. #include <gtest/gtest.h>
  6. #include "transfer_test_helpers.hpp"
  7. #include "can/can.hpp"
  8. #include <uavcan/transport/transfer_sender.hpp>
  9. static int sendOne(uavcan::TransferSender& sender, const std::string& data,
  10. uint64_t monotonic_tx_deadline, uint64_t monotonic_blocking_deadline,
  11. uavcan::TransferType transfer_type, uavcan::NodeID dst_node_id)
  12. {
  13. return sender.send(reinterpret_cast<const uint8_t*>(data.c_str()), unsigned(data.length()),
  14. uavcan::MonotonicTime::fromUSec(monotonic_tx_deadline),
  15. uavcan::MonotonicTime::fromUSec(monotonic_blocking_deadline), transfer_type, dst_node_id);
  16. }
  17. static int sendOne(uavcan::TransferSender& sender, const std::string& data,
  18. uint64_t monotonic_tx_deadline, uint64_t monotonic_blocking_deadline,
  19. uavcan::TransferType transfer_type, uavcan::NodeID dst_node_id, uavcan::TransferID tid)
  20. {
  21. return sender.send(reinterpret_cast<const uint8_t*>(data.c_str()), unsigned(data.length()),
  22. uavcan::MonotonicTime::fromUSec(monotonic_tx_deadline),
  23. uavcan::MonotonicTime::fromUSec(monotonic_blocking_deadline), transfer_type, dst_node_id, tid);
  24. }
  25. TEST(TransferSender, Basic)
  26. {
  27. uavcan::PoolAllocator<uavcan::MemPoolBlockSize * 100, uavcan::MemPoolBlockSize> poolmgr;
  28. SystemClockMock clockmock(100);
  29. CanDriverMock driver(2, clockmock);
  30. static const uavcan::NodeID TX_NODE_ID(64);
  31. static const uavcan::NodeID RX_NODE_ID(65);
  32. uavcan::Dispatcher dispatcher_tx(driver, poolmgr, clockmock);
  33. uavcan::Dispatcher dispatcher_rx(driver, poolmgr, clockmock);
  34. ASSERT_TRUE(dispatcher_tx.setNodeID(TX_NODE_ID));
  35. ASSERT_TRUE(dispatcher_rx.setNodeID(RX_NODE_ID));
  36. /*
  37. * Test environment
  38. */
  39. static const uavcan::DataTypeDescriptor TYPES[2] =
  40. {
  41. makeDataType(uavcan::DataTypeKindMessage, 1),
  42. makeDataType(uavcan::DataTypeKindService, 1)
  43. };
  44. uavcan::TransferSender senders[2] =
  45. {
  46. uavcan::TransferSender(dispatcher_tx, TYPES[0], uavcan::CanTxQueue::Volatile),
  47. uavcan::TransferSender(dispatcher_tx, TYPES[1], uavcan::CanTxQueue::Persistent)
  48. };
  49. static const std::string DATA[4] =
  50. {
  51. "Don't panic.",
  52. "The ships hung in the sky in much the same way that bricks don't.",
  53. "Would it save you a lot of time if I just gave up and went mad now?",
  54. "If there's anything more important than my ego around, I want it caught and shot now."
  55. };
  56. /*
  57. * Transmission
  58. */
  59. static const uint64_t TX_DEADLINE = 1000000;
  60. // Low priority
  61. senders[0].setPriority(20);
  62. sendOne(senders[0], DATA[0], TX_DEADLINE, 0, uavcan::TransferTypeMessageBroadcast, 0);
  63. sendOne(senders[0], DATA[1], TX_DEADLINE, 0, uavcan::TransferTypeMessageBroadcast, 0);
  64. // High priority
  65. senders[0].setPriority(10);
  66. sendOne(senders[0], "123", TX_DEADLINE, 0, uavcan::TransferTypeMessageBroadcast, 0);
  67. sendOne(senders[0], "456", TX_DEADLINE, 0, uavcan::TransferTypeMessageBroadcast, 0);
  68. senders[1].setPriority(15);
  69. sendOne(senders[1], DATA[2], TX_DEADLINE, 0, uavcan::TransferTypeServiceRequest, RX_NODE_ID);
  70. sendOne(senders[1], DATA[3], TX_DEADLINE, 0, uavcan::TransferTypeServiceResponse, RX_NODE_ID, 1);
  71. sendOne(senders[1], "", TX_DEADLINE, 0, uavcan::TransferTypeServiceRequest, RX_NODE_ID);
  72. sendOne(senders[1], "", TX_DEADLINE, 0, uavcan::TransferTypeServiceResponse, RX_NODE_ID, 2);
  73. using namespace uavcan;
  74. static const Transfer TRANSFERS[8] =
  75. {
  76. Transfer(TX_DEADLINE, 0, 20, TransferTypeMessageBroadcast, 0, TX_NODE_ID, 0, DATA[0], TYPES[0]),
  77. Transfer(TX_DEADLINE, 0, 20, TransferTypeMessageBroadcast, 1, TX_NODE_ID, 0, DATA[1], TYPES[0]),
  78. Transfer(TX_DEADLINE, 0, 10, TransferTypeMessageBroadcast, 2, TX_NODE_ID, 0, "123", TYPES[0]),
  79. Transfer(TX_DEADLINE, 0, 10, TransferTypeMessageBroadcast, 3, TX_NODE_ID, 0, "456", TYPES[0]),
  80. Transfer(TX_DEADLINE, 0, 15, TransferTypeServiceRequest, 0, TX_NODE_ID, RX_NODE_ID, DATA[2], TYPES[1]),
  81. Transfer(TX_DEADLINE, 0, 15, TransferTypeServiceResponse, 1, TX_NODE_ID, RX_NODE_ID, DATA[3], TYPES[1]),
  82. Transfer(TX_DEADLINE, 0, 15, TransferTypeServiceRequest, 1, TX_NODE_ID, RX_NODE_ID, "", TYPES[1]),
  83. Transfer(TX_DEADLINE, 0, 15, TransferTypeServiceResponse, 2, TX_NODE_ID, RX_NODE_ID, "", TYPES[1])
  84. };
  85. /*
  86. * Making sure that the abort flag is not used.
  87. */
  88. ASSERT_EQ(0, driver.ifaces.at(0).tx.front().flags);
  89. /*
  90. * Receiving on the other side.
  91. */
  92. for (uint8_t i = 0; i < driver.getNumIfaces(); i++) // Moving the frames from TX to RX side
  93. {
  94. CanIfaceMock& iface = driver.ifaces.at(i);
  95. std::cout << "Num frames: " << iface.tx.size() << std::endl;
  96. while (!iface.tx.empty())
  97. {
  98. CanIfaceMock::FrameWithTime ft = iface.tx.front();
  99. iface.tx.pop();
  100. iface.rx.push(ft);
  101. }
  102. }
  103. TestListener sub_msg(dispatcher_rx.getTransferPerfCounter(), TYPES[0], 512, poolmgr);
  104. TestListener sub_srv_req(dispatcher_rx.getTransferPerfCounter(), TYPES[1], 512, poolmgr);
  105. TestListener sub_srv_resp(dispatcher_rx.getTransferPerfCounter(), TYPES[1], 512, poolmgr);
  106. dispatcher_rx.registerMessageListener(&sub_msg);
  107. dispatcher_rx.registerServiceRequestListener(&sub_srv_req);
  108. dispatcher_rx.registerServiceResponseListener(&sub_srv_resp);
  109. while (true)
  110. {
  111. const int res = dispatcher_rx.spin(tsMono(0));
  112. ASSERT_LE(0, res);
  113. clockmock.advance(100);
  114. if (res == 0)
  115. {
  116. break;
  117. }
  118. }
  119. /*
  120. * Validation
  121. */
  122. ASSERT_TRUE(sub_msg.matchAndPop(TRANSFERS[0]));
  123. ASSERT_TRUE(sub_msg.matchAndPop(TRANSFERS[1]));
  124. ASSERT_TRUE(sub_msg.matchAndPop(TRANSFERS[2]));
  125. ASSERT_TRUE(sub_msg.matchAndPop(TRANSFERS[3]));
  126. ASSERT_TRUE(sub_srv_req.matchAndPop(TRANSFERS[4]));
  127. ASSERT_TRUE(sub_srv_req.matchAndPop(TRANSFERS[6]));
  128. ASSERT_TRUE(sub_srv_resp.matchAndPop(TRANSFERS[5]));
  129. ASSERT_TRUE(sub_srv_resp.matchAndPop(TRANSFERS[7]));
  130. /*
  131. * Perf counters
  132. */
  133. EXPECT_EQ(0, dispatcher_tx.getTransferPerfCounter().getErrorCount());
  134. EXPECT_EQ(8, dispatcher_tx.getTransferPerfCounter().getTxTransferCount());
  135. EXPECT_EQ(0, dispatcher_tx.getTransferPerfCounter().getRxTransferCount());
  136. EXPECT_EQ(0, dispatcher_rx.getTransferPerfCounter().getErrorCount());
  137. EXPECT_EQ(0, dispatcher_rx.getTransferPerfCounter().getTxTransferCount());
  138. EXPECT_EQ(8, dispatcher_rx.getTransferPerfCounter().getRxTransferCount());
  139. }
  140. struct TransferSenderTestLoopbackFrameListener : public uavcan::LoopbackFrameListenerBase
  141. {
  142. uavcan::RxFrame last_frame;
  143. unsigned count;
  144. TransferSenderTestLoopbackFrameListener(uavcan::Dispatcher& dispatcher)
  145. : uavcan::LoopbackFrameListenerBase(dispatcher)
  146. , count(0)
  147. {
  148. startListening();
  149. }
  150. void handleLoopbackFrame(const uavcan::RxFrame& frame)
  151. {
  152. last_frame = frame;
  153. count++;
  154. }
  155. };
  156. TEST(TransferSender, Loopback)
  157. {
  158. uavcan::PoolAllocator<uavcan::MemPoolBlockSize * 100, uavcan::MemPoolBlockSize> poolmgr;
  159. SystemClockMock clockmock(100);
  160. CanDriverMock driver(2, clockmock);
  161. static const uavcan::NodeID TX_NODE_ID(64);
  162. uavcan::Dispatcher dispatcher(driver, poolmgr, clockmock);
  163. ASSERT_TRUE(dispatcher.setNodeID(TX_NODE_ID));
  164. uavcan::DataTypeDescriptor desc = makeDataType(uavcan::DataTypeKindMessage, 1, "Foobar");
  165. uavcan::TransferSender sender(dispatcher, desc, uavcan::CanTxQueue::Volatile);
  166. sender.setCanIOFlags(uavcan::CanIOFlagLoopback);
  167. ASSERT_EQ(uavcan::CanIOFlagLoopback, sender.getCanIOFlags());
  168. sender.setIfaceMask(2);
  169. ASSERT_EQ(2, sender.getIfaceMask());
  170. TransferSenderTestLoopbackFrameListener listener(dispatcher);
  171. ASSERT_LE(0, sender.send(reinterpret_cast<const uint8_t*>("123"), 3, tsMono(1000), tsMono(0),
  172. uavcan::TransferTypeMessageBroadcast, 0));
  173. ASSERT_EQ(0, listener.count);
  174. ASSERT_EQ(0, dispatcher.spin(tsMono(1000)));
  175. ASSERT_EQ(1, listener.count);
  176. ASSERT_EQ(1, listener.last_frame.getIfaceIndex());
  177. ASSERT_EQ(3, listener.last_frame.getPayloadLen());
  178. ASSERT_TRUE(TX_NODE_ID == listener.last_frame.getSrcNodeID());
  179. ASSERT_TRUE(listener.last_frame.isEndOfTransfer());
  180. EXPECT_EQ(0, dispatcher.getTransferPerfCounter().getErrorCount());
  181. EXPECT_EQ(1, dispatcher.getTransferPerfCounter().getTxTransferCount());
  182. EXPECT_EQ(0, dispatcher.getTransferPerfCounter().getRxTransferCount());
  183. }
  184. TEST(TransferSender, PassiveMode)
  185. {
  186. uavcan::PoolAllocator<uavcan::MemPoolBlockSize * 100, uavcan::MemPoolBlockSize> poolmgr;
  187. SystemClockMock clockmock(100);
  188. CanDriverMock driver(2, clockmock);
  189. uavcan::Dispatcher dispatcher(driver, poolmgr, clockmock);
  190. uavcan::TransferSender sender(dispatcher, makeDataType(uavcan::DataTypeKindMessage, 123),
  191. uavcan::CanTxQueue::Volatile);
  192. static const uint8_t Payload[] = {1, 2, 3, 4, 5};
  193. // By default, sending in passive mode is not enabled
  194. ASSERT_EQ(-uavcan::ErrPassiveMode,
  195. sender.send(Payload, sizeof(Payload), tsMono(1000), uavcan::MonotonicTime(),
  196. uavcan::TransferTypeMessageBroadcast, uavcan::NodeID::Broadcast));
  197. // Overriding the default
  198. sender.allowAnonymousTransfers();
  199. // OK, now we can broadcast in any mode
  200. ASSERT_LE(0, sender.send(Payload, sizeof(Payload), tsMono(1000), uavcan::MonotonicTime(),
  201. uavcan::TransferTypeMessageBroadcast, uavcan::NodeID::Broadcast));
  202. // ...but not unicast or anything else
  203. ASSERT_EQ(-uavcan::ErrPassiveMode,
  204. sender.send(Payload, sizeof(Payload), tsMono(1000), uavcan::MonotonicTime(),
  205. uavcan::TransferTypeServiceRequest, uavcan::NodeID(42)));
  206. // Making sure the abort flag is set
  207. ASSERT_FALSE(driver.ifaces.at(0).tx.empty());
  208. ASSERT_EQ(uavcan::CanIOFlagAbortOnError, driver.ifaces.at(0).tx.front().flags);
  209. EXPECT_EQ(0, dispatcher.getTransferPerfCounter().getErrorCount());
  210. EXPECT_EQ(1, dispatcher.getTransferPerfCounter().getTxTransferCount());
  211. EXPECT_EQ(0, dispatcher.getTransferPerfCounter().getRxTransferCount());
  212. }