012-actor-lifetime.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. //
  2. // Copyright (c) 2019 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. namespace r = rotor;
  10. namespace rt = r::test;
  11. static std::uint32_t destroyed = 0;
  12. struct sample_actor_t : public r::actor_base_t {
  13. std::uint32_t event_current;
  14. std::uint32_t event_init;
  15. std::uint32_t event_start;
  16. std::uint32_t event_shutdown;
  17. std::uint32_t event_shutingdown;
  18. r::state_t &get_state() noexcept { return state; }
  19. sample_actor_t(r::supervisor_t &sup) : r::actor_base_t{sup} {
  20. event_current = 1;
  21. event_init = 0;
  22. event_start = 0;
  23. event_shutdown = 0;
  24. event_shutingdown = 0;
  25. }
  26. ~sample_actor_t() override { ++destroyed; }
  27. void on_initialize(r::message::init_request_t &msg) noexcept override {
  28. event_init = event_current++;
  29. r::actor_base_t::on_initialize(msg);
  30. }
  31. void on_start(r::message_t<r::payload::start_actor_t> &msg) noexcept override {
  32. event_start = event_current++;
  33. r::actor_base_t::on_start(msg);
  34. }
  35. void shutdown_start() noexcept override {
  36. r::actor_base_t::shutdown_start();
  37. if (state == r::state_t::SHUTTING_DOWN) {
  38. event_shutingdown = event_current++;
  39. }
  40. }
  41. void shutdown_finish() noexcept override {
  42. if (state == r::state_t::SHUTTED_DOWN) {
  43. event_shutdown = event_current++;
  44. }
  45. r::actor_base_t::shutdown_finish();
  46. }
  47. };
  48. struct fail_shutdown_actor : public r::actor_base_t {
  49. using r::actor_base_t::actor_base_t;
  50. bool allow_shutdown = false;
  51. void shutdown_start() noexcept override {
  52. if (allow_shutdown) {
  53. r::actor_base_t::shutdown_start();
  54. }
  55. }
  56. };
  57. struct double_shutdown_actor : public r::actor_base_t {
  58. using r::actor_base_t::actor_base_t;
  59. std::uint32_t shutdown_starts = 0;
  60. void shutdown_start() noexcept override { ++shutdown_starts; }
  61. void continue_shutdown() noexcept { r::actor_base_t::shutdown_start(); }
  62. };
  63. struct fail_initialize_actor : public r::actor_base_t {
  64. using r::actor_base_t::actor_base_t;
  65. void init_start() noexcept override {}
  66. };
  67. struct fail_test_behavior_t : public r::supervisor_behavior_t {
  68. using r::supervisor_behavior_t::supervisor_behavior_t;
  69. void on_shutdown_fail(const r::address_ptr_t &address, const std::error_code &ec) noexcept override;
  70. };
  71. struct fail_shutdown_sup : public rt::supervisor_test_t {
  72. using rt::supervisor_test_t::supervisor_test_t;
  73. r::address_ptr_t fail_addr;
  74. std::error_code fail_reason;
  75. virtual r::actor_behavior_t *create_behavior() noexcept override { return new fail_test_behavior_t(*this); }
  76. };
  77. void fail_test_behavior_t::on_shutdown_fail(const r::address_ptr_t &address, const std::error_code &ec) noexcept {
  78. auto &sup = static_cast<fail_shutdown_sup &>(actor);
  79. sup.fail_addr = address;
  80. sup.fail_reason = ec;
  81. }
  82. TEST_CASE("actor litetimes", "[actor]") {
  83. r::system_context_t system_context;
  84. rt::supervisor_config_test_t config(r::pt::milliseconds{1}, nullptr);
  85. auto sup = system_context.create_supervisor<rt::supervisor_test_t>(nullptr, config);
  86. auto act = sup->create_actor<sample_actor_t>(r::pt::milliseconds{1});
  87. REQUIRE(act->get_state() == r::state_t::INITIALIZING);
  88. sup->do_process();
  89. REQUIRE(act->get_state() == r::state_t::OPERATIONAL);
  90. auto actor_addr = act->get_address();
  91. act->send<r::payload::shutdown_trigger_t>(actor_addr, actor_addr);
  92. sup->do_process();
  93. REQUIRE(act->event_current == 5);
  94. REQUIRE(act->event_shutdown == 4);
  95. REQUIRE(act->event_shutingdown == 3);
  96. REQUIRE(act->event_start == 2);
  97. REQUIRE(act->event_init == 1);
  98. REQUIRE(destroyed == 0);
  99. REQUIRE(act->get_state() == r::state_t::SHUTTED_DOWN);
  100. act.reset();
  101. REQUIRE(destroyed == 1);
  102. /* for asan */
  103. sup->do_shutdown();
  104. sup->do_process();
  105. REQUIRE(sup->get_state() == r::state_t::SHUTTED_DOWN);
  106. REQUIRE(sup->get_leader_queue().size() == 0);
  107. REQUIRE(sup->get_points().size() == 0);
  108. REQUIRE(sup->get_subscription().size() == 0);
  109. }
  110. TEST_CASE("fail shutdown test", "[actor]") {
  111. r::system_context_t system_context;
  112. rt::supervisor_config_test_t config(r::pt::milliseconds{1}, nullptr);
  113. auto sup = system_context.create_supervisor<fail_shutdown_sup>(nullptr, config);
  114. auto act = sup->create_actor<fail_shutdown_actor>(r::pt::milliseconds{1});
  115. sup->do_process();
  116. act->do_shutdown();
  117. sup->do_process();
  118. REQUIRE(sup->active_timers.size() == 1);
  119. sup->on_timer_trigger(*sup->active_timers.begin());
  120. sup->do_process();
  121. REQUIRE(sup->get_children().size() == 1);
  122. REQUIRE(sup->fail_addr == act->get_address());
  123. REQUIRE(sup->fail_reason.value() == static_cast<int>(r::error_code_t::request_timeout));
  124. act->allow_shutdown = true;
  125. act->do_shutdown();
  126. sup->do_process();
  127. REQUIRE(sup->get_children().size() == 0);
  128. sup->do_shutdown();
  129. sup->do_process();
  130. }
  131. TEST_CASE("fail initialize test", "[actor]") {
  132. r::system_context_t system_context;
  133. auto timeout = r::pt::millisec{1};
  134. rt::supervisor_config_test_t config(timeout, nullptr);
  135. auto sup = system_context.create_supervisor<rt::supervisor_test_t>(nullptr, config);
  136. sup->do_process();
  137. auto act = sup->create_actor<fail_initialize_actor>(timeout);
  138. sup->do_process();
  139. REQUIRE(sup->get_children().size() == 1);
  140. REQUIRE(act->get_state() == r::state_t::INITIALIZING);
  141. REQUIRE(sup->active_timers.size() == 1);
  142. sup->on_timer_trigger(*sup->active_timers.begin());
  143. sup->do_process();
  144. REQUIRE(sup->get_children().size() == 0);
  145. sup->do_shutdown();
  146. sup->do_process();
  147. }
  148. TEST_CASE("double shutdown test (actor)", "[actor]") {
  149. r::system_context_t system_context;
  150. rt::supervisor_config_test_t config(r::pt::milliseconds{1}, nullptr);
  151. auto sup = system_context.create_supervisor<fail_shutdown_sup>(nullptr, config);
  152. auto act = sup->create_actor<double_shutdown_actor>(r::pt::milliseconds{1});
  153. sup->do_process();
  154. act->do_shutdown();
  155. act->do_shutdown();
  156. sup->do_process();
  157. REQUIRE(sup->active_timers.size() == 1);
  158. REQUIRE(act->shutdown_starts == 1);
  159. act->continue_shutdown();
  160. sup->do_process();
  161. REQUIRE(sup->get_children().size() == 0);
  162. sup->do_shutdown();
  163. sup->do_process();
  164. }
  165. TEST_CASE("double shutdown test (supervisor)", "[actor]") {
  166. r::system_context_t system_context;
  167. rt::supervisor_config_test_t config(r::pt::milliseconds{1}, nullptr);
  168. auto sup = system_context.create_supervisor<fail_shutdown_sup>(nullptr, config);
  169. auto act = sup->create_actor<double_shutdown_actor>(r::pt::milliseconds{1});
  170. sup->do_process();
  171. sup->do_shutdown();
  172. sup->do_shutdown();
  173. sup->do_process();
  174. REQUIRE(sup->active_timers.size() == 1);
  175. REQUIRE(act->shutdown_starts == 1);
  176. act->continue_shutdown();
  177. sup->do_process();
  178. REQUIRE(sup->get_children().size() == 0);
  179. sup->do_shutdown();
  180. sup->do_process();
  181. }