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 
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 
45  {
46  extended.push_back(msg);
47  }
48 
49  void receiveSimple(DataType& msg)
50  {
51  simple.push_back(msg);
52  }
53 
56  typedef uavcan::MethodBinder<SelfType*, void (SelfType::*)(DataType&)> SimpleBinder;
57 
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  {
114  uavcan::NodeID::Broadcast : node.getDispatcher().getNodeID();
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 }
subscriber.hpp
UAVCAN_NULLPTR
#define UAVCAN_NULLPTR
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:51
SubscriptionListener::simple
std::vector< DataType > simple
Definition: subscriber.cpp:41
TEST
TEST(Subscriber, Basic)
Definition: subscriber.cpp:63
uavcan::DefaultDataTypeRegistrator
Definition: global_data_type_registry.hpp:186
uavcan::Subscriber
Definition: subscriber.hpp:45
uavcan::UtcTime
Implicitly convertible to/from uavcan.Timestamp.
Definition: time.hpp:191
SubscriptionListener::ReceivedDataStructureCopy::msg
DataType msg
Definition: subscriber.cpp:28
SystemClockDriver::getMonotonic
virtual uavcan::MonotonicTime getMonotonic() const
Definition: libuavcan/libuavcan/test/clock.hpp:67
SubscriptionListener
Definition: subscriber.cpp:16
uavcan::NodeID
Definition: transfer.hpp:112
uavcan::TransferType
TransferType
Definition: transfer.hpp:18
SubscriptionListener::bindSimple
SimpleBinder bindSimple()
Definition: subscriber.cpp:59
SubscriptionListener::ExtendedBinder
uavcan::MethodBinder< SelfType *, void(SelfType::*)(ReceivedDataStructure &)> ExtendedBinder
Definition: subscriber.cpp:55
SubscriptionListener::receiveSimple
void receiveSimple(DataType &msg)
Definition: subscriber.cpp:49
uavcan::GenericSubscriber< DataType_, DataType_, TransferListener >::stop
void stop()
Definition: generic_subscriber.hpp:213
uavcan::ReceivedDataStructure
Definition: generic_subscriber.hpp:39
uavcan::GenericSubscriberBase::getFailureCount
uint32_t getFailureCount() const
Definition: generic_subscriber.hpp:118
uavcan::Subscriber::start
int start(const Callback &callback)
Definition: subscriber.hpp:83
SubscriptionListener::ReceivedDataStructure
uavcan::ReceivedDataStructure< DataType > ReceivedDataStructure
Definition: subscriber.cpp:18
SubscriptionListener::SimpleBinder
uavcan::MethodBinder< SelfType *, void(SelfType::*)(DataType &)> SimpleBinder
Definition: subscriber.cpp:56
TestNode
Definition: test_node.hpp:20
uavcan::TransferID
Definition: transfer.hpp:71
SubscriptionListener::receiveExtended
void receiveExtended(ReceivedDataStructure &msg)
Definition: subscriber.cpp:44
CanDriverMock::ifaces
std::vector< CanIfaceMock > ifaces
Definition: libuavcan/libuavcan/test/transport/can/can.hpp:193
SubscriptionListener::ReceivedDataStructureCopy::src_node_id
uavcan::NodeID src_node_id
Definition: subscriber.cpp:26
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
SubscriptionListener::ReceivedDataStructureCopy::iface_index
uavcan::uint8_t iface_index
Definition: subscriber.cpp:27
uavcan::TransferTypeMessageBroadcast
@ TransferTypeMessageBroadcast
Definition: transfer.hpp:22
uavcan::RxFrame
Definition: frame.hpp:104
SubscriptionListener::ReceivedDataStructureCopy::ts_utc
uavcan::UtcTime ts_utc
Definition: subscriber.cpp:23
SubscriptionListener::ReceivedDataStructureCopy::transfer_id
uavcan::TransferID transfer_id
Definition: subscriber.cpp:25
uavcan::NodeID::Broadcast
static const NodeID Broadcast
Definition: transfer.hpp:122
method_binder.hpp
test_node.hpp
SubscriptionListener::extended
std::vector< ReceivedDataStructureCopy > extended
Definition: subscriber.cpp:42
SystemClockDriver::getUtc
virtual uavcan::UtcTime getUtc() const
Definition: libuavcan/libuavcan/test/clock.hpp:79
frame
uavcan::CanFrame frame
Definition: can.cpp:78
SubscriptionListener::bindExtended
ExtendedBinder bindExtended()
Definition: subscriber.cpp:58
uavcan::MethodBinder
Definition: method_binder.hpp:20
CanDriverMock
Definition: libuavcan/libuavcan/test/transport/can/can.hpp:190
uavcan::Frame
Definition: frame.hpp:17
pyuavcan_v0.dsdl.signature.s
s
Definition: signature.py:73
SubscriptionListener::SelfType
SubscriptionListener< DataType > SelfType
Definition: subscriber.cpp:54
durMono
uavcan::MonotonicDuration durMono(int64_t usec)
Definition: libuavcan/libuavcan/test/clock.hpp:100
SubscriptionListener::ReceivedDataStructureCopy::transfer_type
uavcan::TransferType transfer_type
Definition: subscriber.cpp:24
panickingSink
static void panickingSink(const uavcan::ReceivedDataStructure< root_ns_a::MavlinkMessage > &)
Definition: subscriber.cpp:189
pyuavcan_v0.introspect.node
node
Definition: introspect.py:398
SubscriptionListener::ReceivedDataStructureCopy::ts_monotonic
uavcan::MonotonicTime ts_monotonic
Definition: subscriber.cpp:22
SystemClockDriver
Definition: libuavcan/libuavcan/test/clock.hpp:62
uavcan::MonotonicTime
Definition: time.hpp:184
uavcan::GlobalDataTypeRegistry::instance
static GlobalDataTypeRegistry & instance()
Definition: uc_global_data_type_registry.cpp:128
SubscriptionListener::ReceivedDataStructureCopy::ReceivedDataStructureCopy
ReceivedDataStructureCopy(const ReceivedDataStructure &s)
Definition: subscriber.cpp:30
SubscriptionListener::ReceivedDataStructureCopy
Definition: subscriber.cpp:20


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