test_node.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 #if __GNUC__
8 # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
9 #endif
10 
13 #include <memory>
14 #include <set>
15 #include <queue>
16 #include "../transport/can/can.hpp"
19 
20 struct TestNode : public uavcan::INode
21 {
22  /*
23  * This class used to use the simple pool allocator instead:
24  * uavcan::PoolAllocator<uavcan::MemPoolBlockSize * 1024, uavcan::MemPoolBlockSize> pool;
25  * It has been replaced because unlike the simple allocator, heap-based one is not tested as extensively.
26  * Moreover, heap based allocator prints and error message upon destruction if some memory has not been freed.
27  */
31 
32  TestNode(uavcan::ICanDriver& can_driver, uavcan::ISystemClock& clock_driver, uavcan::NodeID self_node_id) :
33  pool(1024),
34  scheduler(can_driver, pool, clock_driver),
36  {
37  setNodeID(self_node_id);
38  }
39 
40  virtual void registerInternalFailure(const char* msg)
41  {
42  std::cout << "TestNode internal failure: " << msg << std::endl;
44  }
45 
46  virtual uavcan::IPoolAllocator& getAllocator() { return pool; }
47  virtual uavcan::Scheduler& getScheduler() { return scheduler; }
48  virtual const uavcan::Scheduler& getScheduler() const { return scheduler; }
49 };
50 
51 
53 {
55  std::set<PairableCanDriver*> others;
56  std::queue<uavcan::CanFrame> read_queue;
57  std::queue<uavcan::CanFrame> loopback_queue;
59 
61  : clock(clock)
62  , error_count(0)
63  { }
64 
66  {
67  this->others.insert(with);
68  with->others.insert(this);
69  others.erase(this);
70  }
71 
73  {
74  return (iface_index == 0) ? this : UAVCAN_NULLPTR;
75  }
76  virtual const uavcan::ICanIface* getIface(uavcan::uint8_t iface_index) const
77  {
78  return (iface_index == 0) ? this : UAVCAN_NULLPTR;
79  }
80 
81  virtual uavcan::uint8_t getNumIfaces() const { return 1; }
82 
85  uavcan::MonotonicTime blocking_deadline)
86  {
87  if (inout_masks.read == 1)
88  {
89  inout_masks.read = (!read_queue.empty() || !loopback_queue.empty()) ? 1 : 0;
90  }
91  if (inout_masks.read || inout_masks.write)
92  {
93  return 1;
94  }
95  while (clock.getMonotonic() < blocking_deadline)
96  {
97  usleep(1000);
98  }
99  return 0;
100  }
101 
103  {
104  assert(!others.empty());
105  for (std::set<PairableCanDriver*>::iterator it = others.begin(); it != others.end(); ++it)
106  {
107  (*it)->read_queue.push(frame);
108  }
109  if (flags & uavcan::CanIOFlagLoopback)
110  {
111  loopback_queue.push(frame);
112  }
113  return 1;
114  }
115 
116  virtual uavcan::int16_t receive(uavcan::CanFrame& out_frame, uavcan::MonotonicTime& out_ts_monotonic,
117  uavcan::UtcTime& out_ts_utc, uavcan::CanIOFlags& out_flags)
118  {
119  out_flags = 0;
120  if (loopback_queue.empty())
121  {
122  assert(read_queue.size());
123  out_frame = read_queue.front();
124  read_queue.pop();
125  }
126  else
127  {
128  out_flags |= uavcan::CanIOFlagLoopback;
129  out_frame = loopback_queue.front();
130  loopback_queue.pop();
131  }
132  out_ts_monotonic = clock.getMonotonic();
133  out_ts_utc = clock.getUtc();
134  return 1;
135  }
136 
137  void pushRxToAllIfaces(const uavcan::CanFrame& can_frame)
138  {
139  read_queue.push(can_frame);
140  }
141 
143  virtual uavcan::uint16_t getNumFilters() const { return 0; }
144  virtual uavcan::uint64_t getErrorCount() const { return error_count; }
145 };
146 
147 
148 template <typename ClockType>
150 {
151  ClockType clock_a;
152  ClockType clock_b;
157 
159  : can_a(clock_a)
160  , can_b(clock_b)
161  , a(can_a, clock_a, nid_first)
162  , b(can_b, clock_b, nid_second)
163  {
165  }
166 
168  : can_a(clock_a)
169  , can_b(clock_b)
170  , a(can_a, clock_a, 1)
171  , b(can_b, clock_b, 2)
172  {
174  }
175 
177  {
178  assert(!duration.isNegative());
179  unsigned nspins2 = unsigned(duration.toMSec() / 2);
180  nspins2 = nspins2 ? nspins2 : 1;
181  while (nspins2 --> 0)
182  {
184  if (ret < 0)
185  {
186  return ret;
187  }
189  if (ret < 0)
190  {
191  return ret;
192  }
193  }
194  return 0;
195  }
196 };
197 
198 
201 
202 
203 template <unsigned NumNodes>
205 {
207  {
211 
213  : can_driver(clock)
214  , node(can_driver, clock, node_id)
215  { }
216  };
217 
218  std::unique_ptr<NodeEnvironment> nodes[NumNodes];
219 
220  TestNetwork(uavcan::uint8_t first_node_id = 1)
221  {
222  for (uavcan::uint8_t i = 0; i < NumNodes; i++)
223  {
224  nodes[i].reset(new NodeEnvironment(uint8_t(first_node_id + i)));
225  }
226 
227  for (uavcan::uint8_t i = 0; i < NumNodes; i++)
228  {
229  for (uavcan::uint8_t k = 0; k < NumNodes; k++)
230  {
231  nodes[i]->can_driver.linkTogether(&nodes[k]->can_driver);
232  }
233  }
234 
235  for (uavcan::uint8_t i = 0; i < NumNodes; i++)
236  {
237  assert(nodes[i]->can_driver.others.size() == (NumNodes - 1));
238  }
239  }
240 
242  {
243  assert(!duration.isNegative());
244  unsigned nspins = unsigned(duration.toMSec() / NumNodes);
245  nspins = nspins ? nspins : 1;
246  while (nspins --> 0)
247  {
248  for (uavcan::uint8_t i = 0; i < NumNodes; i++)
249  {
250  int ret = nodes[i]->node.spin(uavcan::MonotonicDuration::fromMSec(1));
251  if (ret < 0)
252  {
253  return ret;
254  }
255  }
256  }
257  return 0;
258  }
259 
260  TestNode& operator[](unsigned index)
261  {
262  if (index >= NumNodes)
263  {
264  throw std::out_of_range("No such test node");
265  }
266  return nodes[index]->node;
267  }
268 };
TestNetwork::NodeEnvironment::clock
SystemClockDriver clock
Definition: test_node.hpp:208
InterlinkedTestNodesWithSysClock
InterlinkedTestNodes< SystemClockDriver > InterlinkedTestNodesWithSysClock
Definition: test_node.hpp:199
InterlinkedTestNodes::InterlinkedTestNodes
InterlinkedTestNodes(uavcan::NodeID nid_first, uavcan::NodeID nid_second)
Definition: test_node.hpp:158
subscriber.hpp
TestNode::pool
uavcan::HeapBasedPoolAllocator< uavcan::MemPoolBlockSize > pool
Definition: test_node.hpp:28
UAVCAN_NULLPTR
#define UAVCAN_NULLPTR
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:51
TestNode::internal_failure_count
uint64_t internal_failure_count
Definition: test_node.hpp:30
uavcan::INode::setNodeID
bool setNodeID(NodeID nid)
Definition: abstract_node.hpp:48
PairableCanDriver::PairableCanDriver
PairableCanDriver(uavcan::ISystemClock &clock)
Definition: test_node.hpp:60
uavcan::DurationBase::toMSec
int64_t toMSec() const
Definition: time.hpp:44
uavcan::uint64_t
std::uint64_t uint64_t
Definition: std.hpp:27
PairableCanDriver::receive
virtual uavcan::int16_t receive(uavcan::CanFrame &out_frame, uavcan::MonotonicTime &out_ts_monotonic, uavcan::UtcTime &out_ts_utc, uavcan::CanIOFlags &out_flags)
Definition: test_node.hpp:116
TestNetwork::TestNetwork
TestNetwork(uavcan::uint8_t first_node_id=1)
Definition: test_node.hpp:220
uavcan::UtcTime
Implicitly convertible to/from uavcan.Timestamp.
Definition: time.hpp:191
uavcan::NodeID
Definition: transfer.hpp:112
uavcan::DurationBase< MonotonicDuration >::fromMSec
static MonotonicDuration fromMSec(int64_t ms)
Definition: time.hpp:41
TestNetwork::nodes
std::unique_ptr< NodeEnvironment > nodes[NumNodes]
Definition: test_node.hpp:218
uavcan::ICanDriver
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:207
uavcan::CanFilterConfig
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:99
uavcan::CanFrame
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:24
uavcan::CanIOFlagLoopback
static const CanIOFlags CanIOFlagLoopback
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:141
TestNetwork
Definition: test_node.hpp:204
PairableCanDriver::getNumFilters
virtual uavcan::uint16_t getNumFilters() const
Definition: test_node.hpp:143
InterlinkedTestNodes::can_b
PairableCanDriver can_b
Definition: test_node.hpp:154
uavcan::MonotonicDuration
Definition: time.hpp:182
uavcan::MaxCanIfaces
@ MaxCanIfaces
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:19
uavcan::INode::spin
int spin(MonotonicTime deadline)
Definition: abstract_node.hpp:63
TestNode::getAllocator
virtual uavcan::IPoolAllocator & getAllocator()
Definition: test_node.hpp:46
uavcan::uint16_t
std::uint16_t uint16_t
Definition: std.hpp:25
TestNode
Definition: test_node.hpp:20
PairableCanDriver::clock
uavcan::ISystemClock & clock
Definition: test_node.hpp:54
uavcan::int16_t
std::int16_t int16_t
Definition: std.hpp:30
TestNetwork::NodeEnvironment::node
TestNode node
Definition: test_node.hpp:210
uavcan::CanSelectMasks::read
uint8_t read
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:121
PairableCanDriver::send
virtual uavcan::int16_t send(const uavcan::CanFrame &frame, uavcan::MonotonicTime, uavcan::CanIOFlags flags)
Definition: test_node.hpp:102
uavcan::DurationBase::isNegative
bool isNegative() const
Definition: time.hpp:49
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
TestNetwork::NodeEnvironment::can_driver
PairableCanDriver can_driver
Definition: test_node.hpp:209
TestNode::scheduler
uavcan::Scheduler scheduler
Definition: test_node.hpp:29
heap_based_pool_allocator.hpp
uavcan::IPoolAllocator
Definition: dynamic_memory.hpp:21
abstract_node.hpp
uavcan::CanSelectMasks
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:119
uavcan::Scheduler
Definition: scheduler.hpp:63
uavcan::CanSelectMasks::write
uint8_t write
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:122
InterlinkedTestNodes
Definition: test_node.hpp:149
PairableCanDriver
Definition: test_node.hpp:52
PairableCanDriver::error_count
uint64_t error_count
Definition: test_node.hpp:58
method_binder.hpp
uavcan::INode
Definition: abstract_node.hpp:19
TestNetwork::spinAll
int spinAll(uavcan::MonotonicDuration duration)
Definition: test_node.hpp:241
PairableCanDriver::getErrorCount
virtual uavcan::uint64_t getErrorCount() const
Definition: test_node.hpp:144
TestNode::TestNode
TestNode(uavcan::ICanDriver &can_driver, uavcan::ISystemClock &clock_driver, uavcan::NodeID self_node_id)
Definition: test_node.hpp:32
InterlinkedTestNodes::clock_b
ClockType clock_b
Definition: test_node.hpp:152
PairableCanDriver::configureFilters
virtual uavcan::int16_t configureFilters(const uavcan::CanFilterConfig *, uavcan::uint16_t)
Definition: test_node.hpp:142
frame
uavcan::CanFrame frame
Definition: can.cpp:78
TestNode::getScheduler
virtual uavcan::Scheduler & getScheduler()
Definition: test_node.hpp:47
PairableCanDriver::getIface
virtual const uavcan::ICanIface * getIface(uavcan::uint8_t iface_index) const
Definition: test_node.hpp:76
InterlinkedTestNodes::InterlinkedTestNodes
InterlinkedTestNodes()
Definition: test_node.hpp:167
uavcan::ISystemClock::getUtc
virtual UtcTime getUtc() const =0
PairableCanDriver::linkTogether
void linkTogether(PairableCanDriver *with)
Definition: test_node.hpp:65
TestNode::registerInternalFailure
virtual void registerInternalFailure(const char *msg)
Definition: test_node.hpp:40
PairableCanDriver::getNumIfaces
virtual uavcan::uint8_t getNumIfaces() const
Definition: test_node.hpp:81
InterlinkedTestNodes::a
TestNode a
Definition: test_node.hpp:155
TestNetwork::NodeEnvironment
Definition: test_node.hpp:206
InterlinkedTestNodes::spinBoth
int spinBoth(uavcan::MonotonicDuration duration)
Definition: test_node.hpp:176
InterlinkedTestNodes::clock_a
ClockType clock_a
Definition: test_node.hpp:151
TestNetwork::NodeEnvironment::NodeEnvironment
NodeEnvironment(uavcan::NodeID node_id)
Definition: test_node.hpp:212
PairableCanDriver::select
virtual uavcan::int16_t select(uavcan::CanSelectMasks &inout_masks, const uavcan::CanFrame *(&)[uavcan::MaxCanIfaces], uavcan::MonotonicTime blocking_deadline)
Definition: test_node.hpp:83
PairableCanDriver::pushRxToAllIfaces
void pushRxToAllIfaces(const uavcan::CanFrame &can_frame)
Definition: test_node.hpp:137
uavcan::CanIOFlags
uint16_t CanIOFlags
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:140
PairableCanDriver::read_queue
std::queue< uavcan::CanFrame > read_queue
Definition: test_node.hpp:56
SystemClockDriver
Definition: libuavcan/libuavcan/test/clock.hpp:62
uavcan::MonotonicTime
Definition: time.hpp:184
PairableCanDriver::others
std::set< PairableCanDriver * > others
Definition: test_node.hpp:55
uavcan::HeapBasedPoolAllocator< uavcan::MemPoolBlockSize >
uavcan::ICanIface
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:147
uavcan::ISystemClock
Definition: system_clock.hpp:19
InterlinkedTestNodesWithClockMock
InterlinkedTestNodes< SystemClockMock > InterlinkedTestNodesWithClockMock
Definition: test_node.hpp:200
InterlinkedTestNodes::b
TestNode b
Definition: test_node.hpp:156
TestNode::getScheduler
virtual const uavcan::Scheduler & getScheduler() const
Definition: test_node.hpp:48
PairableCanDriver::getIface
virtual uavcan::ICanIface * getIface(uavcan::uint8_t iface_index)
Definition: test_node.hpp:72
uavcan::ISystemClock::getMonotonic
virtual MonotonicTime getMonotonic() const =0
PairableCanDriver::loopback_queue
std::queue< uavcan::CanFrame > loopback_queue
Definition: test_node.hpp:57
InterlinkedTestNodes::can_a
PairableCanDriver can_a
Definition: test_node.hpp:153
TestNetwork::operator[]
TestNode & operator[](unsigned index)
Definition: test_node.hpp:260


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