012-actor-lifetime.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. //
  2. // Copyright (c) 2019-2021 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 "actor_test.h"
  10. #include "access.h"
  11. namespace r = rotor;
  12. namespace rt = r::test;
  13. static std::uint32_t destroyed = 0;
  14. struct sample_actor_t : public r::actor_base_t {
  15. std::uint32_t event_current = 1;
  16. std::uint32_t event_init_start = 0;
  17. std::uint32_t event_init_finish = 0;
  18. std::uint32_t event_start = 0;
  19. std::uint32_t event_shutdown_start = 0;
  20. std::uint32_t event_shutdown_finish = 0;
  21. r::state_t &get_state() noexcept { return state; }
  22. using r::actor_base_t::actor_base_t;
  23. ~sample_actor_t() override { ++destroyed; }
  24. void init_start() noexcept override {
  25. event_init_start = event_current++;
  26. r::actor_base_t::init_start();
  27. }
  28. void init_finish() noexcept override {
  29. event_init_finish = event_current++;
  30. r::actor_base_t::init_finish();
  31. }
  32. void on_start() noexcept override {
  33. event_start = event_current++;
  34. r::actor_base_t::on_start();
  35. }
  36. void shutdown_start() noexcept override {
  37. event_shutdown_start = event_current++;
  38. r::actor_base_t::shutdown_start();
  39. }
  40. void shutdown_finish() noexcept override {
  41. event_shutdown_finish = event_current++;
  42. r::actor_base_t::shutdown_finish();
  43. }
  44. };
  45. struct custom_child_manager_t : public r::plugin::child_manager_plugin_t {
  46. r::address_ptr_t fail_addr;
  47. r::extended_error_ptr_t fail_ec;
  48. void on_shutdown_fail(r::actor_base_t &actor, const r::extended_error_ptr_t &ec) noexcept override {
  49. fail_addr = actor.get_address();
  50. fail_ec = ec;
  51. }
  52. };
  53. struct custom_supervisor_t : rt::supervisor_test_t {
  54. using rt::supervisor_test_t::supervisor_test_t;
  55. using plugins_list_t =
  56. std::tuple<r::plugin::address_maker_plugin_t, r::plugin::locality_plugin_t,
  57. r::plugin::delivery_plugin_t<r::plugin::local_delivery_t>, r::plugin::lifetime_plugin_t,
  58. r::plugin::init_shutdown_plugin_t, r::plugin::foreigners_support_plugin_t, custom_child_manager_t,
  59. r::plugin::starter_plugin_t>;
  60. };
  61. struct fail_plugin_t : public r::plugin::plugin_base_t {
  62. static bool allow_init;
  63. bool allow_shutdown = true;
  64. static const void *class_identity;
  65. const void *identity() const noexcept override { return class_identity; }
  66. void activate(r::actor_base_t *actor_) noexcept override {
  67. reaction_on(reaction_t::INIT);
  68. reaction_on(reaction_t::SHUTDOWN);
  69. return r::plugin::plugin_base_t::activate(actor_);
  70. }
  71. bool handle_init(r::message::init_request_t *) noexcept override { return allow_init; }
  72. bool handle_shutdown(r::message::shutdown_request_t *) noexcept override { return allow_shutdown; }
  73. };
  74. TEST_CASE("actor litetimes", "[actor]") {
  75. r::system_context_t system_context;
  76. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  77. auto act = sup->create_actor<sample_actor_t>().timeout(rt::default_timeout).finish();
  78. REQUIRE(act->get_state() == r::state_t::INITIALIZING);
  79. sup->do_process();
  80. REQUIRE(act->get_state() == r::state_t::OPERATIONAL);
  81. act->do_shutdown();
  82. sup->do_process();
  83. CHECK(act->event_current == 6);
  84. CHECK(act->event_shutdown_finish == 5);
  85. CHECK(act->event_shutdown_start == 4);
  86. CHECK(act->event_start == 3);
  87. CHECK(act->event_init_finish == 2);
  88. CHECK(act->event_init_start == 1);
  89. REQUIRE(destroyed == 0);
  90. REQUIRE(act->get_state() == r::state_t::SHUT_DOWN);
  91. act.reset();
  92. REQUIRE(destroyed == 1);
  93. /* for asan */
  94. sup->do_shutdown();
  95. sup->do_process();
  96. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  97. REQUIRE(sup->get_leader_queue().size() == 0);
  98. REQUIRE(sup->get_points().size() == 0);
  99. CHECK(rt::empty(sup->get_subscription()));
  100. }
  101. TEST_CASE("fail shutdown test", "[actor]") {
  102. r::system_context_t system_context;
  103. auto sup = system_context.create_supervisor<custom_supervisor_t>().timeout(rt::default_timeout).finish();
  104. auto act = sup->create_actor<rt::actor_test_t>().timeout(rt::default_timeout).finish();
  105. sup->do_process();
  106. REQUIRE(sup->get_state() == r::state_t::OPERATIONAL);
  107. REQUIRE(sup->active_timers.size() == 0);
  108. act->access<rt::to::resources>()->acquire();
  109. act->do_shutdown();
  110. sup->do_process();
  111. REQUIRE(sup->active_timers.size() == 1); // "init child + shutdown children"
  112. auto timer_it = *sup->active_timers.begin();
  113. sup->do_invoke_timer(timer_it->request_id);
  114. sup->do_process();
  115. REQUIRE(sup->get_children_count() == 1);
  116. CHECK(act->get_state() == r::state_t::SHUTTING_DOWN);
  117. auto plugin =
  118. static_cast<r::actor_base_t &>(*sup).access<rt::to::get_plugin>(custom_child_manager_t::class_identity);
  119. auto cm_plugin = static_cast<custom_child_manager_t *>(plugin);
  120. REQUIRE(cm_plugin->fail_addr == act->get_address());
  121. auto &ec = cm_plugin->fail_ec;
  122. REQUIRE(ec);
  123. CHECK(ec->ec.value() == static_cast<int>(r::error_code_t::request_timeout));
  124. REQUIRE(!ec->next);
  125. act->access<rt::to::resources>()->release();
  126. act->shutdown_continue();
  127. sup->do_shutdown();
  128. sup->do_process();
  129. REQUIRE(sup->get_children_count() == 0);
  130. CHECK(act->get_state() == r::state_t::SHUT_DOWN);
  131. CHECK(sup->get_state() == r::state_t::SHUT_DOWN);
  132. CHECK(sup->get_leader_queue().size() == 0);
  133. CHECK(sup->get_points().size() == 0);
  134. CHECK(rt::empty(sup->get_subscription()));
  135. }
  136. TEST_CASE("fail initialize test", "[actor]") {
  137. r::system_context_t system_context;
  138. auto sup = system_context.create_supervisor<custom_supervisor_t>().timeout(rt::default_timeout).finish();
  139. sup->do_process();
  140. auto act = sup->create_actor<rt::actor_test_t>().timeout(rt::default_timeout).finish();
  141. act->access<rt::to::resources>()->acquire();
  142. CHECK(act->access<rt::to::resources>()->has() == 1);
  143. sup->do_process();
  144. REQUIRE(sup->get_children_count() == 2); // sup + actor
  145. REQUIRE(act->get_state() == r::state_t::INITIALIZING);
  146. REQUIRE(sup->active_timers.size() == 1);
  147. auto timer_it = *sup->active_timers.begin();
  148. sup->do_invoke_timer(timer_it->request_id);
  149. act->access<rt::to::resources>()->release();
  150. sup->do_process();
  151. REQUIRE(sup->get_children_count() == 1); // just sup
  152. sup->do_shutdown();
  153. sup->do_process();
  154. CHECK(act->get_state() == r::state_t::SHUT_DOWN);
  155. CHECK(sup->get_state() == r::state_t::SHUT_DOWN);
  156. }
  157. TEST_CASE("double shutdown test (actor)", "[actor]") {
  158. r::system_context_t system_context;
  159. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  160. auto act = sup->create_actor<sample_actor_t>().timeout(rt::default_timeout).finish();
  161. sup->do_process();
  162. act->do_shutdown();
  163. act->do_shutdown();
  164. sup->do_process();
  165. CHECK(act->event_current == 6);
  166. CHECK(act->event_shutdown_finish == 5);
  167. CHECK(act->event_shutdown_start == 4);
  168. REQUIRE(sup->get_children_count() == 1); // just sup
  169. sup->do_shutdown();
  170. sup->do_process();
  171. }
  172. TEST_CASE("double shutdown test (supervisor)", "[actor]") {
  173. r::system_context_t system_context;
  174. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  175. /* auto act = */ sup->create_actor<sample_actor_t>().timeout(rt::default_timeout).finish();
  176. sup->do_process();
  177. sup->do_shutdown();
  178. sup->do_shutdown();
  179. sup->do_process();
  180. REQUIRE(sup->get_children_count() == 0);
  181. REQUIRE(sup->active_timers.size() == 0);
  182. }