firmware_update_trigger.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #include <gtest/gtest.h>
8 #include "helpers.hpp"
9 
10 using namespace uavcan::protocol::file;
11 
13 {
15  unsigned should_retry_cnt;
16  unsigned confirmation_cnt;
17 
18  std::string firmware_path;
19 
22 
23  BeginFirmwareUpdate::Response last_error_response;
24 
26  : should_request_cnt(0)
27  , should_retry_cnt(0)
28  , confirmation_cnt(0)
29  , retry_quota(0)
30  { }
31 
33  const uavcan::protocol::GetNodeInfo::Response& node_info,
34  FirmwareFilePath& out_firmware_file_path)
35  {
36  should_request_cnt++;
37  std::cout << "REQUEST? " << int(node_id.get()) << "\n" << node_info << std::endl;
38  out_firmware_file_path = firmware_path.c_str();
39  return node_info.name == expected_node_name_to_update;
40  }
41 
43  const BeginFirmwareUpdate::Response& error_response,
44  FirmwareFilePath& out_firmware_file_path)
45  {
46  last_error_response = error_response;
47  std::cout << "RETRY? " << int(node_id.get()) << "\n" << error_response << std::endl;
48  should_retry_cnt++;
49 
50  EXPECT_STREQ(firmware_path.c_str(), out_firmware_file_path.c_str());
51 
52  if (retry_quota > 0)
53  {
54  retry_quota--;
55  return true;
56  }
57  else
58  {
59  return false;
60  }
61  }
62 
64  const BeginFirmwareUpdate::Response& response)
65  {
66  confirmation_cnt++;
67  std::cout << "CONFIRMED " << int(node_id.get()) << "\n" << response << std::endl;
68  }
69 };
70 
72 {
74 
75  BeginFirmwareUpdateServer() : response_error_code(0) { }
76 
79  {
80  std::cout << "REQUEST\n" << req << std::endl;
81  res.error = response_error_code;
82  res.optional_error_message = "foobar";
83  }
84 
86  void (BeginFirmwareUpdateServer::*)(
89 
91 };
92 
93 
94 TEST(FirmwareUpdateTrigger, Basic)
95 {
100 
102 
103  FirmwareVersionChecker checker;
104 
105  uavcan::NodeInfoRetriever node_info_retriever(nodes.a); // On the same node
106 
107  uavcan::FirmwareUpdateTrigger trigger(nodes.a, checker);
108  std::cout << "sizeof(uavcan::FirmwareUpdateTrigger): " << sizeof(uavcan::FirmwareUpdateTrigger) << std::endl;
109 
110  std::unique_ptr<uavcan::NodeStatusProvider> provider(new uavcan::NodeStatusProvider(nodes.b)); // Other node
111 
112  /*
113  * Initializing
114  */
115  ASSERT_LE(0, trigger.start(node_info_retriever, "/path_prefix/"));
116 
117  ASSERT_LE(0, node_info_retriever.start());
118  ASSERT_EQ(1, node_info_retriever.getNumListeners());
119 
120  uavcan::protocol::HardwareVersion hwver;
121  hwver.unique_id[0] = 123;
122  hwver.unique_id[4] = 213;
123  hwver.unique_id[8] = 45;
124 
125  provider->setName("Ivan");
126  provider->setHardwareVersion(hwver);
127 
128  ASSERT_LE(0, provider->startAndPublish());
129 
130  ASSERT_FALSE(trigger.isTimerRunning());
131  ASSERT_EQ(0, trigger.getNumPendingNodes());
132 
133  /*
134  * Updating one node
135  * The server that can confirm the request is not running yet
136  */
137  checker.firmware_path = "firmware_path";
138  checker.expected_node_name_to_update = "Ivan";
139  checker.retry_quota = 1000;
140 
142 
143  ASSERT_TRUE(trigger.isTimerRunning());
144  ASSERT_EQ(1, trigger.getNumPendingNodes());
145 
146  ASSERT_EQ(1, checker.should_request_cnt);
147  ASSERT_EQ(0, checker.should_retry_cnt);
148  ASSERT_EQ(0, checker.confirmation_cnt);
149 
151 
152  // Still running!
153  ASSERT_TRUE(trigger.isTimerRunning());
154  ASSERT_EQ(1, trigger.getNumPendingNodes());
155 
156  /*
157  * Starting the firmware update server that returns an error
158  * The checker will instruct the trigger to repeat
159  */
161  BeginFirmwareUpdateServer srv_impl;
162 
163  ASSERT_LE(0, srv.start(srv_impl.makeCallback()));
164 
165  srv_impl.response_error_code = BeginFirmwareUpdate::Response::ERROR_UNKNOWN;
166  checker.retry_quota = 1000;
167 
169 
170  ASSERT_EQ(1, checker.should_request_cnt);
171  ASSERT_EQ(1, checker.should_retry_cnt);
172  ASSERT_EQ(0, checker.confirmation_cnt);
173 
174  // Still running!
175  ASSERT_TRUE(trigger.isTimerRunning());
176  ASSERT_EQ(1, trigger.getNumPendingNodes());
177 
178  /*
179  * Trying again, this time with ERROR_IN_PROGRESS
180  */
181  srv_impl.response_error_code = BeginFirmwareUpdate::Response::ERROR_IN_PROGRESS;
182  checker.retry_quota = 0;
183 
185 
186  ASSERT_EQ(1, checker.should_request_cnt);
187  ASSERT_EQ(1, checker.should_retry_cnt);
188  ASSERT_EQ(1, checker.confirmation_cnt);
189 
190  // Stopped!
191  ASSERT_FALSE(trigger.isTimerRunning());
192  ASSERT_EQ(0, trigger.getNumPendingNodes());
193 
194  /*
195  * Restarting the node info provider
196  * Now it doesn't need an update
197  */
198  provider.reset(new uavcan::NodeStatusProvider(nodes.b));
199 
200  provider->setName("Dmitry");
201  provider->setHardwareVersion(hwver);
202 
203  ASSERT_LE(0, provider->startAndPublish());
204 
206 
207  ASSERT_EQ(2, checker.should_request_cnt);
208  ASSERT_EQ(1, checker.should_retry_cnt);
209  ASSERT_EQ(1, checker.confirmation_cnt);
210 
211  // Stopped!
212  ASSERT_FALSE(trigger.isTimerRunning());
213  ASSERT_EQ(0, trigger.getNumPendingNodes());
214 
215  /*
216  * Final checks
217  */
218  ASSERT_EQ(0, nodes.a.internal_failure_count);
219  ASSERT_EQ(0, nodes.b.internal_failure_count);
220 }
221 
222 
223 TEST(FirmwareUpdateTrigger, MultiNode)
224 {
229 
230  TestNetwork<5> nodes;
231 
232  // The trigger node
233  FirmwareVersionChecker checker;
234  uavcan::NodeInfoRetriever node_info_retriever(nodes[0]);
235  uavcan::FirmwareUpdateTrigger trigger(nodes[0], checker);
236 
237  // The client nodes
238  std::unique_ptr<uavcan::NodeStatusProvider> provider_a(new uavcan::NodeStatusProvider(nodes[1]));
239  std::unique_ptr<uavcan::NodeStatusProvider> provider_b(new uavcan::NodeStatusProvider(nodes[2]));
240  std::unique_ptr<uavcan::NodeStatusProvider> provider_c(new uavcan::NodeStatusProvider(nodes[3]));
241  std::unique_ptr<uavcan::NodeStatusProvider> provider_d(new uavcan::NodeStatusProvider(nodes[4]));
242 
243  uavcan::protocol::HardwareVersion hwver;
244 
245  /*
246  * Initializing
247  */
248  ASSERT_LE(0, trigger.start(node_info_retriever, "/path_prefix/"));
249 
250  ASSERT_LE(0, node_info_retriever.start());
251  ASSERT_EQ(1, node_info_retriever.getNumListeners());
252 
253  hwver.unique_id[0] = 0xAA;
254  provider_a->setHardwareVersion(hwver);
255  provider_a->setName("Victor");
256  ASSERT_LE(0, provider_a->startAndPublish());
257 
258  hwver.unique_id[0] = 0xBB;
259  provider_b->setHardwareVersion(hwver);
260  provider_b->setName("Victor");
261  ASSERT_LE(0, provider_b->startAndPublish());
262 
263  hwver.unique_id[0] = 0xCC;
264  provider_c->setHardwareVersion(hwver);
265  provider_c->setName("Alexey");
266  ASSERT_LE(0, provider_c->startAndPublish());
267 
268  hwver.unique_id[0] = 0xDD;
269  provider_d->setHardwareVersion(hwver);
270  provider_d->setName("Victor");
271  ASSERT_LE(0, provider_d->startAndPublish());
272 
273  checker.expected_node_name_to_update = "Victor"; // Victors will get updated, others will not
274  checker.firmware_path = "abc";
275 
276  /*
277  * Running - 3 will timout, 1 will be ignored
278  */
279  ASSERT_FALSE(trigger.isTimerRunning());
280  ASSERT_EQ(0, trigger.getNumPendingNodes());
281 
283 
284  ASSERT_TRUE(trigger.isTimerRunning());
285  ASSERT_EQ(3, trigger.getNumPendingNodes());
286 
287  ASSERT_EQ(4, checker.should_request_cnt);
288  ASSERT_EQ(0, checker.should_retry_cnt);
289  ASSERT_EQ(0, checker.confirmation_cnt);
290 
291  /*
292  * Initializing the BeginFirmwareUpdate servers
293  */
298 
299  BeginFirmwareUpdateServer srv_a_impl;
300  BeginFirmwareUpdateServer srv_b_impl;
301  BeginFirmwareUpdateServer srv_c_impl;
302  BeginFirmwareUpdateServer srv_d_impl;
303 
304  ASSERT_LE(0, srv_a.start(srv_a_impl.makeCallback()));
305  ASSERT_LE(0, srv_b.start(srv_b_impl.makeCallback()));
306  ASSERT_LE(0, srv_c.start(srv_c_impl.makeCallback()));
307  ASSERT_LE(0, srv_d.start(srv_d_impl.makeCallback()));
308 
309  srv_a_impl.response_error_code = BeginFirmwareUpdate::Response::ERROR_INVALID_MODE; // retry
310  srv_b_impl.response_error_code = BeginFirmwareUpdate::Response::ERROR_INVALID_MODE; // retry
311  srv_c_impl.response_error_code = BeginFirmwareUpdate::Response::ERROR_INVALID_MODE; // ignore (see below)
312  srv_d_impl.response_error_code = BeginFirmwareUpdate::Response::ERROR_OK; // OK
313 
314  /*
315  * Spinning, now we're getting some errors
316  * This also checks correctness of the round-robin selector
317  */
318  checker.retry_quota = 2;
319  nodes.spinAll(uavcan::MonotonicDuration::fromMSec(4200)); // Two will retry, one drop, one confirm
320 
321  ASSERT_TRUE(trigger.isTimerRunning());
322 
324  ASSERT_EQ(0, trigger.getNumPendingNodes()); // All removed now
325 
326  EXPECT_EQ(4, checker.should_request_cnt);
327  EXPECT_EQ(4, checker.should_retry_cnt);
328  EXPECT_EQ(1, checker.confirmation_cnt);
329 
330  /*
331  * Waiting for the timer to stop
332  */
334 
335  ASSERT_FALSE(trigger.isTimerRunning());
336 }
response
const std::string response
TestNode::internal_failure_count
uint64_t internal_failure_count
Definition: test_node.hpp:30
FirmwareVersionChecker::expected_node_name_to_update
std::string expected_node_name_to_update
Definition: firmware_update_trigger.cpp:21
FirmwareVersionChecker::handleFirmwareUpdateConfirmation
virtual void handleFirmwareUpdateConfirmation(uavcan::NodeID node_id, const BeginFirmwareUpdate::Response &response)
Definition: firmware_update_trigger.cpp:63
uavcan::NodeInfoRetriever::start
int start(const TransferPriority priority=TransferPriority::OneHigherThanLowest)
Definition: node_info_retriever.hpp:347
uavcan::FirmwareUpdateTrigger::getNumPendingNodes
unsigned getNumPendingNodes() const
Definition: firmware_update_trigger.hpp:465
uavcan::DefaultDataTypeRegistrator
Definition: global_data_type_registry.hpp:186
BeginFirmwareUpdateServer::BeginFirmwareUpdateServer
BeginFirmwareUpdateServer()
Definition: firmware_update_trigger.cpp:75
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
FirmwareVersionChecker::firmware_path
std::string firmware_path
Definition: firmware_update_trigger.cpp:18
BeginFirmwareUpdateServer::makeCallback
Callback makeCallback()
Definition: firmware_update_trigger.cpp:90
TestNetwork
Definition: test_node.hpp:204
uavcan::ReceivedDataStructure
Definition: generic_subscriber.hpp:39
FirmwareVersionChecker::retry_quota
int retry_quota
Definition: firmware_update_trigger.cpp:20
FirmwareVersionChecker::FirmwareVersionChecker
FirmwareVersionChecker()
Definition: firmware_update_trigger.cpp:25
uavcan::IFirmwareVersionChecker
Definition: firmware_update_trigger.hpp:23
BeginFirmwareUpdateServer
Definition: firmware_update_trigger.cpp:71
uavcan::Array
Definition: array.hpp:424
uavcan::ServiceServer
Definition: service_server.hpp:90
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
uavcan::FirmwareUpdateTrigger::isTimerRunning
bool isTimerRunning() const
Definition: firmware_update_trigger.hpp:463
pyuavcan_v0.file
file
Definition: pyuavcan/pyuavcan_v0/__init__.py:42
helpers.hpp
InterlinkedTestNodes
Definition: test_node.hpp:149
firmware_update_trigger.hpp
FirmwareVersionChecker::shouldRequestFirmwareUpdate
virtual bool shouldRequestFirmwareUpdate(uavcan::NodeID node_id, const uavcan::protocol::GetNodeInfo::Response &node_info, FirmwareFilePath &out_firmware_file_path)
Definition: firmware_update_trigger.cpp:32
TestNetwork::spinAll
int spinAll(uavcan::MonotonicDuration duration)
Definition: test_node.hpp:241
uavcan::ServiceServer::start
int start(const Callback &callback)
Definition: service_server.hpp:158
int
int
Definition: libstubs.cpp:120
FirmwareVersionChecker::confirmation_cnt
unsigned confirmation_cnt
Definition: firmware_update_trigger.cpp:16
uavcan::MethodBinder
Definition: method_binder.hpp:20
BeginFirmwareUpdateServer::handleRequest
void handleRequest(const uavcan::ReceivedDataStructure< typename BeginFirmwareUpdate::Request > &req, uavcan::ServiceResponseDataStructure< typename BeginFirmwareUpdate::Response > &res) const
Definition: firmware_update_trigger.cpp:77
FirmwareVersionChecker::last_error_response
BeginFirmwareUpdate::Response last_error_response
Definition: firmware_update_trigger.cpp:23
InterlinkedTestNodes::a
TestNode a
Definition: test_node.hpp:155
InterlinkedTestNodes::spinBoth
int spinBoth(uavcan::MonotonicDuration duration)
Definition: test_node.hpp:176
BeginFirmwareUpdateServer::response_error_code
uint8_t response_error_code
Definition: firmware_update_trigger.cpp:73
FirmwareVersionChecker
Definition: firmware_update_trigger.cpp:12
uavcan::ServiceResponseDataStructure
Definition: service_server.hpp:40
FirmwareVersionChecker::should_retry_cnt
unsigned should_retry_cnt
Definition: firmware_update_trigger.cpp:15
TEST
TEST(FirmwareUpdateTrigger, Basic)
Definition: firmware_update_trigger.cpp:94
uavcan::NodeInfoRetriever
Definition: node_info_retriever.hpp:91
uavcan::GlobalDataTypeRegistry::instance
static GlobalDataTypeRegistry & instance()
Definition: uc_global_data_type_registry.cpp:128
uavcan::NodeInfoRetriever::getNumListeners
unsigned getNumListeners() const
Definition: node_info_retriever.hpp:415
uavcan::FirmwareUpdateTrigger::start
int start(NodeInfoRetriever &node_info_retriever, const FirmwareFilePath &arg_common_path_prefix=FirmwareFilePath(), const TransferPriority priority=TransferPriority::OneHigherThanLowest)
Definition: firmware_update_trigger.hpp:397
InterlinkedTestNodes::b
TestNode b
Definition: test_node.hpp:156
uavcan::ArrayImpl::c_str
const char * c_str() const
Definition: array.hpp:321
node_status_provider.hpp
uavcan::FirmwareUpdateTrigger
Definition: firmware_update_trigger.hpp:136
FirmwareVersionChecker::should_request_cnt
unsigned should_request_cnt
Definition: firmware_update_trigger.cpp:14
FirmwareVersionChecker::shouldRetryFirmwareUpdate
virtual bool shouldRetryFirmwareUpdate(uavcan::NodeID node_id, const BeginFirmwareUpdate::Response &error_response, FirmwareFilePath &out_firmware_file_path)
Definition: firmware_update_trigger.cpp:42


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