020-two-supervisors.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. //
  2. // Copyright (c) 2019-2020 Ivan Baidakou (basiliscos) (the dot dmol at gmail dot com)
  3. //
  4. // Distributed under the MIT Software License
  5. //
  6. #include "catch.hpp"
  7. #include "rotor.hpp"
  8. #include "supervisor_test.h"
  9. #include "access.h"
  10. namespace r = rotor;
  11. namespace rt = r::test;
  12. static size_t destroyed = 0;
  13. struct my_supervisor_t : public rt::supervisor_test_t {
  14. using rt::supervisor_test_t::supervisor_test_t;
  15. void init_start() noexcept override {
  16. rt::supervisor_test_t::init_start();
  17. assert(state == r::state_t::INITIALIZING);
  18. init_start_count++;
  19. }
  20. void init_finish() noexcept override {
  21. rt::supervisor_test_t::init_finish();
  22. assert(state == r::state_t::INITIALIZED);
  23. init_finish_count++;
  24. }
  25. void shutdown_start() noexcept override {
  26. rt::supervisor_test_t::shutdown_start();
  27. shutdown_start_count++;
  28. assert(state == r::state_t::SHUTTING_DOWN);
  29. }
  30. void shutdown_finish() noexcept override {
  31. rt::supervisor_test_t::shutdown_finish();
  32. shutdown_finish_count++;
  33. assert(state == r::state_t::SHUT_DOWN);
  34. }
  35. ~my_supervisor_t() { ++destroyed; }
  36. std::uint32_t init_start_count = 0;
  37. std::uint32_t init_finish_count = 0;
  38. std::uint32_t shutdown_start_count = 0;
  39. std::uint32_t shutdown_finish_count = 0;
  40. };
  41. TEST_CASE("two supervisors, different localities, shutdown 2nd", "[supervisor]") {
  42. r::system_context_t system_context;
  43. const char locality1[] = "abc";
  44. const char locality2[] = "def";
  45. auto sup1 =
  46. system_context.create_supervisor<my_supervisor_t>().locality(locality1).timeout(rt::default_timeout).finish();
  47. auto sup2 = sup1->create_actor<my_supervisor_t>().locality(locality2).timeout(rt::default_timeout).finish();
  48. REQUIRE(&sup2->get_supervisor() == sup2.get());
  49. REQUIRE(sup2->access<rt::to::parent_supervisor>() == sup1.get());
  50. sup1->do_process();
  51. REQUIRE(sup1->get_state() == r::state_t::INITIALIZING);
  52. REQUIRE(sup2->get_state() == r::state_t::INITIALIZING);
  53. REQUIRE(sup1->init_start_count == 1);
  54. REQUIRE(sup1->init_finish_count == 0);
  55. REQUIRE(sup2->init_start_count == 1);
  56. REQUIRE(sup2->init_finish_count == 0);
  57. sup2->do_process();
  58. REQUIRE(sup1->get_state() == r::state_t::INITIALIZING);
  59. REQUIRE(sup2->get_state() == r::state_t::INITIALIZED);
  60. REQUIRE(sup1->init_start_count == 1);
  61. REQUIRE(sup1->init_finish_count == 0);
  62. REQUIRE(sup2->init_start_count == 1);
  63. REQUIRE(sup2->init_finish_count == 1);
  64. sup1->do_process();
  65. REQUIRE(sup1->init_start_count == 1);
  66. REQUIRE(sup1->init_finish_count == 1);
  67. REQUIRE(sup2->init_start_count == 1);
  68. REQUIRE(sup2->init_finish_count == 1);
  69. REQUIRE(sup1->get_state() == r::state_t::OPERATIONAL);
  70. REQUIRE(sup2->get_state() == r::state_t::INITIALIZED);
  71. REQUIRE(sup1->shutdown_start_count == 0);
  72. sup2->do_process();
  73. REQUIRE(sup2->get_state() == r::state_t::OPERATIONAL);
  74. REQUIRE(sup1->init_start_count == 1);
  75. REQUIRE(sup1->init_finish_count == 1);
  76. REQUIRE(sup2->init_start_count == 1);
  77. REQUIRE(sup2->init_finish_count == 1);
  78. REQUIRE(sup2->shutdown_start_count == 0);
  79. REQUIRE(sup1->shutdown_start_count == 0);
  80. sup2->do_shutdown();
  81. sup2->do_process();
  82. REQUIRE(sup1->shutdown_start_count == 0);
  83. REQUIRE(sup1->shutdown_finish_count == 0);
  84. REQUIRE(sup2->shutdown_start_count == 0);
  85. REQUIRE(sup2->shutdown_finish_count == 0);
  86. sup1->do_process();
  87. REQUIRE(sup1->shutdown_start_count == 0);
  88. REQUIRE(sup1->shutdown_finish_count == 0);
  89. REQUIRE(sup2->shutdown_start_count == 0);
  90. REQUIRE(sup2->shutdown_finish_count == 0);
  91. sup2->do_process();
  92. REQUIRE(sup1->get_state() == r::state_t::OPERATIONAL);
  93. REQUIRE(sup2->get_state() == r::state_t::SHUT_DOWN);
  94. REQUIRE(sup1->shutdown_start_count == 0);
  95. REQUIRE(sup1->shutdown_finish_count == 0);
  96. REQUIRE(sup2->shutdown_start_count == 1);
  97. REQUIRE(sup2->shutdown_finish_count == 1);
  98. sup1->do_process();
  99. REQUIRE(sup1->get_state() == r::state_t::OPERATIONAL);
  100. REQUIRE(sup2->get_state() == r::state_t::SHUT_DOWN);
  101. REQUIRE(sup1->shutdown_start_count == 0);
  102. REQUIRE(sup1->shutdown_finish_count == 0);
  103. REQUIRE(sup2->shutdown_start_count == 1);
  104. REQUIRE(sup2->shutdown_finish_count == 1);
  105. sup1->do_shutdown();
  106. sup1->do_process();
  107. REQUIRE(sup1->get_state() == r::state_t::SHUT_DOWN);
  108. REQUIRE(sup1->shutdown_start_count == 1);
  109. REQUIRE(sup1->shutdown_finish_count == 1);
  110. REQUIRE(sup1->get_leader_queue().size() == 0);
  111. REQUIRE(sup1->get_points().size() == 0);
  112. REQUIRE(rt::empty(sup1->get_subscription()));
  113. REQUIRE(sup2->get_leader_queue().size() == 0);
  114. REQUIRE(sup2->get_points().size() == 0);
  115. REQUIRE(rt::empty(sup2->get_subscription()));
  116. }
  117. TEST_CASE("two supervisors, different localities, shutdown 1st", "[supervisor]") {
  118. r::system_context_t system_context;
  119. const char locality1[] = "abc";
  120. const char locality2[] = "def";
  121. auto sup1 =
  122. system_context.create_supervisor<my_supervisor_t>().locality(locality1).timeout(rt::default_timeout).finish();
  123. auto sup2 = sup1->create_actor<my_supervisor_t>().locality(locality2).timeout(rt::default_timeout).finish();
  124. REQUIRE(&sup2->get_supervisor() == sup2.get());
  125. REQUIRE(sup2->access<rt::to::parent_supervisor>() == sup1.get());
  126. sup1->do_process();
  127. sup2->do_process();
  128. sup1->do_process();
  129. sup2->do_process();
  130. REQUIRE(sup1->get_state() == r::state_t::OPERATIONAL);
  131. REQUIRE(sup2->get_state() == r::state_t::OPERATIONAL);
  132. sup1->do_shutdown();
  133. while (!sup1->get_leader_queue().empty() || !sup2->get_leader_queue().empty()) {
  134. sup1->do_process();
  135. sup2->do_process();
  136. }
  137. CHECK(sup1->get_state() == r::state_t::SHUT_DOWN);
  138. CHECK(sup2->get_state() == r::state_t::SHUT_DOWN);
  139. REQUIRE(sup1->get_leader_queue().size() == 0);
  140. REQUIRE(sup1->get_points().size() == 0);
  141. REQUIRE(rt::empty(sup1->get_subscription()));
  142. REQUIRE(sup2->get_leader_queue().size() == 0);
  143. REQUIRE(sup2->get_points().size() == 0);
  144. REQUIRE(rt::empty(sup2->get_subscription()));
  145. }
  146. TEST_CASE("two supervisors, same locality", "[supervisor]") {
  147. r::system_context_ptr_t system_context = new r::system_context_t();
  148. auto mark = destroyed;
  149. const char locality[] = "locality";
  150. auto sup1 =
  151. system_context->create_supervisor<my_supervisor_t>().locality(locality).timeout(rt::default_timeout).finish();
  152. auto sup2 = sup1->create_actor<my_supervisor_t>().locality(locality).timeout(rt::default_timeout).finish();
  153. REQUIRE(&sup2->get_supervisor() == sup2.get());
  154. REQUIRE(sup2->access<rt::to::parent_supervisor>() == sup1.get());
  155. sup1->do_process();
  156. REQUIRE(sup1->get_state() == r::state_t::OPERATIONAL);
  157. REQUIRE(sup2->get_state() == r::state_t::OPERATIONAL);
  158. REQUIRE(sup1->init_start_count == 1);
  159. REQUIRE(sup1->init_finish_count == 1);
  160. REQUIRE(sup2->init_start_count == 1);
  161. REQUIRE(sup2->init_finish_count == 1);
  162. sup1->do_shutdown();
  163. sup1->do_process();
  164. REQUIRE(sup1->get_state() == r::state_t::SHUT_DOWN);
  165. REQUIRE(sup2->get_state() == r::state_t::SHUT_DOWN);
  166. REQUIRE(sup1->shutdown_start_count == 1);
  167. REQUIRE(sup1->get_leader_queue().size() == 0);
  168. REQUIRE(sup1->get_points().size() == 0);
  169. REQUIRE(rt::empty(sup1->get_subscription()));
  170. REQUIRE(sup2->get_leader_queue().size() == 0);
  171. REQUIRE(sup2->get_points().size() == 0);
  172. REQUIRE(rt::empty(sup2->get_subscription()));
  173. system_context.reset();
  174. sup1.reset();
  175. sup2.reset();
  176. REQUIRE(mark + 2 == destroyed);
  177. }
  178. TEST_CASE("two supervisors, down internal first, same locality", "[supervisor]") {
  179. r::system_context_t system_context;
  180. const char locality[] = "locality";
  181. auto sup1 =
  182. system_context.create_supervisor<my_supervisor_t>().timeout(rt::default_timeout).locality(locality).finish();
  183. auto sup2 = sup1->create_actor<my_supervisor_t>().timeout(rt::default_timeout).locality(locality).finish();
  184. REQUIRE(&sup2->get_supervisor() == sup2.get());
  185. REQUIRE(sup2->access<rt::to::parent_supervisor>() == sup1.get());
  186. sup1->do_process();
  187. REQUIRE(sup1->get_state() == r::state_t::OPERATIONAL);
  188. REQUIRE(sup2->get_state() == r::state_t::OPERATIONAL);
  189. // for better coverage
  190. auto &address = static_cast<r::actor_base_t *>(sup2.get())->get_address();
  191. sup2->send<r::payload::shutdown_trigger_t>(address, address);
  192. sup1->do_process();
  193. REQUIRE(sup2->get_state() == r::state_t::SHUT_DOWN);
  194. REQUIRE(sup1->get_state() == r::state_t::OPERATIONAL);
  195. sup1->do_shutdown();
  196. sup1->do_process();
  197. REQUIRE(sup1->get_state() == r::state_t::SHUT_DOWN);
  198. REQUIRE(sup1->get_leader_queue().size() == 0);
  199. REQUIRE(sup1->get_points().size() == 0);
  200. REQUIRE(rt::empty(sup1->get_subscription()));
  201. REQUIRE(sup2->get_leader_queue().size() == 0);
  202. REQUIRE(sup2->get_points().size() == 0);
  203. REQUIRE(rt::empty(sup2->get_subscription()));
  204. }