transfer_listener.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #include <gtest/gtest.h>
7 #include "../clock.hpp"
8 
9 
11 {
14 
15 public:
17  uavcan::NodeID dst_node_id = 127)
18  : IncomingTransferEmulatorBase(dst_node_id)
19  , target_(target)
20  , data_type_(type)
21  { }
22 
23  void sendOneFrame(const uavcan::RxFrame& frame) { target_.handleFrame(frame); }
24 
26  uint8_t source_node_id, const std::string& payload)
27  {
28  return IncomingTransferEmulatorBase::makeTransfer(priority, transfer_type, source_node_id, payload, data_type_);
29  }
30 };
31 
32 
33 TEST(TransferListener, BasicMFT)
34 {
36 
37  static const int NUM_POOL_BLOCKS = 100;
39 
41  TestListener subscriber(perf, type, 256, pool);
42 
43  /*
44  * Test data
45  */
46  static const std::string DATA[] =
47  {
48  "Build a man a fire, and he'll be warm for a day. "
49  "Set a man on fire, and he'll be warm for the rest of his life.",
50 
51  "123456789",
52 
53  "In the beginning there was nothing, which exploded.",
54 
55  "The USSR, which they'd begun to renovate and improve at about the time when Tatarsky decided to "
56  "change his profession, improved so much that it ceased to exist",
57 
58  "BEWARE JET BLAST"
59  };
60 
61  for (unsigned i = 0; i < sizeof(DATA) / sizeof(DATA[0]); i++)
62  {
63  std::cout << "Size of test data chunk " << i << ": " << DATA[i].length() << std::endl;
64  }
65 
66  TransferListenerEmulator emulator(subscriber, type);
67  const Transfer transfers[] =
68  {
69  emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 1, DATA[0]),
70  emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 2, DATA[1]), // Same NID
71  emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 3, DATA[2]),
72  emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest, 4, DATA[3]),
73  emulator.makeTransfer(16, uavcan::TransferTypeServiceResponse, 5, DATA[4]),
74  };
75 
76  /*
77  * Sending concurrently
78  * Expected reception order: 1, 4, 2, 0, 3
79  */
80  emulator.send(transfers);
81 
82  ASSERT_TRUE(subscriber.matchAndPop(transfers[1]));
83  ASSERT_TRUE(subscriber.matchAndPop(transfers[4]));
84  ASSERT_TRUE(subscriber.matchAndPop(transfers[2]));
85  ASSERT_TRUE(subscriber.matchAndPop(transfers[0]));
86  ASSERT_TRUE(subscriber.matchAndPop(transfers[3]));
87 
88  ASSERT_TRUE(subscriber.isEmpty());
89 }
90 
91 
92 TEST(TransferListener, CrcFailure)
93 {
95 
96  static const int NUM_POOL_BLOCKS = 100;
99  TestListener subscriber(perf, type, 256, poolmgr); // Static buffer only, 2 entries
100 
101  /*
102  * Generating transfers with damaged payload (CRC is not valid)
103  */
104  TransferListenerEmulator emulator(subscriber, type);
105  const Transfer tr_mft = emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 42, "123456789abcdefghik");
106  const Transfer tr_sft = emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 11, "abcd");
107 
108  std::vector<uavcan::RxFrame> ser_mft = serializeTransfer(tr_mft);
109  std::vector<uavcan::RxFrame> ser_sft = serializeTransfer(tr_sft);
110 
111  ASSERT_TRUE(ser_mft.size() > 1);
112  ASSERT_TRUE(ser_sft.size() == 1);
113 
114  const_cast<uint8_t*>(ser_mft[1].getPayloadPtr())[1] = uint8_t(~ser_mft[1].getPayloadPtr()[1]); // CRC invalid now
115  const_cast<uint8_t*>(ser_sft[0].getPayloadPtr())[2] = uint8_t(~ser_sft[0].getPayloadPtr()[2]); // no CRC here
116 
117  /*
118  * Sending and making sure that MFT was not received, but SFT was.
119  */
120  std::vector<std::vector<uavcan::RxFrame> > sers;
121  sers.push_back(ser_mft);
122  sers.push_back(ser_sft);
123  sers.push_back(ser_mft); // Ignored
124  sers.push_back(ser_sft); // Ignored
125 
126  emulator.send(sers);
127 
128  Transfer tr_sft_damaged = tr_sft;
129  tr_sft_damaged.payload[2] = char(~tr_sft.payload[2]); // Damaging the data similarly, so that it can be matched
130 
131  ASSERT_TRUE(subscriber.matchAndPop(tr_sft_damaged));
132  ASSERT_TRUE(subscriber.isEmpty());
133 }
134 
135 
136 TEST(TransferListener, BasicSFT)
137 {
139 
140  static const int NUM_POOL_BLOCKS = 100;
143  TestListener subscriber(perf, type, 0, poolmgr); // Max buf size is 0, i.e. SFT-only
144 
145  TransferListenerEmulator emulator(subscriber, type);
146  const Transfer transfers[] =
147  {
148  emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 1, "123"),
149  emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest, 1, "456"), // Same NID
151  emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest, 3, "abc"),
153  emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest, 2, "foo"), // Same as 2, not ignored
154  emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest, 2, "123456789abc"), // Same as 2, not SFT - ignore
155  emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest, 2, "bar"), // Same as 2, not ignored
156  };
157 
158  emulator.send(transfers);
159 
160  ASSERT_TRUE(subscriber.matchAndPop(transfers[0]));
161  ASSERT_TRUE(subscriber.matchAndPop(transfers[1]));
162  ASSERT_TRUE(subscriber.matchAndPop(transfers[2]));
163  ASSERT_TRUE(subscriber.matchAndPop(transfers[3]));
164  ASSERT_TRUE(subscriber.matchAndPop(transfers[4]));
165  ASSERT_TRUE(subscriber.matchAndPop(transfers[5]));
166  ASSERT_TRUE(subscriber.matchAndPop(transfers[7]));
167 
168  ASSERT_TRUE(subscriber.isEmpty());
169 }
170 
171 
172 TEST(TransferListener, Cleanup)
173 {
175 
176  static const int NUM_POOL_BLOCKS = 100;
179  TestListener subscriber(perf, type, 256, poolmgr);
180 
181  /*
182  * Generating transfers
183  */
184  TransferListenerEmulator emulator(subscriber, type);
185  const Transfer tr_mft = emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 42, "123456789abcdefghik");
186  const Transfer tr_sft = emulator.makeTransfer(16, uavcan::TransferTypeServiceResponse, 11, "abcd");
187 
188  const std::vector<uavcan::RxFrame> ser_mft = serializeTransfer(tr_mft);
189  const std::vector<uavcan::RxFrame> ser_sft = serializeTransfer(tr_sft);
190 
191  ASSERT_TRUE(ser_mft.size() > 1);
192  ASSERT_TRUE(ser_sft.size() == 1);
193 
194  const std::vector<uavcan::RxFrame> ser_mft_begin(ser_mft.begin(), ser_mft.begin() + 1);
195 
196  /*
197  * Sending the first part and SFT
198  */
199  std::vector<std::vector<uavcan::RxFrame> > sers;
200  sers.push_back(ser_mft_begin); // Only the first part
201  sers.push_back(ser_sft);
202 
203  emulator.send(sers);
204 
205  ASSERT_TRUE(subscriber.matchAndPop(tr_sft));
206  ASSERT_TRUE(subscriber.isEmpty());
207 
208  /*
209  * Cleanup with huge timestamp value will remove all entries
210  */
211  static_cast<uavcan::TransferListener&>(subscriber).cleanup(tsMono(100000000));
212 
213  /*
214  * Sending the same transfers again - they will be accepted since registres were cleared
215  */
216  sers.clear();
217  sers.push_back(ser_mft); // Complete transfer
218  sers.push_back(ser_sft);
219 
220  emulator.send(sers);
221 
222  ASSERT_TRUE(subscriber.matchAndPop(tr_sft));
223  ASSERT_TRUE(subscriber.matchAndPop(tr_mft));
224  ASSERT_TRUE(subscriber.isEmpty());
225 }
226 
227 
228 TEST(TransferListener, AnonymousTransfers)
229 {
231 
232  static const int NUM_POOL_BLOCKS = 100;
235  TestListener subscriber(perf, type, 0, poolmgr);
236 
237  TransferListenerEmulator emulator(subscriber, type);
238  const Transfer transfers[] =
239  {
240  emulator.makeTransfer(16, uavcan::TransferTypeServiceRequest, 0, "1234567"), // Invalid - not broadcast
241  emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 0, "1234567"), // Valid
242  emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 0, "12345678"), // Invalid - not SFT
243  emulator.makeTransfer(16, uavcan::TransferTypeMessageBroadcast, 0, "") // Valid
244  };
245 
246  emulator.send(transfers);
247 
248  // Nothing will be received, because anonymous transfers are disabled by default
249  ASSERT_TRUE(subscriber.isEmpty());
250 
251  subscriber.allowAnonymousTransfers();
252 
253  // Re-send everything again
254  emulator.send(transfers);
255 
256  // Now the anonymous transfers are enabled
257  ASSERT_TRUE(subscriber.matchAndPop(transfers[1])); // Only SFT broadcast will be accepted
258  ASSERT_TRUE(subscriber.matchAndPop(transfers[3]));
259 
260  ASSERT_TRUE(subscriber.isEmpty());
261 }
262 
263 TEST(TransferListener, Sizes)
264 {
265  using namespace uavcan;
266 
267  std::cout << "sizeof(TransferListener): " << sizeof(TransferListener) << std::endl;
268 }
TEST(TransferListener, BasicMFT)
std::uint8_t uint8_t
Definition: std.hpp:24
bool matchAndPop(const Transfer &reference)
TransferListenerEmulator(uavcan::TransferListener &target, const uavcan::DataTypeDescriptor &type, uavcan::NodeID dst_node_id=127)
uavcan::TransferListener & target_
void send(const std::vector< std::vector< uavcan::RxFrame > > &sers)
Transfer makeTransfer(uavcan::TransferPriority priority, uavcan::TransferType transfer_type, uint8_t source_node_id, const std::string &payload)
virtual void handleFrame(const RxFrame &frame)
Transfer makeTransfer(uavcan::TransferPriority priority, uavcan::TransferType transfer_type, uint8_t source_node_id, const std::string &payload, const uavcan::DataTypeDescriptor &type, uavcan::NodeID dst_node_id_override=uavcan::NodeID())
void sendOneFrame(const uavcan::RxFrame &frame)
TransferType
Definition: transfer.hpp:18
uavcan::MonotonicTime tsMono(uint64_t usec)
uavcan::CanFrame frame
Definition: can.cpp:78
std::string payload
const uavcan::DataTypeDescriptor data_type_


uavcan_communicator
Author(s):
autogenerated on Wed Jan 11 2023 03:59:40