node_status_monitor.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
  3. */
  4. #include <gtest/gtest.h>
  5. #include <uavcan/protocol/node_status_monitor.hpp>
  6. #include <uavcan/protocol/node_status_provider.hpp>
  7. #include "helpers.hpp"
  8. static void publishNodeStatus(CanDriverMock& can, uavcan::NodeID node_id,
  9. uavcan::uint8_t health, uavcan::uint8_t mode,
  10. uavcan::uint32_t uptime_sec, uavcan::TransferID tid)
  11. {
  12. uavcan::protocol::NodeStatus msg;
  13. msg.health = health;
  14. msg.mode = mode;
  15. msg.uptime_sec = uptime_sec;
  16. emulateSingleFrameBroadcastTransfer(can, node_id, msg, tid);
  17. }
  18. static void shortSpin(TestNode& node)
  19. {
  20. ASSERT_LE(0, node.spin(uavcan::MonotonicDuration::fromMSec(10)));
  21. }
  22. TEST(NodeStatusMonitor, Basic)
  23. {
  24. using uavcan::protocol::NodeStatus;
  25. using uavcan::NodeID;
  26. SystemClockMock clock_mock(100);
  27. clock_mock.monotonic_auto_advance = 1000;
  28. CanDriverMock can(2, clock_mock);
  29. TestNode node(can, clock_mock, 64);
  30. uavcan::GlobalDataTypeRegistry::instance().reset();
  31. uavcan::DefaultDataTypeRegistrator<uavcan::protocol::NodeStatus> _reg1;
  32. uavcan::NodeStatusMonitor nsm(node);
  33. ASSERT_LE(0, nsm.start());
  34. ASSERT_LE(0, node.spin(uavcan::MonotonicDuration::fromMSec(10)));
  35. /*
  36. * Empty NSM, no nodes were registered yet
  37. */
  38. ASSERT_FALSE(nsm.findNodeWithWorstHealth().isValid());
  39. ASSERT_FALSE(nsm.isNodeKnown(uavcan::NodeID(123)));
  40. ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(123)).mode);
  41. /*
  42. * Some new status messages
  43. */
  44. publishNodeStatus(can, 10, NodeStatus::HEALTH_OK, NodeStatus::MODE_OPERATIONAL, 12, 0);
  45. shortSpin(node);
  46. ASSERT_EQ(NodeID(10), nsm.findNodeWithWorstHealth());
  47. publishNodeStatus(can, 9, NodeStatus::HEALTH_WARNING, NodeStatus::MODE_INITIALIZATION, 0, 0);
  48. shortSpin(node);
  49. ASSERT_EQ(NodeID(9), nsm.findNodeWithWorstHealth());
  50. publishNodeStatus(can, 11, NodeStatus::HEALTH_CRITICAL, NodeStatus::MODE_MAINTENANCE, 999, 0);
  51. shortSpin(node);
  52. ASSERT_EQ(NodeID(11), nsm.findNodeWithWorstHealth());
  53. ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(10)));
  54. ASSERT_EQ(NodeStatus::MODE_OPERATIONAL, nsm.getNodeStatus(uavcan::NodeID(10)).mode);
  55. ASSERT_EQ(NodeStatus::HEALTH_OK, nsm.getNodeStatus(uavcan::NodeID(10)).health);
  56. ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(9)));
  57. ASSERT_EQ(NodeStatus::MODE_INITIALIZATION, nsm.getNodeStatus(uavcan::NodeID(9)).mode);
  58. ASSERT_EQ(NodeStatus::HEALTH_WARNING, nsm.getNodeStatus(uavcan::NodeID(9)).health);
  59. ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(11)));
  60. ASSERT_EQ(NodeStatus::MODE_MAINTENANCE, nsm.getNodeStatus(uavcan::NodeID(11)).mode);
  61. ASSERT_EQ(NodeStatus::HEALTH_CRITICAL, nsm.getNodeStatus(uavcan::NodeID(11)).health);
  62. /*
  63. * Timeout
  64. */
  65. std::cout << "Starting timeout test, current monotime is " << clock_mock.monotonic << std::endl;
  66. clock_mock.advance(500000);
  67. shortSpin(node);
  68. ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(10)));
  69. ASSERT_EQ(NodeStatus::MODE_OPERATIONAL, nsm.getNodeStatus(uavcan::NodeID(10)).mode);
  70. ASSERT_EQ(NodeStatus::HEALTH_OK, nsm.getNodeStatus(uavcan::NodeID(10)).health);
  71. clock_mock.advance(500000);
  72. shortSpin(node);
  73. ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(9)));
  74. ASSERT_EQ(NodeStatus::MODE_INITIALIZATION, nsm.getNodeStatus(uavcan::NodeID(9)).mode);
  75. ASSERT_EQ(NodeStatus::HEALTH_WARNING, nsm.getNodeStatus(uavcan::NodeID(9)).health);
  76. clock_mock.advance(500000);
  77. shortSpin(node);
  78. ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(11)));
  79. ASSERT_EQ(NodeStatus::MODE_MAINTENANCE, nsm.getNodeStatus(uavcan::NodeID(11)).mode);
  80. ASSERT_EQ(NodeStatus::HEALTH_CRITICAL, nsm.getNodeStatus(uavcan::NodeID(11)).health);
  81. /*
  82. * Will timeout now
  83. */
  84. clock_mock.advance(4000000);
  85. shortSpin(node);
  86. ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(10)));
  87. ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(10)).mode);
  88. ASSERT_EQ(NodeStatus::HEALTH_OK, nsm.getNodeStatus(uavcan::NodeID(10)).health);
  89. ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(9)));
  90. ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(9)).mode);
  91. ASSERT_EQ(NodeStatus::HEALTH_WARNING, nsm.getNodeStatus(uavcan::NodeID(9)).health);
  92. ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(11)));
  93. ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(11)).mode);
  94. ASSERT_EQ(NodeStatus::HEALTH_CRITICAL, nsm.getNodeStatus(uavcan::NodeID(11)).health);
  95. /*
  96. * Recovering one node, adding two extra
  97. */
  98. publishNodeStatus(can, 11, NodeStatus::HEALTH_WARNING, NodeStatus::MODE_OPERATIONAL, 999, 1);
  99. shortSpin(node);
  100. publishNodeStatus(can, 127, NodeStatus::HEALTH_WARNING, NodeStatus::MODE_OPERATIONAL, 9999, 1);
  101. shortSpin(node);
  102. publishNodeStatus(can, 1, NodeStatus::HEALTH_OK, NodeStatus::MODE_OPERATIONAL, 1234, 1);
  103. shortSpin(node);
  104. /*
  105. * Making sure OFFLINE is still worst status
  106. */
  107. ASSERT_EQ(NodeID(9), nsm.findNodeWithWorstHealth());
  108. /*
  109. * Final validation
  110. */
  111. ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(10)));
  112. ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(10)).mode);
  113. ASSERT_EQ(NodeStatus::HEALTH_OK, nsm.getNodeStatus(uavcan::NodeID(10)).health);
  114. ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(9)));
  115. ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(9)).mode);
  116. ASSERT_EQ(NodeStatus::HEALTH_WARNING, nsm.getNodeStatus(uavcan::NodeID(9)).health);
  117. ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(11)));
  118. ASSERT_EQ(NodeStatus::MODE_OPERATIONAL, nsm.getNodeStatus(uavcan::NodeID(11)).mode);
  119. ASSERT_EQ(NodeStatus::HEALTH_WARNING, nsm.getNodeStatus(uavcan::NodeID(11)).health);
  120. ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(127)));
  121. ASSERT_EQ(NodeStatus::MODE_OPERATIONAL, nsm.getNodeStatus(uavcan::NodeID(127)).mode);
  122. ASSERT_EQ(NodeStatus::HEALTH_WARNING, nsm.getNodeStatus(uavcan::NodeID(127)).health);
  123. ASSERT_TRUE(nsm.isNodeKnown(uavcan::NodeID(1)));
  124. ASSERT_EQ(NodeStatus::MODE_OPERATIONAL, nsm.getNodeStatus(uavcan::NodeID(1)).mode);
  125. ASSERT_EQ(NodeStatus::HEALTH_OK, nsm.getNodeStatus(uavcan::NodeID(1)).health);
  126. /*
  127. * Forgetting
  128. */
  129. nsm.forgetNode(127);
  130. ASSERT_FALSE(nsm.isNodeKnown(uavcan::NodeID(127)));
  131. ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(127)).mode);
  132. ASSERT_EQ(NodeStatus::HEALTH_CRITICAL, nsm.getNodeStatus(uavcan::NodeID(127)).health);
  133. nsm.forgetNode(9);
  134. ASSERT_FALSE(nsm.isNodeKnown(uavcan::NodeID(9)));
  135. ASSERT_EQ(NodeStatus::MODE_OFFLINE, nsm.getNodeStatus(uavcan::NodeID(9)).mode);
  136. ASSERT_EQ(NodeStatus::HEALTH_CRITICAL, nsm.getNodeStatus(uavcan::NodeID(9)).health);
  137. }