node_info_retriever.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #if __GNUC__
6 # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
7 #endif
8 
9 #include <memory>
10 #include <gtest/gtest.h>
13 #include "helpers.hpp"
14 
16  uavcan::uint32_t uptime_sec, uavcan::TransferID tid)
17 {
18  uavcan::protocol::NodeStatus msg;
19  msg.health = uavcan::protocol::NodeStatus::HEALTH_OK;
20  msg.mode = uavcan::protocol::NodeStatus::MODE_OPERATIONAL;
21  msg.uptime_sec = uptime_sec;
22  emulateSingleFrameBroadcastTransfer(can, node_id, msg, tid);
23 }
24 
25 
27 {
28  std::unique_ptr<uavcan::protocol::GetNodeInfo::Response> last_node_info;
33 
38  { }
39 
41  const uavcan::protocol::GetNodeInfo::Response& node_info)
42  {
43  last_node_id = node_id;
44  std::cout << node_info << std::endl;
45  last_node_info.reset(new uavcan::protocol::GetNodeInfo::Response(node_info));
46  }
47 
49  {
50  std::cout << "NODE INFO FOR " << int(node_id.get()) << " IS UNAVAILABLE" << std::endl;
51  last_node_id = node_id;
53  }
54 
56  {
57  std::cout << "NODE " << int(event.node_id.get()) << " STATUS CHANGE: "
58  << event.old_status.toString() << " --> " << event.status.toString() << std::endl;
60  }
61 
63  {
64  std::cout << msg << std::endl;
66  }
67 };
68 
69 
70 TEST(NodeInfoRetriever, Basic)
71 {
75 
77 
78  uavcan::NodeInfoRetriever retr(nodes.a);
79  std::cout << "sizeof(uavcan::NodeInfoRetriever): " << sizeof(uavcan::NodeInfoRetriever) << std::endl;
80  std::cout << "sizeof(uavcan::ServiceClient<uavcan::protocol::GetNodeInfo>): "
82 
83  std::unique_ptr<uavcan::NodeStatusProvider> provider(new uavcan::NodeStatusProvider(nodes.b));
84 
85  NodeInfoListener listener;
86 
87  /*
88  * Initialization
89  */
90  ASSERT_LE(0, retr.start());
91 
92  retr.removeListener(&listener); // Does nothing
93  retr.addListener(&listener);
94  retr.addListener(&listener);
95  retr.addListener(&listener);
96  ASSERT_EQ(1, retr.getNumListeners());
97 
98  uavcan::protocol::HardwareVersion hwver;
99  hwver.unique_id[0] = 123;
100  hwver.unique_id[4] = 213;
101  hwver.unique_id[8] = 45;
102 
103  provider->setName("Ivan");
104  provider->setHardwareVersion(hwver);
105 
106  ASSERT_LE(0, provider->startAndPublish());
107 
108  ASSERT_FALSE(retr.isRetrievingInProgress());
109  ASSERT_EQ(0, retr.getNumPendingRequests());
110 
111  EXPECT_EQ(40, retr.getRequestInterval().toMSec()); // Default
112 
113  /*
114  * Waiting for discovery
115  */
117  ASSERT_TRUE(retr.isRetrievingInProgress());
119  ASSERT_FALSE(retr.isRetrievingInProgress());
120 
121  ASSERT_EQ(2, listener.status_message_cnt);
122  ASSERT_EQ(1, listener.status_change_cnt);
123  ASSERT_EQ(0, listener.info_unavailable_cnt);
124  ASSERT_TRUE(listener.last_node_info.get());
125  ASSERT_EQ(uavcan::NodeID(2), listener.last_node_id);
126  ASSERT_EQ("Ivan", listener.last_node_info->name);
127  ASSERT_TRUE(hwver == listener.last_node_info->hardware_version);
128 
129  provider.reset(); // Moving the provider out of the way; its entry will timeout meanwhile
130 
131  /*
132  * Declaring a bunch of different nodes that don't support GetNodeInfo
133  */
134  ASSERT_FALSE(retr.isRetrievingInProgress());
135 
136  retr.setNumRequestAttempts(3);
137 
138  uavcan::TransferID tid;
139 
140  publishNodeStatus(nodes.can_a, uavcan::NodeID(10), 10, tid);
141  publishNodeStatus(nodes.can_a, uavcan::NodeID(11), 10, tid);
142  publishNodeStatus(nodes.can_a, uavcan::NodeID(12), 10, tid);
143 
145  ASSERT_LE(1, retr.getNumPendingRequests());
147  ASSERT_LE(2, retr.getNumPendingRequests());
149  ASSERT_EQ(3, retr.getNumPendingRequests());
151  ASSERT_TRUE(retr.isRetrievingInProgress());
152 
153  tid.increment();
154  publishNodeStatus(nodes.can_a, uavcan::NodeID(10), 11, tid);
155  publishNodeStatus(nodes.can_a, uavcan::NodeID(11), 11, tid);
156  publishNodeStatus(nodes.can_a, uavcan::NodeID(12), 11, tid);
157 
159  ASSERT_LE(1, retr.getNumPendingRequests());
161  ASSERT_LE(2, retr.getNumPendingRequests());
163  ASSERT_EQ(3, retr.getNumPendingRequests());
165  ASSERT_TRUE(retr.isRetrievingInProgress());
166 
167  tid.increment();
168  publishNodeStatus(nodes.can_a, uavcan::NodeID(10), 12, tid);
169  publishNodeStatus(nodes.can_a, uavcan::NodeID(11), 12, tid);
170  publishNodeStatus(nodes.can_a, uavcan::NodeID(12), 10, tid); // Reset
171 
173  ASSERT_LE(1, retr.getNumPendingRequests());
175  ASSERT_LE(2, retr.getNumPendingRequests());
177  ASSERT_EQ(3, retr.getNumPendingRequests());
179  ASSERT_TRUE(retr.isRetrievingInProgress());
180 
181  EXPECT_EQ(11, listener.status_message_cnt);
182  EXPECT_EQ(5, listener.status_change_cnt); // node 2 online/offline + 3 test nodes above
183  EXPECT_EQ(2, listener.info_unavailable_cnt);
184 
185  tid.increment();
186  publishNodeStatus(nodes.can_a, uavcan::NodeID(12), 11, tid);
187 
189  ASSERT_EQ(1, retr.getNumPendingRequests());
191  ASSERT_EQ(1, retr.getNumPendingRequests()); // Still one because two went offline
193  ASSERT_TRUE(retr.isRetrievingInProgress());
194 
195  tid.increment();
196  publishNodeStatus(nodes.can_a, uavcan::NodeID(12), 12, tid);
197 
199  ASSERT_FALSE(retr.isRetrievingInProgress()); // Out of attempts, stopping
200  ASSERT_EQ(0, retr.getNumPendingRequests());
201 
202  EXPECT_EQ(13, listener.status_message_cnt);
203  EXPECT_EQ(7, listener.status_change_cnt); // node 2 online/offline + 2 test nodes above online/offline + 1
204  EXPECT_EQ(3, listener.info_unavailable_cnt);
205 
206  /*
207  * Forcing the class to forget everything
208  */
209  std::cout << "Invalidation" << std::endl;
210 
211  retr.invalidateAll();
212 
213  ASSERT_FALSE(retr.isRetrievingInProgress());
214  ASSERT_EQ(0, retr.getNumPendingRequests());
215 
216  tid.increment();
217  publishNodeStatus(nodes.can_a, uavcan::NodeID(10), 60, tid);
218  publishNodeStatus(nodes.can_a, uavcan::NodeID(11), 60, tid);
219  publishNodeStatus(nodes.can_a, uavcan::NodeID(12), 60, tid);
220 
222 
223  ASSERT_TRUE(retr.isRetrievingInProgress());
224  ASSERT_EQ(3, retr.getNumPendingRequests());
225 }
226 
227 
228 TEST(NodeInfoRetriever, MaxConcurrentRequests)
229 {
233 
235 
236  uavcan::NodeInfoRetriever retr(nodes.a);
237  std::cout << "sizeof(uavcan::NodeInfoRetriever): " << sizeof(uavcan::NodeInfoRetriever) << std::endl;
238  std::cout << "sizeof(uavcan::ServiceClient<uavcan::protocol::GetNodeInfo>): "
240 
241  NodeInfoListener listener;
242 
243  /*
244  * Initialization
245  */
246  ASSERT_LE(0, retr.start());
247 
248  retr.addListener(&listener);
249  ASSERT_EQ(1, retr.getNumListeners());
250 
251  ASSERT_FALSE(retr.isRetrievingInProgress());
252  ASSERT_EQ(0, retr.getNumPendingRequests());
253 
254  ASSERT_EQ(40, retr.getRequestInterval().toMSec());
255 
256  const unsigned MaxPendingRequests = 26; // See class docs
257  const unsigned MinPendingRequestsAtFullLoad = 12;
258 
259  /*
260  * Sending a lot of requests, making sure that the number of concurrent calls does not exceed the specified limit.
261  */
262  for (uint8_t node_id = 1U; node_id <= 127U; node_id++)
263  {
264  publishNodeStatus(nodes.can_a, node_id, 0, uavcan::TransferID());
266  ASSERT_GE(MaxPendingRequests, retr.getNumPendingRequests());
267  ASSERT_TRUE(retr.isRetrievingInProgress());
268  }
269 
270  ASSERT_GE(MaxPendingRequests, retr.getNumPendingRequests());
271  ASSERT_LE(MinPendingRequestsAtFullLoad, retr.getNumPendingRequests());
272 
273  for (int i = 0; i < 8; i++) // Approximate
274  {
276  std::cout << "!!! SPIN " << i << " COMPLETE" << std::endl;
277 
278  ASSERT_GE(MaxPendingRequests, retr.getNumPendingRequests());
279  ASSERT_LE(MinPendingRequestsAtFullLoad, retr.getNumPendingRequests());
280 
281  ASSERT_TRUE(retr.isRetrievingInProgress());
282  }
283 
284  ASSERT_LT(0, retr.getNumPendingRequests());
285  ASSERT_TRUE(retr.isRetrievingInProgress());
286 
288 
289  ASSERT_EQ(0, retr.getNumPendingRequests());
290  ASSERT_FALSE(retr.isRetrievingInProgress());
291 }
emulateSingleFrameBroadcastTransfer
static void emulateSingleFrameBroadcastTransfer(CanDriver &can, uavcan::NodeID node_id, const MessageType &message, uavcan::TransferID tid)
Definition: libuavcan/libuavcan/test/protocol/helpers.hpp:135
uavcan::NodeStatusMonitor::NodeStatusChangeEvent::node_id
NodeID node_id
Definition: node_status_monitor.hpp:62
uavcan::NodeInfoRetriever::removeListener
void removeListener(INodeInfoListener *listener)
Definition: node_info_retriever.hpp:403
uavcan::DurationBase::toMSec
int64_t toMSec() const
Definition: time.hpp:44
uavcan::NodeInfoRetriever::start
int start(const TransferPriority priority=TransferPriority::OneHigherThanLowest)
Definition: node_info_retriever.hpp:347
uavcan::DefaultDataTypeRegistrator
Definition: global_data_type_registry.hpp:186
uavcan::uint32_t
std::uint32_t uint32_t
Definition: std.hpp:26
uavcan::NodeInfoRetriever::setNumRequestAttempts
void setNumRequestAttempts(const uint8_t num)
Definition: node_info_retriever.hpp:423
uavcan::INodeInfoListener
Definition: node_info_retriever.hpp:21
uavcan::NodeID::get
uint8_t get() const
Definition: transfer.hpp:132
uavcan::NodeID
Definition: transfer.hpp:112
uavcan::DurationBase< MonotonicDuration >::fromMSec
static MonotonicDuration fromMSec(int64_t ms)
Definition: time.hpp:41
uavcan::NodeStatusProvider
Definition: node_status_provider.hpp:51
uavcan::ReceivedDataStructure
Definition: generic_subscriber.hpp:39
NodeInfoListener::info_unavailable_cnt
unsigned info_unavailable_cnt
Definition: node_info_retriever.cpp:32
NodeInfoListener
Definition: node_info_retriever.cpp:26
uavcan::NodeInfoRetriever::getRequestInterval
MonotonicDuration getRequestInterval() const
Definition: node_info_retriever.hpp:432
NodeInfoListener::handleNodeInfoUnavailable
virtual void handleNodeInfoUnavailable(uavcan::NodeID node_id)
Definition: node_info_retriever.cpp:48
NodeInfoListener::last_node_info
std::unique_ptr< uavcan::protocol::GetNodeInfo::Response > last_node_info
Definition: node_info_retriever.cpp:28
NodeInfoListener::status_message_cnt
unsigned status_message_cnt
Definition: node_info_retriever.cpp:30
NodeInfoListener::NodeInfoListener
NodeInfoListener()
Definition: node_info_retriever.cpp:34
uavcan::TransferID
Definition: transfer.hpp:71
NodeInfoListener::handleNodeInfoRetrieved
virtual void handleNodeInfoRetrieved(uavcan::NodeID node_id, const uavcan::protocol::GetNodeInfo::Response &node_info)
Definition: node_info_retriever.cpp:40
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
node_info_retriever.hpp
uavcan::NodeInfoRetriever::isRetrievingInProgress
bool isRetrievingInProgress() const
Definition: node_info_retriever.hpp:452
helpers.hpp
publishNodeStatus
static void publishNodeStatus(PairableCanDriver &can, uavcan::NodeID node_id, uavcan::uint32_t uptime_sec, uavcan::TransferID tid)
Definition: node_info_retriever.cpp:15
InterlinkedTestNodes
Definition: test_node.hpp:149
PairableCanDriver
Definition: test_node.hpp:52
uavcan::ServiceClient
Definition: service_client.hpp:217
int
int
Definition: libstubs.cpp:120
uavcan::NodeInfoRetriever::getNumPendingRequests
uint8_t getNumPendingRequests() const
Definition: node_info_retriever.hpp:454
NodeInfoListener::handleNodeStatusMessage
virtual void handleNodeStatusMessage(const uavcan::ReceivedDataStructure< uavcan::protocol::NodeStatus > &msg)
Definition: node_info_retriever.cpp:62
InterlinkedTestNodes::a
TestNode a
Definition: test_node.hpp:155
InterlinkedTestNodes::spinBoth
int spinBoth(uavcan::MonotonicDuration duration)
Definition: test_node.hpp:176
uavcan::NodeInfoRetriever::addListener
int addListener(INodeInfoListener *listener)
Definition: node_info_retriever.hpp:386
uavcan::NodeInfoRetriever::invalidateAll
void invalidateAll()
Definition: node_info_retriever.hpp:370
TEST
TEST(NodeInfoRetriever, Basic)
Definition: node_info_retriever.cpp:70
uavcan::NodeInfoRetriever
Definition: node_info_retriever.hpp:91
uavcan::GlobalDataTypeRegistry::instance
static GlobalDataTypeRegistry & instance()
Definition: uc_global_data_type_registry.cpp:128
NodeInfoListener::status_change_cnt
unsigned status_change_cnt
Definition: node_info_retriever.cpp:31
uavcan::NodeInfoRetriever::getNumListeners
unsigned getNumListeners() const
Definition: node_info_retriever.hpp:415
InterlinkedTestNodes::b
TestNode b
Definition: test_node.hpp:156
NodeInfoListener::last_node_id
uavcan::NodeID last_node_id
Definition: node_info_retriever.cpp:29
uavcan::TransferID::increment
void increment()
Definition: transfer.hpp:94
node_status_provider.hpp
uavcan::NodeStatusMonitor::NodeStatusChangeEvent
Definition: node_status_monitor.hpp:60
NodeInfoListener::handleNodeStatusChange
virtual void handleNodeStatusChange(const uavcan::NodeStatusMonitor::NodeStatusChangeEvent &event)
Definition: node_info_retriever.cpp:55
InterlinkedTestNodes::can_a
PairableCanDriver can_a
Definition: test_node.hpp:153


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