Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UAVCAN UAVCAN_Subscriber
Diff: libuavcan/test/protocol/node_status_monitor.cpp
- Revision:
- 0:dfe6edabb8ec
diff -r 000000000000 -r dfe6edabb8ec libuavcan/test/protocol/node_status_monitor.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libuavcan/test/protocol/node_status_monitor.cpp Sat Apr 14 10:25:32 2018 +0000
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
+ */
+
+#include <gtest/gtest.h>
+#include <uavcan/protocol/node_status_monitor.hpp>
+#include <uavcan/protocol/node_status_provider.hpp>
+#include "helpers.hpp"
+
+static void publishNodeStatus(CanDriverMock& can, uavcan::NodeID node_id,
+ uavcan::uint8_t health, uavcan::uint8_t mode,
+ uavcan::uint32_t uptime_sec, uavcan::TransferID tid)
+{
+ uavcan::protocol::NodeStatus msg;
+ msg.health = health;
+ msg.mode = mode;
+ msg.uptime_sec = uptime_sec;
+ emulateSingleFrameBroadcastTransfer(can, node_id, msg, tid);
+}
+
+
+static void shortSpin(TestNode& node)
+{
+ ASSERT_LE(0, node.spin(uavcan::MonotonicDuration::fromMSec(10)));
+}
+
+
+TEST(NodeStatusMonitor, Basic)
+{
+ using uavcan::protocol::NodeStatus;
+ using uavcan::NodeID;
+
+ SystemClockMock clock_mock(100);
+ clock_mock.monotonic_auto_advance = 1000;
+
+ CanDriverMock can(2, clock_mock);
+
+ TestNode node(can, clock_mock, 64);
+
+ uavcan::GlobalDataTypeRegistry::instance().reset();
+ uavcan::DefaultDataTypeRegistrator<uavcan::protocol::NodeStatus> _reg1;
+
+ uavcan::NodeStatusMonitor nsm(node);
+ ASSERT_LE(0, nsm.start());
+
+ ASSERT_LE(0, node.spin(uavcan::MonotonicDuration::fromMSec(10)));
+
+ /*
+ * Empty NSM, no nodes were registered yet
+ */
+ ASSERT_FALSE(nsm.findNodeWithWorstHealth().isValid());
+
+ ASSERT_FALSE(nsm.isNodeKnown(uavcan::NodeID(123)));
+ ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(123)).mode);
+
+ /*
+ * Some new status messages
+ */
+ publishNodeStatus(can, 10, NodeStatus::HEALTH_OK, NodeStatus::MODE_OPERATIONAL, 12, 0);
+ shortSpin(node);
+ ASSERT_EQ(NodeID(10), nsm.findNodeWithWorstHealth());
+
+ publishNodeStatus(can, 9, NodeStatus::HEALTH_WARNING, NodeStatus::MODE_INITIALIZATION, 0, 0);
+ shortSpin(node);
+ ASSERT_EQ(NodeID(9), nsm.findNodeWithWorstHealth());
+
+ publishNodeStatus(can, 11, NodeStatus::HEALTH_CRITICAL, NodeStatus::MODE_MAINTENANCE, 999, 0);
+ shortSpin(node);
+ ASSERT_EQ(NodeID(11), nsm.findNodeWithWorstHealth());
+
+ ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(10)));
+ ASSERT_EQ(NodeStatus::MODE_OPERATIONAL, nsm.getNodeStatus(uavcan::NodeID(10)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_OK, nsm.getNodeStatus(uavcan::NodeID(10)).health);
+
+ ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(9)));
+ ASSERT_EQ(NodeStatus::MODE_INITIALIZATION, nsm.getNodeStatus(uavcan::NodeID(9)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_WARNING, nsm.getNodeStatus(uavcan::NodeID(9)).health);
+
+ ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(11)));
+ ASSERT_EQ(NodeStatus::MODE_MAINTENANCE, nsm.getNodeStatus(uavcan::NodeID(11)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_CRITICAL, nsm.getNodeStatus(uavcan::NodeID(11)).health);
+
+ /*
+ * Timeout
+ */
+ std::cout << "Starting timeout test, current monotime is " << clock_mock.monotonic << std::endl;
+
+ clock_mock.advance(500000);
+ shortSpin(node);
+ ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(10)));
+ ASSERT_EQ(NodeStatus::MODE_OPERATIONAL, nsm.getNodeStatus(uavcan::NodeID(10)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_OK, nsm.getNodeStatus(uavcan::NodeID(10)).health);
+
+ clock_mock.advance(500000);
+ shortSpin(node);
+ ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(9)));
+ ASSERT_EQ(NodeStatus::MODE_INITIALIZATION, nsm.getNodeStatus(uavcan::NodeID(9)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_WARNING, nsm.getNodeStatus(uavcan::NodeID(9)).health);
+
+ clock_mock.advance(500000);
+ shortSpin(node);
+ ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(11)));
+ ASSERT_EQ(NodeStatus::MODE_MAINTENANCE, nsm.getNodeStatus(uavcan::NodeID(11)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_CRITICAL, nsm.getNodeStatus(uavcan::NodeID(11)).health);
+
+ /*
+ * Will timeout now
+ */
+ clock_mock.advance(4000000);
+ shortSpin(node);
+
+ ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(10)));
+ ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(10)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_OK, nsm.getNodeStatus(uavcan::NodeID(10)).health);
+
+ ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(9)));
+ ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(9)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_WARNING, nsm.getNodeStatus(uavcan::NodeID(9)).health);
+
+ ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(11)));
+ ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(11)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_CRITICAL, nsm.getNodeStatus(uavcan::NodeID(11)).health);
+
+ /*
+ * Recovering one node, adding two extra
+ */
+ publishNodeStatus(can, 11, NodeStatus::HEALTH_WARNING, NodeStatus::MODE_OPERATIONAL, 999, 1);
+ shortSpin(node);
+
+ publishNodeStatus(can, 127, NodeStatus::HEALTH_WARNING, NodeStatus::MODE_OPERATIONAL, 9999, 1);
+ shortSpin(node);
+
+ publishNodeStatus(can, 1, NodeStatus::HEALTH_OK, NodeStatus::MODE_OPERATIONAL, 1234, 1);
+ shortSpin(node);
+
+ /*
+ * Making sure OFFLINE is still worst status
+ */
+ ASSERT_EQ(NodeID(9), nsm.findNodeWithWorstHealth());
+
+ /*
+ * Final validation
+ */
+ ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(10)));
+ ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(10)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_OK, nsm.getNodeStatus(uavcan::NodeID(10)).health);
+
+ ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(9)));
+ ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(9)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_WARNING, nsm.getNodeStatus(uavcan::NodeID(9)).health);
+
+ ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(11)));
+ ASSERT_EQ(NodeStatus::MODE_OPERATIONAL, nsm.getNodeStatus(uavcan::NodeID(11)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_WARNING, nsm.getNodeStatus(uavcan::NodeID(11)).health);
+
+ ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(127)));
+ ASSERT_EQ(NodeStatus::MODE_OPERATIONAL, nsm.getNodeStatus(uavcan::NodeID(127)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_WARNING, nsm.getNodeStatus(uavcan::NodeID(127)).health);
+
+ ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(1)));
+ ASSERT_EQ(NodeStatus::MODE_OPERATIONAL, nsm.getNodeStatus(uavcan::NodeID(1)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_OK, nsm.getNodeStatus(uavcan::NodeID(1)).health);
+
+ /*
+ * Forgetting
+ */
+ nsm.forgetNode(127);
+ ASSERT_FALSE(nsm.isNodeKnown(uavcan::NodeID(127)));
+ ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(127)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_CRITICAL, nsm.getNodeStatus(uavcan::NodeID(127)).health);
+
+ nsm.forgetNode(9);
+ ASSERT_FALSE(nsm.isNodeKnown(uavcan::NodeID(9)));
+ ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(9)).mode);
+ ASSERT_EQ(NodeStatus::HEALTH_CRITICAL, nsm.getNodeStatus(uavcan::NodeID(9)).health);
+}