dispatcher.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /*
  2. * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
  3. */
  4. #include <memory>
  5. #include <vector>
  6. #include <gtest/gtest.h>
  7. #include "transfer_test_helpers.hpp"
  8. #include "can/can.hpp"
  9. #include <uavcan/transport/dispatcher.hpp>
  10. class DispatcherTransferEmulator : public IncomingTransferEmulatorBase
  11. {
  12. CanDriverMock& target_;
  13. public:
  14. DispatcherTransferEmulator(CanDriverMock& target, uavcan::NodeID dst_node_id = 127)
  15. : IncomingTransferEmulatorBase(dst_node_id)
  16. , target_(target)
  17. { }
  18. void sendOneFrame(const uavcan::RxFrame& frame)
  19. {
  20. CanIfaceMock* const iface = static_cast<CanIfaceMock*>(target_.getIface(frame.getIfaceIndex()));
  21. EXPECT_TRUE(iface);
  22. if (iface)
  23. {
  24. iface->pushRx(frame);
  25. }
  26. }
  27. };
  28. struct RxFrameListener : public uavcan::IRxFrameListener
  29. {
  30. std::vector<uavcan::CanRxFrame> rx_frames;
  31. virtual void handleRxFrame(const uavcan::CanRxFrame& frame, uavcan::CanIOFlags flags)
  32. {
  33. std::cout << "RX frame [flags=" << flags << "]: " << frame.toString() << std::endl;
  34. if ((flags & uavcan::CanIOFlagLoopback) == 0)
  35. {
  36. rx_frames.push_back(frame);
  37. }
  38. }
  39. };
  40. static const uavcan::NodeID SELF_NODE_ID(64);
  41. TEST(Dispatcher, Reception)
  42. {
  43. uavcan::PoolAllocator<uavcan::MemPoolBlockSize * 100, uavcan::MemPoolBlockSize> pool;
  44. SystemClockMock clockmock(100);
  45. CanDriverMock driver(2, clockmock);
  46. uavcan::Dispatcher dispatcher(driver, pool, clockmock);
  47. ASSERT_TRUE(dispatcher.setNodeID(SELF_NODE_ID)); // Can be set only once
  48. ASSERT_FALSE(dispatcher.setNodeID(SELF_NODE_ID));
  49. ASSERT_EQ(SELF_NODE_ID, dispatcher.getNodeID());
  50. DispatcherTransferEmulator emulator(driver, SELF_NODE_ID);
  51. /*
  52. * RX listener
  53. */
  54. RxFrameListener rx_listener;
  55. ASSERT_FALSE(dispatcher.getRxFrameListener());
  56. dispatcher.installRxFrameListener(&rx_listener);
  57. ASSERT_TRUE(dispatcher.getRxFrameListener());
  58. ASSERT_TRUE(rx_listener.rx_frames.empty());
  59. /*
  60. * Test environment
  61. */
  62. static const uavcan::DataTypeDescriptor TYPES[4] =
  63. {
  64. makeDataType(uavcan::DataTypeKindMessage, 1),
  65. makeDataType(uavcan::DataTypeKindMessage, 2),
  66. makeDataType(uavcan::DataTypeKindService, 1),
  67. makeDataType(uavcan::DataTypeKindService, 1)
  68. };
  69. typedef std::auto_ptr<TestListener> TestListenerPtr;
  70. static const int MaxBufSize = 512;
  71. static const int NumSubscribers = 6;
  72. TestListenerPtr subscribers[NumSubscribers] =
  73. {
  74. TestListenerPtr(new TestListener(dispatcher.getTransferPerfCounter(), TYPES[0], MaxBufSize, pool)), // msg
  75. TestListenerPtr(new TestListener(dispatcher.getTransferPerfCounter(), TYPES[0], MaxBufSize, pool)), // msg // Two similar
  76. TestListenerPtr(new TestListener(dispatcher.getTransferPerfCounter(), TYPES[1], MaxBufSize, pool)), // msg
  77. TestListenerPtr(new TestListener(dispatcher.getTransferPerfCounter(), TYPES[2], MaxBufSize, pool)), // srv
  78. TestListenerPtr(new TestListener(dispatcher.getTransferPerfCounter(), TYPES[3], MaxBufSize, pool)), // srv
  79. TestListenerPtr(new TestListener(dispatcher.getTransferPerfCounter(), TYPES[3], MaxBufSize, pool)) // srv // Repeat again
  80. };
  81. static const std::string DATA[6] =
  82. {
  83. "Yes, man is mortal, but that would be only half the trouble. "
  84. "The worst of it is that he's sometimes unexpectedly mortal - there's the trick!",
  85. "In fact, I'm beginning to fear that this confusion will go on for a long time. "
  86. "And all because he writes down what I said incorrectly.",
  87. "I had the pleasure of meeting that young man at the Patriarch's Ponds. "
  88. "He almost drove me mad myself, proving to me that I don't exist. But you do believe that it is really I?",
  89. "He was a dreamer, a thinker, a speculative philosopher... or, as his wife would have it, an idiot.",
  90. "The only way to get ideas for stories is to drink way too much coffee and buy a desk that doesn't "
  91. "collapse when you beat your head against it",
  92. ""
  93. };
  94. for (unsigned i = 0; i < sizeof(DATA) / sizeof(DATA[0]); i++)
  95. {
  96. std::cout << "Size of test data chunk " << i << ": " << DATA[i].length() << std::endl;
  97. }
  98. const Transfer transfers[8] =
  99. {
  100. emulator.makeTransfer(0, uavcan::TransferTypeMessageBroadcast, 10, DATA[0], TYPES[0]),
  101. emulator.makeTransfer(5, uavcan::TransferTypeMessageBroadcast, 11, DATA[1], TYPES[1]),
  102. emulator.makeTransfer(10, uavcan::TransferTypeServiceRequest, 12, DATA[2], TYPES[2]),
  103. emulator.makeTransfer(15, uavcan::TransferTypeServiceResponse, 13, DATA[4], TYPES[3]),
  104. emulator.makeTransfer(20, uavcan::TransferTypeMessageBroadcast, 14, DATA[3], TYPES[0]),
  105. emulator.makeTransfer(25, uavcan::TransferTypeMessageBroadcast, 15, DATA[5], TYPES[1]),
  106. // Wrongly addressed:
  107. emulator.makeTransfer(29, uavcan::TransferTypeServiceResponse, 10, DATA[0], TYPES[3], 100),
  108. emulator.makeTransfer(31, uavcan::TransferTypeServiceRequest, 11, DATA[4], TYPES[2], 101)
  109. };
  110. /*
  111. * Registration
  112. */
  113. for (int i = 0; i < NumSubscribers; i++)
  114. {
  115. ASSERT_FALSE(dispatcher.hasSubscriber(subscribers[i]->getDataTypeDescriptor().getID()));
  116. ASSERT_FALSE(dispatcher.hasPublisher(subscribers[i]->getDataTypeDescriptor().getID()));
  117. ASSERT_FALSE(dispatcher.hasServer(subscribers[i]->getDataTypeDescriptor().getID()));
  118. }
  119. ASSERT_TRUE(dispatcher.registerMessageListener(subscribers[0].get()));
  120. ASSERT_TRUE(dispatcher.registerMessageListener(subscribers[1].get()));
  121. ASSERT_TRUE(dispatcher.registerMessageListener(subscribers[2].get()));
  122. ASSERT_TRUE(dispatcher.registerServiceRequestListener(subscribers[3].get()));
  123. ASSERT_TRUE(dispatcher.registerServiceResponseListener(subscribers[4].get()));
  124. ASSERT_TRUE(dispatcher.registerServiceResponseListener(subscribers[5].get()));
  125. for (int i = 0; i < NumSubscribers; i++)
  126. {
  127. ASSERT_FALSE(dispatcher.hasPublisher(subscribers[i]->getDataTypeDescriptor().getID()));
  128. }
  129. // Subscribers
  130. ASSERT_TRUE(dispatcher.hasSubscriber(subscribers[0]->getDataTypeDescriptor().getID()));
  131. ASSERT_TRUE(dispatcher.hasSubscriber(subscribers[1]->getDataTypeDescriptor().getID()));
  132. ASSERT_TRUE(dispatcher.hasSubscriber(subscribers[2]->getDataTypeDescriptor().getID()));
  133. // Servers
  134. ASSERT_TRUE(dispatcher.hasServer(subscribers[3]->getDataTypeDescriptor().getID()));
  135. /*
  136. * Sending the transfers
  137. */
  138. // Multiple service request listeners are not allowed
  139. ASSERT_FALSE(dispatcher.registerServiceRequestListener(subscribers[3].get()));
  140. // Item count validation
  141. ASSERT_EQ(3, dispatcher.getNumMessageListeners());
  142. ASSERT_EQ(1, dispatcher.getNumServiceRequestListeners());
  143. ASSERT_EQ(2, dispatcher.getNumServiceResponseListeners());
  144. for (int i = 0; i < NumSubscribers; i++)
  145. {
  146. ASSERT_TRUE(subscribers[i]->isEmpty());
  147. }
  148. emulator.send(transfers);
  149. emulator.send(transfers); // Just for fun, they will be ignored anyway.
  150. while (true)
  151. {
  152. const int res = dispatcher.spinOnce();
  153. ASSERT_LE(0, res);
  154. clockmock.advance(100);
  155. if (res == 0)
  156. {
  157. break;
  158. }
  159. }
  160. /*
  161. * Matching.
  162. */
  163. ASSERT_TRUE(subscribers[0]->matchAndPop(transfers[4]));
  164. ASSERT_TRUE(subscribers[0]->matchAndPop(transfers[0]));
  165. ASSERT_TRUE(subscribers[1]->matchAndPop(transfers[4]));
  166. ASSERT_TRUE(subscribers[1]->matchAndPop(transfers[0]));
  167. ASSERT_TRUE(subscribers[2]->matchAndPop(transfers[5]));
  168. ASSERT_TRUE(subscribers[2]->matchAndPop(transfers[1]));
  169. ASSERT_TRUE(subscribers[3]->matchAndPop(transfers[2]));
  170. ASSERT_TRUE(subscribers[4]->matchAndPop(transfers[3]));
  171. ASSERT_TRUE(subscribers[5]->matchAndPop(transfers[3]));
  172. for (int i = 0; i < NumSubscribers; i++)
  173. {
  174. ASSERT_TRUE(subscribers[i]->isEmpty());
  175. }
  176. /*
  177. * Unregistering all transfers
  178. */
  179. dispatcher.unregisterMessageListener(subscribers[0].get());
  180. dispatcher.unregisterMessageListener(subscribers[1].get());
  181. dispatcher.unregisterMessageListener(subscribers[2].get());
  182. dispatcher.unregisterServiceRequestListener(subscribers[3].get());
  183. dispatcher.unregisterServiceResponseListener(subscribers[4].get());
  184. dispatcher.unregisterServiceResponseListener(subscribers[5].get());
  185. ASSERT_EQ(0, dispatcher.getNumMessageListeners());
  186. ASSERT_EQ(0, dispatcher.getNumServiceRequestListeners());
  187. ASSERT_EQ(0, dispatcher.getNumServiceResponseListeners());
  188. /*
  189. * Perf counters
  190. */
  191. EXPECT_LT(0, dispatcher.getTransferPerfCounter().getErrorCount()); // Repeated transfers
  192. EXPECT_EQ(0, dispatcher.getTransferPerfCounter().getTxTransferCount());
  193. EXPECT_EQ(9, dispatcher.getTransferPerfCounter().getRxTransferCount());
  194. /*
  195. * RX listener
  196. */
  197. std::cout << "Num received frames: " << rx_listener.rx_frames.size() << std::endl;
  198. ASSERT_EQ(292, rx_listener.rx_frames.size());
  199. }
  200. TEST(Dispatcher, Transmission)
  201. {
  202. uavcan::PoolAllocator<uavcan::MemPoolBlockSize * 8, uavcan::MemPoolBlockSize> pool;
  203. SystemClockMock clockmock(100);
  204. CanDriverMock driver(2, clockmock);
  205. uavcan::Dispatcher dispatcher(driver, pool, clockmock);
  206. ASSERT_TRUE(dispatcher.setNodeID(SELF_NODE_ID)); // Can be set only once
  207. ASSERT_FALSE(dispatcher.setNodeID(SELF_NODE_ID));
  208. /*
  209. * RX listener
  210. */
  211. RxFrameListener rx_listener;
  212. dispatcher.installRxFrameListener(&rx_listener);
  213. /*
  214. * Transmission
  215. */
  216. static const uavcan::MonotonicTime TX_DEADLINE = tsMono(123456);
  217. // uint_fast16_t data_type_id, TransferType transfer_type, NodeID src_node_id, NodeID dst_node_id,
  218. // uint_fast8_t frame_index, TransferID transfer_id, bool last_frame = false
  219. uavcan::Frame frame(123, uavcan::TransferTypeServiceRequest, SELF_NODE_ID, 2, 0);
  220. frame.setPayload(reinterpret_cast<const uint8_t*>("123"), 3);
  221. ASSERT_FALSE(dispatcher.hasPublisher(123));
  222. ASSERT_FALSE(dispatcher.hasPublisher(456));
  223. const uavcan::OutgoingTransferRegistryKey otr_key(123, uavcan::TransferTypeMessageBroadcast, 0);
  224. ASSERT_TRUE(dispatcher.getOutgoingTransferRegistry().accessOrCreate(otr_key,
  225. uavcan::MonotonicTime::fromMSec(1000000)));
  226. ASSERT_TRUE(dispatcher.hasPublisher(123));
  227. ASSERT_FALSE(dispatcher.hasPublisher(456));
  228. ASSERT_EQ(2, dispatcher.send(frame, TX_DEADLINE, tsMono(0), uavcan::CanTxQueue::Volatile, 0, 0xFF));
  229. /*
  230. * Validation
  231. */
  232. uavcan::CanFrame expected_can_frame;
  233. ASSERT_TRUE(frame.compile(expected_can_frame));
  234. ASSERT_TRUE(driver.ifaces.at(0).matchAndPopTx(expected_can_frame, TX_DEADLINE));
  235. ASSERT_TRUE(driver.ifaces.at(1).matchAndPopTx(expected_can_frame, TX_DEADLINE));
  236. ASSERT_TRUE(driver.ifaces.at(0).tx.empty());
  237. ASSERT_TRUE(driver.ifaces.at(1).tx.empty());
  238. /*
  239. * Perf counters - all empty because dispatcher itself does not count TX transfers
  240. */
  241. EXPECT_EQ(0, dispatcher.getTransferPerfCounter().getErrorCount());
  242. EXPECT_EQ(0, dispatcher.getTransferPerfCounter().getTxTransferCount());
  243. EXPECT_EQ(0, dispatcher.getTransferPerfCounter().getRxTransferCount());
  244. /*
  245. * RX listener
  246. */
  247. ASSERT_TRUE(rx_listener.rx_frames.empty());
  248. }
  249. TEST(Dispatcher, Spin)
  250. {
  251. NullAllocator poolmgr;
  252. SystemClockMock clockmock(100);
  253. CanDriverMock driver(2, clockmock);
  254. uavcan::Dispatcher dispatcher(driver, poolmgr, clockmock);
  255. ASSERT_TRUE(dispatcher.setNodeID(SELF_NODE_ID)); // Can be set only once
  256. ASSERT_FALSE(dispatcher.setNodeID(SELF_NODE_ID));
  257. clockmock.monotonic_auto_advance = 100;
  258. ASSERT_EQ(100, clockmock.monotonic);
  259. ASSERT_EQ(0, dispatcher.spin(tsMono(1000)));
  260. ASSERT_LE(1000, clockmock.monotonic);
  261. ASSERT_EQ(0, dispatcher.spinOnce());
  262. ASSERT_LE(1000, clockmock.monotonic);
  263. ASSERT_EQ(0, dispatcher.spin(tsMono(1100)));
  264. ASSERT_LE(1100, clockmock.monotonic);
  265. }
  266. struct DispatcherTestLoopbackFrameListener : public uavcan::LoopbackFrameListenerBase
  267. {
  268. uavcan::RxFrame last_frame;
  269. unsigned count;
  270. DispatcherTestLoopbackFrameListener(uavcan::Dispatcher& dispatcher)
  271. : uavcan::LoopbackFrameListenerBase(dispatcher)
  272. , count(0)
  273. { }
  274. using uavcan::LoopbackFrameListenerBase::startListening;
  275. using uavcan::LoopbackFrameListenerBase::isListening;
  276. void handleLoopbackFrame(const uavcan::RxFrame& frame)
  277. {
  278. std::cout << "DispatcherTestLoopbackFrameListener: " << frame.toString() << std::endl;
  279. last_frame = frame;
  280. count++;
  281. }
  282. };
  283. TEST(Dispatcher, Loopback)
  284. {
  285. NullAllocator poolmgr;
  286. SystemClockMock clockmock(100);
  287. CanDriverMock driver(2, clockmock);
  288. uavcan::Dispatcher dispatcher(driver, poolmgr, clockmock);
  289. ASSERT_TRUE(dispatcher.setNodeID(SELF_NODE_ID));
  290. {
  291. DispatcherTestLoopbackFrameListener listener(dispatcher);
  292. ASSERT_FALSE(listener.isListening());
  293. listener.startListening();
  294. ASSERT_TRUE(listener.isListening());
  295. // uint_fast16_t data_type_id, TransferType transfer_type, NodeID src_node_id, NodeID dst_node_id,
  296. // uint_fast8_t frame_index, TransferID transfer_id, bool last_frame = false
  297. uavcan::Frame frame(123, uavcan::TransferTypeServiceResponse, SELF_NODE_ID, 2, 0);
  298. frame.setPayload(reinterpret_cast<const uint8_t*>("123"), 3);
  299. ASSERT_TRUE(listener.last_frame == uavcan::RxFrame());
  300. ASSERT_LE(0, dispatcher.send(frame, tsMono(1000), tsMono(0), uavcan::CanTxQueue::Persistent,
  301. uavcan::CanIOFlagLoopback, 0xFF));
  302. ASSERT_EQ(0, dispatcher.spin(tsMono(1000)));
  303. ASSERT_TRUE(listener.last_frame != uavcan::RxFrame());
  304. ASSERT_TRUE(listener.last_frame == frame);
  305. ASSERT_EQ(1, listener.last_frame.getIfaceIndex()); // Last iface
  306. ASSERT_EQ(2, listener.count);
  307. ASSERT_EQ(1, dispatcher.getLoopbackFrameListenerRegistry().getNumListeners());
  308. }
  309. ASSERT_EQ(0, dispatcher.getLoopbackFrameListenerRegistry().getNumListeners());
  310. }