From 518e105809d4ab2bc883d14938a156ddc63a7ef5 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Sat, 14 Jun 2014 12:38:50 +0400 Subject: [PATCH] NetworkCompatChecker can tolerate no-response from CATS service. This allows nodes to not implement services at all while being UAVCAN compatible. --- .../uavcan/protocol/network_compat_checker.hpp | 4 ++++ .../src/protocol/uc_network_compat_checker.cpp | 15 ++++++--------- .../test/protocol/network_compat_checker.cpp | 17 +++++++++++------ 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/libuavcan/include/uavcan/protocol/network_compat_checker.hpp b/libuavcan/include/uavcan/protocol/network_compat_checker.hpp index 2f72c189a7..d7a0a05e75 100644 --- a/libuavcan/include/uavcan/protocol/network_compat_checker.hpp +++ b/libuavcan/include/uavcan/protocol/network_compat_checker.hpp @@ -40,6 +40,7 @@ class UAVCAN_EXPORT NetworkCompatibilityChecker : Noncopyable NodeIDMask nid_mask_checked_; NetworkCompatibilityCheckResult result_; DataTypeKind checking_dtkind_; + uint8_t num_failed_nodes_; bool last_cats_request_ok_; INode& getNode() { return ns_sub_.getNode(); } @@ -63,11 +64,14 @@ public: : ns_sub_(node) , cats_cln_(node) , checking_dtkind_(DataTypeKindService) + , num_failed_nodes_(0) , last_cats_request_ok_(false) { } int execute(); + uint8_t getNumFailedNodes() const { return num_failed_nodes_; } + const NetworkCompatibilityCheckResult& getResult() const { return result_; } static int publishGlobalDiscoveryRequest(INode& node); diff --git a/libuavcan/src/protocol/uc_network_compat_checker.cpp b/libuavcan/src/protocol/uc_network_compat_checker.cpp index b4488d4573..e4ae61836e 100644 --- a/libuavcan/src/protocol/uc_network_compat_checker.cpp +++ b/libuavcan/src/protocol/uc_network_compat_checker.cpp @@ -132,21 +132,18 @@ int NetworkCompatibilityChecker::checkOneNode(NodeID nid) int NetworkCompatibilityChecker::checkNodes() { (void)nid_mask_checked_.reset(); - while (true) + num_failed_nodes_ = 0; + result_ = NetworkCompatibilityCheckResult(); + + while (result_.isOk()) { const NodeID nid = findNextUncheckedNode(); if (nid.isValid()) { UAVCAN_TRACE("NodeInitializer", "Checking nid=%i", int(nid.get())); const int res = checkOneNode(nid); - if (res < 0 || !result_.isOk()) - { - return res; - } - if (cats_cln_.getResponseFailureCount() > 0) - { - return -cats_cln_.getResponseFailureCount(); - } + num_failed_nodes_ += (res < 0) ? 1U : 0U; + UAVCAN_TRACE("NodeInitializer", "Checked nid=%i result=%i", int(nid.get()), res); } else { break; } } diff --git a/libuavcan/test/protocol/network_compat_checker.cpp b/libuavcan/test/protocol/network_compat_checker.cpp index 00220f9328..7c62fce586 100644 --- a/libuavcan/test/protocol/network_compat_checker.cpp +++ b/libuavcan/test/protocol/network_compat_checker.cpp @@ -22,12 +22,12 @@ static void registerTypes() } -struct NodeInitializerRemoteContext +struct NetworkCompatibilityCheckerRemoteContext { uavcan::NodeStatusProvider node_status_provider; uavcan::DataTypeInfoProvider data_type_info_provider; - NodeInitializerRemoteContext(uavcan::INode& node) + NetworkCompatibilityCheckerRemoteContext(uavcan::INode& node) : node_status_provider(node) , data_type_info_provider(node) { @@ -71,7 +71,7 @@ TEST(NetworkCompatibilityChecker, Success) { registerTypes(); InterlinkedTestNodesWithSysClock nodes; - NodeInitializerRemoteContext remote(nodes.b); + NetworkCompatibilityCheckerRemoteContext remote(nodes.b); remote.start(); BackgroundSpinner bgspinner(nodes.b, nodes.a); @@ -89,13 +89,18 @@ TEST(NetworkCompatibilityChecker, RequestTimeout) { registerTypes(); InterlinkedTestNodesWithSysClock nodes; - NodeInitializerRemoteContext remote(nodes.b); + NetworkCompatibilityCheckerRemoteContext remote(nodes.b); remote.start(); ASSERT_LE(0, uavcan::NetworkCompatibilityChecker::publishGlobalDiscoveryRequest(nodes.a)); uavcan::NetworkCompatibilityChecker ni(nodes.a); - ASSERT_GT(0, ni.execute()); // There is no background spinner, so CATS request will time out + // There is no background spinner, so CATS request will time out + // Despite the time out, the checker will not report failure + ASSERT_EQ(0, ni.execute()); + + // The one (and only) node has failed + ASSERT_EQ(1, ni.getNumFailedNodes()); } @@ -103,7 +108,7 @@ TEST(NetworkCompatibilityChecker, NodeIDCollision) { registerTypes(); InterlinkedTestNodesWithSysClock nodes(8, 8); // Same NID - NodeInitializerRemoteContext remote(nodes.b); + NetworkCompatibilityCheckerRemoteContext remote(nodes.b); remote.start(); BackgroundSpinner bgspinner(nodes.b, nodes.a);