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


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