32-hierarchy.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // SPDX-License-Identifier: MIT
  2. // SPDX-FileCopyrightText: 2022 Ivan Baidakou
  3. #if defined(__ANDROID__)
  4. #undef __ANDROID__
  5. #endif
  6. #include "catch.hpp"
  7. #include "rotor-light/planner.hpp"
  8. #include "rotor-light/queue.hpp"
  9. #include "rotor-light/supervisor.hpp"
  10. #include <string>
  11. using namespace rotor_light;
  12. using MessageStorage =
  13. traits::MessageStorage<message::ChangeState, message::ChangeStateAck>;
  14. using AppQueue = Queue<MessageStorage, 5>;
  15. using AppPlanner = Planner<1>;
  16. TEST_CASE("normal hierarchy", "[hierarchy]") {
  17. struct A1 : Actor<1> {
  18. using Parent = Actor<1>;
  19. using Parent::Parent;
  20. };
  21. struct S1_1 : Supervisor<3, A1> {
  22. using Parent = Supervisor<3, A1>;
  23. using Parent::Parent;
  24. };
  25. struct S1_2 : Supervisor<3, S1_1> {
  26. using Parent = Supervisor<3, S1_1>;
  27. using Parent::Parent;
  28. };
  29. AppQueue queue;
  30. AppPlanner planner;
  31. Context context{&queue, &planner, nullptr};
  32. S1_2 sup;
  33. sup.bind(context);
  34. auto sup2 = sup.get_child<0>();
  35. auto act = sup2->get_child<0>();
  36. sup.start();
  37. sup.process();
  38. CHECK(sup.get_state() == State::operational);
  39. CHECK(sup2->get_state() == State::operational);
  40. CHECK(act->get_state() == State::operational);
  41. SECTION("stop root supervisor") {
  42. sup.stop();
  43. sup.process();
  44. CHECK(sup.get_state() == State::off);
  45. CHECK(sup2->get_state() == State::off);
  46. CHECK(act->get_state() == State::off);
  47. }
  48. SECTION("manual stop") {
  49. sup2->stop();
  50. sup.process();
  51. CHECK(sup.get_state() == State::operational);
  52. CHECK(sup2->get_state() == State::off);
  53. CHECK(act->get_state() == State::off);
  54. sup.stop();
  55. sup.process();
  56. CHECK(sup.get_state() == State::off);
  57. }
  58. }
  59. TEST_CASE("auto collapse hierarchy", "[hierarchy]") {
  60. struct A1 : Actor<1> {
  61. using Parent = Actor<1>;
  62. using Parent::Parent;
  63. };
  64. struct A2 : Actor<1> {
  65. using Parent = Actor<1>;
  66. using Parent::Parent;
  67. void advance_init() override {
  68. send<ctx::thread, message::ChangeStateAck>(0, supervisor->get_id(), id,
  69. State::initialized, false);
  70. init_attempted = true;
  71. }
  72. bool init_attempted = false;
  73. };
  74. struct S1_1 : Supervisor<3, A1, A2> {
  75. using Parent = Supervisor<3, A1, A2>;
  76. using Parent::Parent;
  77. };
  78. struct S1_2 : Supervisor<3, S1_1> {
  79. using Parent = Supervisor<3, S1_1>;
  80. using Parent::Parent;
  81. };
  82. AppQueue queue;
  83. AppPlanner planner;
  84. Context context{&queue, &planner, nullptr};
  85. S1_2 sup;
  86. sup.bind(context);
  87. auto sup2 = sup.get_child<0>();
  88. auto act1 = sup2->get_child<0>();
  89. auto act2 = sup2->get_child<1>();
  90. sup.start();
  91. sup.process();
  92. CHECK(sup.get_state() == State::off);
  93. CHECK(sup2->get_state() == State::off);
  94. CHECK(act1->get_state() == State::off);
  95. CHECK(act2->get_state() == State::off);
  96. REQUIRE(act2->init_attempted);
  97. }