transfer_test_helpers.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #pragma once
6 
7 #include <algorithm>
8 #include <queue>
9 #include <vector>
10 #include <gtest/gtest.h>
12 
16 struct Transfer
17 {
26  std::string payload;
27 
29  : ts_monotonic(tr.getMonotonicTimestamp())
30  , ts_utc(tr.getUtcTimestamp())
31  , priority(tr.getPriority())
32  , transfer_type(tr.getTransferType())
33  , transfer_id(tr.getTransferID())
34  , src_node_id(tr.getSrcNodeID())
35  , dst_node_id() // default is invalid
37  {
38  unsigned offset = 0;
39  while (true)
40  {
41  uint8_t buf[256];
42  int res = tr.read(offset, buf, sizeof(buf));
43  if (res < 0)
44  {
45  std::cout << "IncomingTransferContainer: read failure " << res << std::endl;
46  exit(1);
47  }
48  if (res == 0)
49  {
50  break;
51  }
52  payload += std::string(reinterpret_cast<const char*>(buf), unsigned(res));
53  offset += unsigned(res);
54  }
55  }
56 
61  , ts_utc(ts_utc)
68  , payload(payload)
69  { }
70 
74  : ts_monotonic(uavcan::MonotonicTime::fromUSec(ts_monotonic))
75  , ts_utc(uavcan::UtcTime::fromUSec(ts_utc))
82  , payload(payload)
83  { }
84 
85  bool operator==(const Transfer& rhs) const
86  {
87  return
88  (ts_monotonic == rhs.ts_monotonic) &&
89  ((!ts_utc.isZero() && !rhs.ts_utc.isZero()) ? (ts_utc == rhs.ts_utc) : true) &&
90  (priority == rhs.priority) &&
91  (transfer_type == rhs.transfer_type) &&
92  (transfer_id == rhs.transfer_id) &&
93  (src_node_id == rhs.src_node_id) &&
94  ((dst_node_id.isValid() && rhs.dst_node_id.isValid()) ? (dst_node_id == rhs.dst_node_id) : true) &&
95  (data_type == rhs.data_type) &&
96  (payload == rhs.payload);
97  }
98 
99  std::string toString() const
100  {
101  std::ostringstream os;
102  os << "ts_m=" << ts_monotonic
103  << " ts_utc=" << ts_utc
104  << " prio=" << int(priority.get())
105  << " tt=" << int(transfer_type)
106  << " tid=" << int(transfer_id.get())
107  << " snid=" << int(src_node_id.get())
108  << " dnid=" << int(dst_node_id.get())
109  << " dtid=" << int(data_type.getID().get())
110  << "\n\t'" << payload << "'";
111  return os.str();
112  }
113 };
114 
121 {
123 
124  std::queue<Transfer> transfers_;
125 
126 public:
128  uavcan::uint16_t max_buffer_size, uavcan::IPoolAllocator& allocator)
129  : Base(perf, data_type, max_buffer_size, allocator)
130  { }
131 
133  {
134  const Transfer rx(transfer, Base::getDataTypeDescriptor());
135  transfers_.push(rx);
136  std::cout << "Received transfer: " << rx.toString() << std::endl;
137 
138  const bool single_frame = dynamic_cast<uavcan::SingleFrameIncomingTransfer*>(&transfer) != UAVCAN_NULLPTR;
139 
140  const bool anonymous = single_frame &&
141  transfer.getSrcNodeID().isBroadcast() &&
143 
144  ASSERT_EQ(anonymous, transfer.isAnonymousTransfer());
145  }
146 
147  bool matchAndPop(const Transfer& reference)
148  {
149  if (transfers_.empty())
150  {
151  std::cout << "No received transfers" << std::endl;
152  return false;
153  }
154 
155  const Transfer tr = transfers_.front();
156  transfers_.pop();
157 
158  const bool res = (tr == reference);
159  if (!res)
160  {
161  std::cout << "TestSubscriber: Transfer mismatch:\n"
162  << "Expected: " << reference.toString() << "\n"
163  << "Received: " << tr.toString() << std::endl;
164  }
165  return res;
166  }
167 
168  unsigned getNumReceivedTransfers() const { return static_cast<unsigned>(transfers_.size()); }
169  bool isEmpty() const { return transfers_.empty(); }
170 };
171 
172 
173 namespace
174 {
175 
176 std::vector<uavcan::RxFrame> serializeTransfer(const Transfer& transfer)
177 {
178  const bool need_crc = transfer.payload.length() > (sizeof(uavcan::CanFrame::data) - 1);
179 
180  std::vector<uint8_t> raw_payload;
181  if (need_crc)
182  {
183  uavcan::TransferCRC payload_crc = transfer.data_type.getSignature().toTransferCRC();
184  payload_crc.add(reinterpret_cast<const uint8_t*>(transfer.payload.c_str()), uint16_t(transfer.payload.length()));
185  // Little endian
186  raw_payload.push_back(uint8_t(payload_crc.get() & 0xFF));
187  raw_payload.push_back(uint8_t((payload_crc.get() >> 8) & 0xFF));
188  }
189  raw_payload.insert(raw_payload.end(), transfer.payload.begin(), transfer.payload.end());
190 
191  std::vector<uavcan::RxFrame> output;
192  unsigned offset = 0;
193  uavcan::MonotonicTime ts_monotonic = transfer.ts_monotonic;
194  uavcan::UtcTime ts_utc = transfer.ts_utc;
195 
196  uavcan::Frame frm(transfer.data_type.getID(), transfer.transfer_type, transfer.src_node_id,
197  transfer.dst_node_id, transfer.transfer_id);
198  frm.setStartOfTransfer(true);
199  frm.setPriority(transfer.priority);
200 
201  while (true)
202  {
203  const int bytes_left = int(raw_payload.size()) - int(offset);
204  EXPECT_TRUE(bytes_left >= 0);
205 
206  const int spres = frm.setPayload(&*(raw_payload.begin() + offset), unsigned(bytes_left));
207  if (spres < 0)
208  {
209  std::cerr << ">_<" << std::endl;
210  std::exit(1);
211  }
212  if (spres == bytes_left)
213  {
214  frm.setEndOfTransfer(true);
215  }
216 
217  offset += unsigned(spres);
218 
219  const uavcan::RxFrame rxfrm(frm, ts_monotonic, ts_utc, 0);
220  ts_monotonic += uavcan::MonotonicDuration::fromUSec(1);
221  ts_utc += uavcan::UtcDuration::fromUSec(1);
222 
223  output.push_back(rxfrm);
224  if (frm.isEndOfTransfer())
225  {
226  break;
227  }
228 
229  frm.setStartOfTransfer(false);
230  frm.flipToggle();
231  }
232  return output;
233 }
234 
235 inline uavcan::DataTypeDescriptor makeDataType(uavcan::DataTypeKind kind, uint16_t id, const char* name = "")
236 {
237  const uavcan::DataTypeSignature signature((uint64_t(kind) << 16) | uint16_t(id << 8) | uint16_t(id & 0xFF));
238  return uavcan::DataTypeDescriptor(kind, id, signature, name);
239 }
240 
241 }
242 
243 
245 {
249 
250 public:
252  : dst_node_id_(dst_node_id)
253  { }
254 
256 
258  uint8_t source_node_id, const std::string& payload, const uavcan::DataTypeDescriptor& type,
259  uavcan::NodeID dst_node_id_override = uavcan::NodeID())
260  {
262  const uavcan::UtcTime utc = uavcan::UtcTime::fromUSec(ts_.toUSec() + 1000000000ul);
263  const uavcan::NodeID dst_node_id = (transfer_type == uavcan::TransferTypeMessageBroadcast) ?
265  (dst_node_id_override.isValid() ? dst_node_id_override : dst_node_id_);
266  const Transfer tr(ts_, utc, priority, transfer_type, tid_, source_node_id, dst_node_id, payload, type);
267  tid_.increment();
268  return tr;
269  }
270 
271  virtual void sendOneFrame(const uavcan::RxFrame& frame) = 0;
272 
273  void send(const std::vector<std::vector<uavcan::RxFrame> >& sers)
274  {
275  unsigned index = 0;
276  while (true)
277  {
278  // Sending all transfers concurrently
279  bool all_empty = true;
280  for (std::vector<std::vector<uavcan::RxFrame> >::const_iterator it = sers.begin(); it != sers.end(); ++it)
281  {
282  if (it->size() <= index)
283  {
284  continue;
285  }
286  all_empty = false;
287  std::cout << "Incoming Transfer Emulator: Sending: " << it->at(index).toString() << std::endl;
288  sendOneFrame(it->at(index));
289  }
290  index++;
291  if (all_empty)
292  {
293  break;
294  }
295  }
296  }
297 
298  void send(const Transfer* transfers, unsigned num_transfers)
299  {
300  std::vector<std::vector<uavcan::RxFrame> > sers;
301  while (num_transfers--)
302  {
303  sers.push_back(serializeTransfer(*transfers++));
304  }
305  send(sers);
306  }
307 
308  template <int SIZE> void send(const Transfer (&transfers)[SIZE]) { send(transfers, SIZE); }
309 };
310 
315 {
316 public:
317  virtual void* allocate(std::size_t) { return UAVCAN_NULLPTR; }
318  virtual void deallocate(const void*) { }
319  virtual uint16_t getBlockCapacity() const { return 0; }
320 };
IncomingTransferEmulatorBase::send
void send(const std::vector< std::vector< uavcan::RxFrame > > &sers)
Definition: transfer_test_helpers.hpp:273
uavcan::TransferListener::getDataTypeDescriptor
const DataTypeDescriptor & getDataTypeDescriptor() const
Definition: transfer_listener.hpp:143
UAVCAN_NULLPTR
#define UAVCAN_NULLPTR
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:51
Transfer::operator==
bool operator==(const Transfer &rhs) const
Definition: transfer_test_helpers.hpp:85
Transfer::src_node_id
uavcan::NodeID src_node_id
Definition: transfer_test_helpers.hpp:23
IncomingTransferEmulatorBase::makeTransfer
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())
Definition: transfer_test_helpers.hpp:257
uavcan::uint64_t
std::uint64_t uint64_t
Definition: std.hpp:27
uavcan::NodeID::isValid
bool isValid() const
Definition: transfer.hpp:134
std::size_t
unsigned long size_t
Definition: coverity_scan_model.cpp:19
IncomingTransferEmulatorBase::ts_
uavcan::MonotonicTime ts_
Definition: transfer_test_helpers.hpp:246
TestListener::TestListener
TestListener(uavcan::TransferPerfCounter &perf, const uavcan::DataTypeDescriptor &data_type, uavcan::uint16_t max_buffer_size, uavcan::IPoolAllocator &allocator)
Definition: transfer_test_helpers.hpp:127
uavcan::UtcTime
Implicitly convertible to/from uavcan.Timestamp.
Definition: time.hpp:191
uavcan::NodeID::get
uint8_t get() const
Definition: transfer.hpp:132
uavcan::NodeID
Definition: transfer.hpp:112
uavcan::TransferType
TransferType
Definition: transfer.hpp:18
Transfer::ts_utc
uavcan::UtcTime ts_utc
Definition: transfer_test_helpers.hpp:19
TestListener::matchAndPop
bool matchAndPop(const Transfer &reference)
Definition: transfer_test_helpers.hpp:147
uavcan::IncomingTransfer
Definition: transfer_listener.hpp:24
uavcan::TransferCRC::add
void add(uint8_t byte)
Definition: crc.hpp:60
TestListener::Base
uavcan::TransferListener Base
Definition: transfer_test_helpers.hpp:122
uavcan::DataTypeSignature::toTransferCRC
TransferCRC toTransferCRC() const
Definition: uc_data_type.cpp:85
IncomingTransferEmulatorBase::~IncomingTransferEmulatorBase
virtual ~IncomingTransferEmulatorBase()
Definition: transfer_test_helpers.hpp:255
IncomingTransferEmulatorBase::sendOneFrame
virtual void sendOneFrame(const uavcan::RxFrame &frame)=0
TestListener
Definition: transfer_test_helpers.hpp:120
Transfer::toString
std::string toString() const
Definition: transfer_test_helpers.hpp:99
Transfer::ts_monotonic
uavcan::MonotonicTime ts_monotonic
Definition: transfer_test_helpers.hpp:18
uavcan::TransferID::get
uint8_t get() const
Definition: transfer.hpp:99
IncomingTransferEmulatorBase::send
void send(const Transfer(&transfers)[SIZE])
Definition: transfer_test_helpers.hpp:308
uavcan::uint16_t
std::uint16_t uint16_t
Definition: std.hpp:25
Transfer
Definition: transfer_test_helpers.hpp:16
uavcan::TransferPerfCounter
Definition: perf_counter.hpp:36
uavcan::TransferID
Definition: transfer.hpp:71
uavcan::TimeBase< UtcTime, UtcDuration >::fromUSec
static UtcTime fromUSec(uint64_t us)
Definition: time.hpp:112
Transfer::priority
uavcan::TransferPriority priority
Definition: transfer_test_helpers.hpp:20
Transfer::payload
std::string payload
Definition: transfer_test_helpers.hpp:26
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
transfer_listener.hpp
uavcan::DataTypeDescriptor
Definition: data_type.hpp:130
uavcan::TransferTypeMessageBroadcast
@ TransferTypeMessageBroadcast
Definition: transfer.hpp:22
uavcan::RxFrame
Definition: frame.hpp:104
TestListener::transfers_
std::queue< Transfer > transfers_
Definition: transfer_test_helpers.hpp:124
TestListener::handleIncomingTransfer
void handleIncomingTransfer(uavcan::IncomingTransfer &transfer)
Definition: transfer_test_helpers.hpp:132
uavcan::DataTypeID::get
uint16_t get() const
Definition: data_type.hpp:69
Transfer::data_type
uavcan::DataTypeDescriptor data_type
Definition: transfer_test_helpers.hpp:25
IncomingTransferEmulatorBase::send
void send(const Transfer *transfers, unsigned num_transfers)
Definition: transfer_test_helpers.hpp:298
uavcan::TransferPriority::get
uint8_t get() const
Definition: transfer.hpp:62
uavcan::IPoolAllocator
Definition: dynamic_memory.hpp:21
Transfer::Transfer
Transfer(const uavcan::IncomingTransfer &tr, const uavcan::DataTypeDescriptor &data_type)
Definition: transfer_test_helpers.hpp:28
Transfer::transfer_type
uavcan::TransferType transfer_type
Definition: transfer_test_helpers.hpp:21
uavcan::DataTypeKind
DataTypeKind
Definition: data_type.hpp:19
Transfer::dst_node_id
uavcan::NodeID dst_node_id
Definition: transfer_test_helpers.hpp:24
uavcan::TimeBase::isZero
bool isZero() const
Definition: time.hpp:123
uavcan::IncomingTransfer::isAnonymousTransfer
virtual bool isAnonymousTransfer() const
Definition: transfer_listener.hpp:59
Transfer::Transfer
Transfer(uint64_t ts_monotonic, uint64_t ts_utc, uavcan::TransferPriority priority, uavcan::TransferType transfer_type, uavcan::TransferID transfer_id, uavcan::NodeID src_node_id, uavcan::NodeID dst_node_id, const std::string &payload, const uavcan::DataTypeDescriptor &data_type)
Definition: transfer_test_helpers.hpp:71
TestListener::getNumReceivedTransfers
unsigned getNumReceivedTransfers() const
Definition: transfer_test_helpers.hpp:168
NullAllocator
Definition: transfer_test_helpers.hpp:314
uavcan::NodeID::Broadcast
static const NodeID Broadcast
Definition: transfer.hpp:122
uavcan::TransferPriority
Definition: transfer.hpp:28
uavcan::CanFrame::data
uint8_t data[MaxDataLen]
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:35
uavcan::TransferListener
Definition: transfer_listener.hpp:99
uavcan::ITransferBuffer::read
virtual int read(unsigned offset, uint8_t *data, unsigned len) const =0
int
int
Definition: libstubs.cpp:120
NullAllocator::deallocate
virtual void deallocate(const void *)
Definition: transfer_test_helpers.hpp:318
frame
uavcan::CanFrame frame
Definition: can.cpp:78
uavcan::IncomingTransfer::getSrcNodeID
NodeID getSrcNodeID() const
Definition: transfer_listener.hpp:66
NullAllocator::allocate
virtual void * allocate(std::size_t)
Definition: transfer_test_helpers.hpp:317
Transfer::Transfer
Transfer(uavcan::MonotonicTime ts_monotonic, uavcan::UtcTime ts_utc, uavcan::TransferPriority priority, uavcan::TransferType transfer_type, uavcan::TransferID transfer_id, uavcan::NodeID src_node_id, uavcan::NodeID dst_node_id, const std::string &payload, const uavcan::DataTypeDescriptor &data_type)
Definition: transfer_test_helpers.hpp:57
IncomingTransferEmulatorBase::tid_
uavcan::TransferID tid_
Definition: transfer_test_helpers.hpp:247
uavcan::Frame
Definition: frame.hpp:17
IncomingTransferEmulatorBase::dst_node_id_
uavcan::NodeID dst_node_id_
Definition: transfer_test_helpers.hpp:248
uavcan::SingleFrameIncomingTransfer
Definition: transfer_listener.hpp:73
uavcan::DataTypeDescriptor::getID
DataTypeID getID() const
Definition: data_type.hpp:159
Transfer::transfer_id
uavcan::TransferID transfer_id
Definition: transfer_test_helpers.hpp:22
uavcan::MonotonicTime
Definition: time.hpp:184
TestListener::isEmpty
bool isEmpty() const
Definition: transfer_test_helpers.hpp:169
uavcan::DataTypeSignature
Definition: data_type.hpp:107
uavcan
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:204
IncomingTransferEmulatorBase
Definition: transfer_test_helpers.hpp:244
uavcan::DataTypeDescriptor::getSignature
const DataTypeSignature & getSignature() const
Definition: data_type.hpp:160
uavcan::TransferID::increment
void increment()
Definition: transfer.hpp:94
uavcan::TransferCRC
Definition: crc.hpp:28
uavcan::TimeBase::toUSec
uint64_t toUSec() const
Definition: time.hpp:120
uavcan::NodeID::isBroadcast
bool isBroadcast() const
Definition: transfer.hpp:135
IncomingTransferEmulatorBase::IncomingTransferEmulatorBase
IncomingTransferEmulatorBase(uavcan::NodeID dst_node_id)
Definition: transfer_test_helpers.hpp:251
uavcan::IncomingTransfer::getTransferType
TransferType getTransferType() const
Definition: transfer_listener.hpp:64
uavcan::DurationBase< MonotonicDuration >::fromUSec
static MonotonicDuration fromUSec(int64_t us)
Definition: time.hpp:35
uavcan::TransferCRC::get
uint16_t get() const
Definition: crc.hpp:75
NullAllocator::getBlockCapacity
virtual uint16_t getBlockCapacity() const
Definition: transfer_test_helpers.hpp:319


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