subscriber.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>
8 #include <root_ns_a/EmptyMessage.hpp>
9 #include <root_ns_a/MavlinkMessage.hpp>
10 #include "../clock.hpp"
11 #include "../transport/can/can.hpp"
12 #include "test_node.hpp"
13 
14 
15 template <typename DataType>
17 {
19 
21  {
28  DataType msg;
29 
30  ReceivedDataStructureCopy(const ReceivedDataStructure& s)
31  : ts_monotonic(s.getMonotonicTimestamp())
32  , ts_utc(s.getUtcTimestamp())
33  , transfer_type(s.getTransferType())
34  , transfer_id(s.getTransferID())
35  , src_node_id(s.getSrcNodeID())
36  , iface_index(s.getIfaceIndex())
37  , msg(s)
38  { }
39  };
40 
41  std::vector<DataType> simple;
42  std::vector<ReceivedDataStructureCopy> extended;
43 
44  void receiveExtended(ReceivedDataStructure& msg)
45  {
46  extended.push_back(msg);
47  }
48 
49  void receiveSimple(DataType& msg)
50  {
51  simple.push_back(msg);
52  }
53 
57 
58  ExtendedBinder bindExtended() { return ExtendedBinder(this, &SelfType::receiveExtended); }
59  SimpleBinder bindSimple() { return SimpleBinder(this, &SelfType::receiveSimple); }
60 };
61 
62 
63 TEST(Subscriber, Basic)
64 {
65  // Manual type registration - we can't rely on the GDTR state
68 
69  SystemClockDriver clock_driver;
70  CanDriverMock can_driver(2, clock_driver);
71  TestNode node(can_driver, clock_driver, 1);
72 
74 
79 
80  std::cout <<
81  "sizeof(uavcan::Subscriber<root_ns_a::MavlinkMessage, Listener::ExtendedBinder>): " <<
83 
84  // Null binder - will fail
85  ASSERT_EQ(-uavcan::ErrInvalidParam, sub_extended.start(Listener::ExtendedBinder(UAVCAN_NULLPTR, UAVCAN_NULLPTR)));
86 
87  Listener listener;
88 
89  /*
90  * Message layout:
91  * uint8 seq
92  * uint8 sysid
93  * uint8 compid
94  * uint8 msgid
95  * uint8[<256] payload
96  */
97  root_ns_a::MavlinkMessage expected_msg;
98  expected_msg.seq = 0x42;
99  expected_msg.sysid = 0x72;
100  expected_msg.compid = 0x08;
101  expected_msg.msgid = 0xa5;
102  expected_msg.payload = "Msg";
103 
104  const uint8_t transfer_payload[] = {0x42, 0x72, 0x08, 0xa5, 'M', 's', 'g'};
105 
106  /*
107  * RxFrame generation
108  */
109  std::vector<uavcan::RxFrame> rx_frames;
110  for (uint8_t i = 0; i < 4; i++)
111  {
115  // uint_fast16_t data_type_id, TransferType transfer_type, NodeID src_node_id, NodeID dst_node_id,
116  // uint_fast8_t frame_index, TransferID transfer_id, bool last_frame
117  uavcan::Frame frame(root_ns_a::MavlinkMessage::DefaultDataTypeID, tt, uavcan::NodeID(uint8_t(i + 100)),
118  dni, i);
119  frame.setStartOfTransfer(true);
120  frame.setEndOfTransfer(true);
121  frame.setPayload(transfer_payload, 7);
122  uavcan::RxFrame rx_frame(frame, clock_driver.getMonotonic(), clock_driver.getUtc(), 0);
123  rx_frames.push_back(rx_frame);
124  }
125 
126  /*
127  * Reception
128  */
129  ASSERT_EQ(0, node.getDispatcher().getNumMessageListeners());
130 
131  ASSERT_EQ(0, sub_extended.start(listener.bindExtended()));
132  ASSERT_EQ(0, sub_extended2.start(listener.bindExtended()));
133  ASSERT_EQ(0, sub_simple.start(listener.bindSimple()));
134  ASSERT_EQ(0, sub_simple2.start(listener.bindSimple()));
135 
136  ASSERT_EQ(4, node.getDispatcher().getNumMessageListeners());
137 
138  sub_extended2.stop(); // These are not used - making sure they aren't receiving anything
139  sub_simple2.stop();
140 
141  ASSERT_EQ(2, node.getDispatcher().getNumMessageListeners());
142 
143  for (unsigned i = 0; i < rx_frames.size(); i++)
144  {
145  can_driver.ifaces[0].pushRx(rx_frames[i]);
146  can_driver.ifaces[1].pushRx(rx_frames[i]);
147  }
148 
149  ASSERT_LE(0, node.spin(clock_driver.getMonotonic() + durMono(10000)));
150 
151  /*
152  * Validation
153  */
154  ASSERT_EQ(listener.extended.size(), rx_frames.size());
155  for (unsigned i = 0; i < rx_frames.size(); i++)
156  {
157  const Listener::ReceivedDataStructureCopy s = listener.extended.at(i);
158  ASSERT_TRUE(s.msg == expected_msg);
159  ASSERT_EQ(rx_frames[i].getSrcNodeID(), s.src_node_id);
160  ASSERT_EQ(rx_frames[i].getTransferID(), s.transfer_id);
161  ASSERT_EQ(rx_frames[i].getTransferType(), s.transfer_type);
162  ASSERT_EQ(rx_frames[i].getMonotonicTimestamp(), s.ts_monotonic);
163  ASSERT_EQ(rx_frames[i].getIfaceIndex(), s.iface_index);
164  }
165 
166  ASSERT_EQ(listener.simple.size(), rx_frames.size());
167  for (unsigned i = 0; i < rx_frames.size(); i++)
168  {
169  ASSERT_TRUE(listener.simple.at(i) == expected_msg);
170  }
171 
172  ASSERT_EQ(0, sub_extended.getFailureCount());
173  ASSERT_EQ(0, sub_simple.getFailureCount());
174 
175  /*
176  * Unregistration
177  */
178  ASSERT_EQ(2, node.getDispatcher().getNumMessageListeners());
179 
180  sub_extended.stop();
181  sub_extended2.stop();
182  sub_simple.stop();
183  sub_simple2.stop();
184 
185  ASSERT_EQ(0, node.getDispatcher().getNumMessageListeners());
186 }
187 
188 
190 {
191  FAIL() << "I just went mad";
192 }
193 
194 
195 TEST(Subscriber, FailureCount)
196 {
197  // Manual type registration - we can't rely on the GDTR state
200 
201  SystemClockDriver clock_driver;
202  CanDriverMock can_driver(2, clock_driver);
203  TestNode node(can_driver, clock_driver, 1);
204 
205  {
207  ASSERT_EQ(0, node.getDispatcher().getNumMessageListeners());
208  sub.start(panickingSink);
209  ASSERT_EQ(1, node.getDispatcher().getNumMessageListeners());
210 
211  ASSERT_EQ(0, sub.getFailureCount());
212 
213  for (uint8_t i = 0; i < 4; i++)
214  {
215  // uint_fast16_t data_type_id, TransferType transfer_type, NodeID src_node_id, NodeID dst_node_id,
216  // uint_fast8_t frame_index, TransferID transfer_id, bool last_frame
217  uavcan::Frame frame(root_ns_a::MavlinkMessage::DefaultDataTypeID, uavcan::TransferTypeMessageBroadcast,
219  frame.setStartOfTransfer(true);
220  frame.setEndOfTransfer(true);
221  // No payload - broken transfer
222  uavcan::RxFrame rx_frame(frame, clock_driver.getMonotonic(), clock_driver.getUtc(), 0);
223  can_driver.ifaces[0].pushRx(rx_frame);
224  can_driver.ifaces[1].pushRx(rx_frame);
225  }
226 
227  ASSERT_LE(0, node.spin(clock_driver.getMonotonic() + durMono(10000)));
228 
229  ASSERT_EQ(4, sub.getFailureCount());
230 
231  ASSERT_EQ(1, node.getDispatcher().getNumMessageListeners()); // Still there
232  }
233  ASSERT_EQ(0, node.getDispatcher().getNumMessageListeners()); // Removed
234 }
235 
236 
237 TEST(Subscriber, SingleFrameTransfer)
238 {
239  // Manual type registration - we can't rely on the GDTR state
242 
243  SystemClockDriver clock_driver;
244  CanDriverMock can_driver(2, clock_driver);
245  TestNode node(can_driver, clock_driver, 1);
246 
248 
250 
251  std::cout <<
252  "sizeof(uavcan::Subscriber<root_ns_a::EmptyMessage, Listener::SimpleBinder>): " <<
254 
255  Listener listener;
256 
257  sub.start(listener.bindSimple());
258 
259  for (uint8_t i = 0; i < 4; i++)
260  {
261  // uint_fast16_t data_type_id, TransferType transfer_type, NodeID src_node_id, NodeID dst_node_id,
262  // uint_fast8_t frame_index, TransferID transfer_id, bool last_frame
263  uavcan::Frame frame(root_ns_a::EmptyMessage::DefaultDataTypeID, uavcan::TransferTypeMessageBroadcast,
265  frame.setStartOfTransfer(true);
266  frame.setEndOfTransfer(true);
267  // No payload - message is empty
268  uavcan::RxFrame rx_frame(frame, clock_driver.getMonotonic(), clock_driver.getUtc(), 0);
269  can_driver.ifaces[0].pushRx(rx_frame);
270  can_driver.ifaces[1].pushRx(rx_frame);
271  }
272 
273  ASSERT_LE(0, node.spin(clock_driver.getMonotonic() + durMono(10000)));
274 
275  ASSERT_EQ(0, sub.getFailureCount());
276 
277  ASSERT_EQ(4, listener.simple.size());
278  for (unsigned i = 0; i < 4; i++)
279  {
280  ASSERT_TRUE(listener.simple.at(i) == root_ns_a::EmptyMessage());
281  }
282 }
static void panickingSink(const uavcan::ReceivedDataStructure< root_ns_a::MavlinkMessage > &)
Definition: subscriber.cpp:189
std::uint8_t uint8_t
Definition: std.hpp:24
SubscriptionListener< DataType > SelfType
Definition: subscriber.cpp:54
virtual uavcan::MonotonicTime getMonotonic() const
Dispatcher & getDispatcher()
void setStartOfTransfer(bool x)
Definition: frame.hpp:81
ExtendedBinder bindExtended()
Definition: subscriber.cpp:58
static const NodeID Broadcast
Definition: transfer.hpp:122
uint8_t setPayload(const uint8_t *data, unsigned len)
Definition: uc_frame.cpp:16
SimpleBinder bindSimple()
Definition: subscriber.cpp:59
std::vector< DataType > simple
Definition: subscriber.cpp:41
uavcan::MethodBinder< SelfType *, void(SelfType::*)(ReceivedDataStructure &)> ExtendedBinder
Definition: subscriber.cpp:55
Implicitly convertible to/from uavcan.Timestamp.
Definition: time.hpp:191
virtual uavcan::UtcTime getUtc() const
int spin(MonotonicTime deadline)
TransferType
Definition: transfer.hpp:18
void receiveSimple(DataType &msg)
Definition: subscriber.cpp:49
int start(const Callback &callback)
Definition: subscriber.hpp:83
static GlobalDataTypeRegistry & instance()
uavcan::MethodBinder< SelfType *, void(SelfType::*)(DataType &)> SimpleBinder
Definition: subscriber.cpp:56
uavcan::CanFrame frame
Definition: can.cpp:78
uavcan::ReceivedDataStructure< DataType > ReceivedDataStructure
Definition: subscriber.cpp:18
std::vector< ReceivedDataStructureCopy > extended
Definition: subscriber.cpp:42
unsigned getNumMessageListeners() const
Definition: dispatcher.hpp:177
uavcan::MonotonicDuration durMono(int64_t usec)
void receiveExtended(ReceivedDataStructure &msg)
Definition: subscriber.cpp:44
ReceivedDataStructureCopy(const ReceivedDataStructure &s)
Definition: subscriber.cpp:30
void setEndOfTransfer(bool x)
Definition: frame.hpp:82
TEST(Subscriber, Basic)
Definition: subscriber.cpp:63
NodeID getNodeID() const
Definition: dispatcher.hpp:222


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