023-supervisor-children.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. //
  2. // Copyright (c) 2019-2023 Ivan Baidakou (basiliscos) (the dot dmol at gmail dot com)
  3. //
  4. // Distributed under the MIT Software License
  5. //
  6. #include "rotor.hpp"
  7. #include "actor_test.h"
  8. #include "supervisor_test.h"
  9. #include "system_context_test.h"
  10. #include "access.h"
  11. namespace r = rotor;
  12. namespace rt = r::test;
  13. namespace payload {
  14. struct trigger_t {};
  15. } // namespace payload
  16. namespace message {
  17. using trigger_t = r::message_t<payload::trigger_t>;
  18. }
  19. namespace {
  20. namespace to {
  21. struct init_request {};
  22. struct shutdown_request {};
  23. } // namespace to
  24. } // namespace
  25. template <> auto &r::actor_base_t::access<to::init_request>() noexcept { return init_request; }
  26. template <> auto &r::actor_base_t::access<to::shutdown_request>() noexcept { return shutdown_request; }
  27. struct sample_actor_t : public rt::actor_test_t {
  28. using rt::actor_test_t::actor_test_t;
  29. virtual void init_finish() noexcept override {}
  30. void confirm_init() noexcept { r::actor_base_t::init_finish(); }
  31. };
  32. struct fail_init_actor_t : public rt::actor_test_t {
  33. using rt::actor_test_t::actor_test_t;
  34. void init_finish() noexcept override { supervisor->do_shutdown(); }
  35. };
  36. struct fail_start_actor_t : public rt::actor_test_t {
  37. using rt::actor_test_t::actor_test_t;
  38. void on_start() noexcept override {
  39. rt::actor_test_t::on_start();
  40. do_shutdown();
  41. }
  42. };
  43. struct fail_start_actor2_t : public rt::actor_test_t {
  44. using rt::actor_test_t::actor_test_t;
  45. void on_start() noexcept override {
  46. rt::actor_test_t::on_start();
  47. supervisor->do_shutdown();
  48. }
  49. };
  50. struct fail_start_actor3_t : public rt::actor_test_t {
  51. using rt::actor_test_t::actor_test_t;
  52. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  53. r::actor_base_t::configure(plugin);
  54. plugin.with_casted<r::plugin::starter_plugin_t>(
  55. [&](auto &p) { p.subscribe_actor(&fail_start_actor3_t::on_trigger); });
  56. }
  57. void on_start() noexcept override {
  58. rt::actor_test_t::on_start();
  59. send<payload::trigger_t>(address);
  60. }
  61. void on_trigger(message::trigger_t &) noexcept { supervisor->do_shutdown(); }
  62. };
  63. struct custom_init_plugin2_t;
  64. struct fail_init_actor3_t : public rt::actor_test_t {
  65. using rt::actor_test_t::actor_test_t;
  66. void init_start() noexcept override {
  67. rt::actor_test_t::init_start();
  68. do_shutdown();
  69. }
  70. };
  71. struct fail_init_actor4_t : public rt::actor_test_t {
  72. using rt::actor_test_t::actor_test_t;
  73. void init_start() noexcept override {
  74. do_shutdown();
  75. rt::actor_test_t::init_start();
  76. }
  77. };
  78. struct fail_init_actor5_t : public rt::actor_test_t {
  79. using rt::actor_test_t::actor_test_t;
  80. void init_start() noexcept override {
  81. supervisor->do_shutdown();
  82. rt::actor_test_t::init_start();
  83. }
  84. };
  85. struct fail_init_actor6_t : public rt::actor_test_t {
  86. using rt::actor_test_t::actor_test_t;
  87. using plugins_list_t =
  88. std::tuple<r::plugin::address_maker_plugin_t, r::plugin::lifetime_plugin_t, r::plugin::init_shutdown_plugin_t,
  89. custom_init_plugin2_t, r::plugin::starter_plugin_t>;
  90. };
  91. struct custom_init_plugin2_t : r::plugin::plugin_base_t {
  92. static std::type_index class_id;
  93. const std::type_index &identity() const noexcept override { return class_id; }
  94. void activate(r::actor_base_t *actor_) noexcept override {
  95. r::plugin::plugin_base_t::activate(actor_);
  96. reaction_on(reaction_t::INIT);
  97. }
  98. bool handle_init(r::message::init_request_t *message) noexcept override {
  99. auto ec = r::make_error_code(r::error_code_t::actor_misconfigured);
  100. actor->reply_with_error(*message, make_error(ec));
  101. actor->access<to::init_request>().reset();
  102. return false;
  103. }
  104. };
  105. std::type_index custom_init_plugin2_t::class_id = typeid(custom_init_plugin2_t);
  106. struct custom_shutdown_plugin_t : r::plugin::plugin_base_t {
  107. static std::type_index class_id;
  108. const std::type_index &identity() const noexcept override { return class_id; }
  109. void activate(r::actor_base_t *actor_) noexcept override {
  110. r::plugin::plugin_base_t::activate(actor_);
  111. reaction_on(reaction_t::SHUTDOWN);
  112. }
  113. bool handle_shutdown(r::message::shutdown_request_t *message) noexcept override {
  114. auto ec = r::make_error_code(r::error_code_t::actor_misconfigured);
  115. actor->reply_with_error(*message, make_error(ec));
  116. actor->access<to::shutdown_request>().reset();
  117. return false;
  118. }
  119. };
  120. std::type_index custom_shutdown_plugin_t::class_id = typeid(custom_shutdown_plugin_t);
  121. struct sample_supervisor_t : public rt::supervisor_test_t {
  122. using rt::supervisor_test_t::supervisor_test_t;
  123. using child_ptr_t = r::intrusive_ptr_t<sample_actor_t>;
  124. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  125. plugin.with_casted<r::plugin::child_manager_plugin_t>(
  126. [this](auto &) { child = create_actor<sample_actor_t>().timeout(rt::default_timeout).finish(); });
  127. }
  128. child_ptr_t child;
  129. };
  130. struct post_shutdown_actor_t : public rt::actor_test_t {
  131. using rt::actor_test_t::actor_test_t;
  132. void shutdown_start() noexcept override {
  133. rt::actor_test_t::shutdown_start();
  134. do_shutdown();
  135. }
  136. };
  137. struct pre_shutdown_actor_t : public rt::actor_test_t {
  138. using rt::actor_test_t::actor_test_t;
  139. void shutdown_start() noexcept override {
  140. do_shutdown();
  141. rt::actor_test_t::shutdown_start();
  142. }
  143. };
  144. struct managed_supervisor_t : public rt::supervisor_test_t {
  145. using parent_t = rt::supervisor_test_t;
  146. using actor_t = rt::actor_test_t;
  147. using child_ptr_t = r::intrusive_ptr_t<actor_t>;
  148. using parent_t::parent_t;
  149. child_ptr_t child;
  150. void do_initialize(r::system_context_t *ctx) noexcept override {
  151. parent_t::do_initialize(ctx);
  152. child = create_actor<actor_t>().timeout(rt::default_timeout).finish();
  153. }
  154. };
  155. struct fail_shutdown_actor1_t : rt::actor_test_t {
  156. using rt::actor_test_t::actor_test_t;
  157. void shutdown_finish() noexcept override {}
  158. };
  159. struct fail_shutdown_actor2_t : rt::actor_test_t {
  160. using rt::actor_test_t::actor_test_t;
  161. using plugins_list_t =
  162. std::tuple<r::plugin::address_maker_plugin_t, r::plugin::lifetime_plugin_t, r::plugin::init_shutdown_plugin_t,
  163. custom_shutdown_plugin_t, r::plugin::starter_plugin_t>;
  164. };
  165. struct unsubscriber_actor_t : rt::actor_test_t {
  166. using rt::actor_test_t::actor_test_t;
  167. r::address_ptr_t some_addr;
  168. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  169. rt::actor_test_t::configure(plugin);
  170. plugin.with_casted<rotor::plugin::starter_plugin_t>(
  171. [this](auto &p) { p.subscribe_actor(&unsubscriber_actor_t::on_message, some_addr); });
  172. }
  173. void on_message(message::trigger_t &) noexcept {}
  174. void shutdown_start() noexcept override {
  175. rt::actor_test_t::shutdown_start();
  176. // send<payload::trigger_t>(some_addr);
  177. }
  178. };
  179. TEST_CASE("supervisor is not initialized, while it child did not confirmed initialization", "[supervisor]") {
  180. r::system_context_t system_context;
  181. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  182. auto act = sup->create_actor<sample_actor_t>().timeout(rt::default_timeout).finish();
  183. sup->do_process();
  184. REQUIRE(sup->get_state() == r::state_t::INITIALIZING);
  185. REQUIRE(act->get_state() == r::state_t::INITIALIZING);
  186. act->confirm_init();
  187. sup->do_process();
  188. REQUIRE(sup->get_state() == r::state_t::OPERATIONAL);
  189. REQUIRE(act->get_state() == r::state_t::OPERATIONAL);
  190. sup->do_shutdown();
  191. sup->do_process();
  192. }
  193. TEST_CASE("supervisor is not initialized, while it 1 of 2 children did not confirmed initialization", "[supervisor]") {
  194. r::system_context_t system_context;
  195. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  196. auto act1 = sup->create_actor<sample_actor_t>().timeout(rt::default_timeout).finish();
  197. auto act2 = sup->create_actor<sample_actor_t>().timeout(rt::default_timeout).finish();
  198. sup->do_process();
  199. REQUIRE(sup->get_state() == r::state_t::INITIALIZING);
  200. REQUIRE(act1->get_state() == r::state_t::INITIALIZING);
  201. REQUIRE(act2->get_state() == r::state_t::INITIALIZING);
  202. act1->confirm_init();
  203. sup->do_process();
  204. REQUIRE(sup->get_state() == r::state_t::INITIALIZING);
  205. REQUIRE(act1->get_state() == r::state_t::OPERATIONAL);
  206. REQUIRE(act2->get_state() == r::state_t::INITIALIZING);
  207. sup->do_shutdown();
  208. sup->do_process();
  209. }
  210. TEST_CASE("supervisor does not starts, if a children did not initialized", "[supervisor]") {
  211. r::system_context_t system_context;
  212. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  213. auto act1 = sup->create_actor<sample_actor_t>().timeout(rt::default_timeout).finish();
  214. auto act2 = sup->create_actor<sample_actor_t>().timeout(rt::default_timeout).finish();
  215. sup->do_process();
  216. REQUIRE(sup->get_state() == r::state_t::INITIALIZING);
  217. REQUIRE(act1->get_state() == r::state_t::INITIALIZING);
  218. REQUIRE(act2->get_state() == r::state_t::INITIALIZING);
  219. act1->confirm_init();
  220. sup->do_process();
  221. REQUIRE(act1->get_state() == r::state_t::OPERATIONAL);
  222. REQUIRE(sup->active_timers.size() == 2);
  223. auto act2_init_req = sup->get_timer(1);
  224. sup->do_invoke_timer(act2_init_req);
  225. sup->do_process();
  226. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  227. REQUIRE(act1->get_state() == r::state_t::SHUT_DOWN);
  228. REQUIRE(act2->get_state() == r::state_t::SHUT_DOWN);
  229. }
  230. TEST_CASE("supervisor create child during init phase", "[supervisor]") {
  231. r::system_context_t system_context;
  232. auto sup = system_context.create_supervisor<sample_supervisor_t>().timeout(rt::default_timeout).finish();
  233. auto &act = sup->child;
  234. sup->do_process();
  235. REQUIRE(sup->get_state() == r::state_t::INITIALIZING);
  236. REQUIRE(act->get_state() == r::state_t::INITIALIZING);
  237. act->confirm_init();
  238. sup->do_process();
  239. REQUIRE(sup->get_state() == r::state_t::OPERATIONAL);
  240. REQUIRE(act->get_state() == r::state_t::OPERATIONAL);
  241. sup->do_shutdown();
  242. sup->do_process();
  243. }
  244. TEST_CASE("shutdown_failed policy", "[supervisor]") {
  245. r::system_context_t system_context;
  246. auto sup = system_context.create_supervisor<rt::supervisor_test_t>()
  247. .policy(r::supervisor_policy_t::shutdown_failed)
  248. .timeout(rt::default_timeout)
  249. .finish();
  250. auto act = sup->create_actor<sample_actor_t>().timeout(rt::default_timeout).finish();
  251. sup->do_process();
  252. REQUIRE(sup->get_state() == r::state_t::INITIALIZING);
  253. REQUIRE(act->get_state() == r::state_t::INITIALIZING);
  254. auto act_init_req = sup->get_timer(1);
  255. sup->do_invoke_timer(act_init_req);
  256. sup->do_process();
  257. sup->do_process();
  258. REQUIRE(act->get_state() == r::state_t::SHUT_DOWN);
  259. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  260. auto &sup_reason = sup->get_shutdown_reason();
  261. CHECK(sup_reason->ec == r::shutdown_code_t::child_down);
  262. CHECK(sup_reason->ec.message() == "supervisor shutdown due to child shutdown policy");
  263. auto &act_reason = act->get_shutdown_reason();
  264. REQUIRE(act_reason->next->ec == r::shutdown_code_t::init_failed);
  265. REQUIRE(act_reason->next->ec.message() == "actor shutdown due to init failure");
  266. }
  267. TEST_CASE("shutdown_self policy", "[supervisor]") {
  268. r::system_context_t system_context;
  269. auto sup = system_context.create_supervisor<rt::supervisor_test_t>()
  270. .policy(r::supervisor_policy_t::shutdown_self)
  271. .timeout(rt::default_timeout)
  272. .finish();
  273. auto act = sup->create_actor<sample_actor_t>().timeout(rt::default_timeout).finish();
  274. sup->do_process();
  275. REQUIRE(sup->get_state() == r::state_t::INITIALIZING);
  276. REQUIRE(act->get_state() == r::state_t::INITIALIZING);
  277. auto act_init_req = sup->get_timer(1);
  278. sup->do_invoke_timer(act_init_req);
  279. sup->do_process();
  280. sup->do_process();
  281. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  282. REQUIRE(act->get_state() == r::state_t::SHUT_DOWN);
  283. }
  284. TEST_CASE("actor shuts self down during start => supervisor is not affected", "[supervisor]") {
  285. r::system_context_t system_context;
  286. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  287. auto act = sup->create_actor<fail_start_actor_t>().timeout(rt::default_timeout).finish();
  288. sup->do_process();
  289. REQUIRE(act->get_state() == r::state_t::SHUT_DOWN);
  290. REQUIRE(sup->get_state() == r::state_t::OPERATIONAL);
  291. sup->do_shutdown();
  292. sup->do_process();
  293. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  294. }
  295. TEST_CASE("actor shuts supervisor down during start") {
  296. r::system_context_t system_context;
  297. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  298. auto act = sup->create_actor<fail_start_actor2_t>().timeout(rt::default_timeout).finish();
  299. sup->do_process();
  300. REQUIRE(act->get_state() == r::state_t::SHUT_DOWN);
  301. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  302. }
  303. TEST_CASE("actor shuts supervisor down during start(2)") {
  304. r::system_context_t system_context;
  305. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  306. auto act = sup->create_actor<fail_start_actor3_t>().timeout(rt::default_timeout).finish();
  307. sup->do_process();
  308. REQUIRE(act->get_state() == r::state_t::SHUT_DOWN);
  309. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  310. }
  311. TEST_CASE("actor shutdown on init_finish()", "[supervisor]") {
  312. r::system_context_t system_context;
  313. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  314. auto act = sup->create_actor<fail_init_actor_t>().timeout(rt::default_timeout).finish();
  315. sup->do_process();
  316. REQUIRE(act->get_state() == r::state_t::SHUT_DOWN);
  317. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  318. }
  319. TEST_CASE("actor shutdown on init_start(), post", "[supervisor]") {
  320. r::system_context_t system_context;
  321. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  322. auto act = sup->create_actor<fail_init_actor3_t>().timeout(rt::default_timeout).finish();
  323. sup->do_process();
  324. CHECK(act->get_state() == r::state_t::SHUT_DOWN);
  325. CHECK(sup->get_state() == r::state_t::SHUT_DOWN);
  326. }
  327. TEST_CASE("actor shutdown on init_start(), pre", "[supervisor]") {
  328. r::system_context_t system_context;
  329. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  330. auto act = sup->create_actor<fail_init_actor4_t>().timeout(rt::default_timeout).finish();
  331. sup->do_process();
  332. CHECK(act->get_state() == r::state_t::SHUT_DOWN);
  333. CHECK(sup->get_state() == r::state_t::SHUT_DOWN);
  334. }
  335. TEST_CASE("actor sends shutdown to sup during init_start()", "[supervisor]") {
  336. r::system_context_t system_context;
  337. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  338. auto act = sup->create_actor<fail_init_actor5_t>().timeout(rt::default_timeout).finish();
  339. sup->do_process();
  340. CHECK(act->get_state() == r::state_t::SHUT_DOWN);
  341. CHECK(sup->get_state() == r::state_t::SHUT_DOWN);
  342. }
  343. TEST_CASE("actor replies with error to init", "[supervisor]") {
  344. r::system_context_t system_context;
  345. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  346. auto act = sup->create_actor<fail_init_actor6_t>().timeout(rt::default_timeout).finish();
  347. sup->do_process();
  348. CHECK(act->get_state() == r::state_t::SHUT_DOWN);
  349. CHECK(sup->get_state() == r::state_t::SHUT_DOWN);
  350. }
  351. TEST_CASE("actor shutdown during init", "[supervisor]") {
  352. r::system_context_t system_context;
  353. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  354. auto act = sup->create_actor<rt::actor_test_t>().timeout(rt::default_timeout).finish();
  355. act->configurer = [&](auto &, r::plugin::plugin_base_t &plugin) {
  356. plugin.with_casted<r::plugin::resources_plugin_t>([&](auto &p) { p.acquire(); });
  357. };
  358. sup->do_process();
  359. REQUIRE(act->get_state() == r::state_t::INITIALIZING);
  360. REQUIRE(sup->get_state() == r::state_t::INITIALIZING);
  361. act->do_shutdown();
  362. act->access<rt::to::resources>()->access<rt::to::resources>().clear();
  363. sup->do_process();
  364. REQUIRE(act->get_state() == r::state_t::SHUT_DOWN);
  365. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  366. }
  367. TEST_CASE("two actors shutdown during init", "[supervisor]") {
  368. r::system_context_t system_context;
  369. auto configurer = [&](auto &, r::plugin::plugin_base_t &plugin) {
  370. plugin.with_casted<r::plugin::resources_plugin_t>([&](auto &p) { p.acquire(); });
  371. };
  372. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  373. auto act1 = sup->create_actor<rt::actor_test_t>().timeout(rt::default_timeout).finish();
  374. auto act2 = sup->create_actor<rt::actor_test_t>().timeout(rt::default_timeout).finish();
  375. act1->configurer = configurer;
  376. act2->configurer = configurer;
  377. sup->do_process();
  378. REQUIRE(act1->get_state() == r::state_t::INITIALIZING);
  379. REQUIRE(act2->get_state() == r::state_t::INITIALIZING);
  380. REQUIRE(sup->get_state() == r::state_t::INITIALIZING);
  381. act1->do_shutdown();
  382. act2->do_shutdown();
  383. act1->access<rt::to::resources>()->access<rt::to::resources>().clear();
  384. act2->access<rt::to::resources>()->access<rt::to::resources>().clear();
  385. sup->do_process();
  386. REQUIRE(act1->get_state() == r::state_t::SHUT_DOWN);
  387. REQUIRE(act2->get_state() == r::state_t::SHUT_DOWN);
  388. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  389. }
  390. TEST_CASE("double shutdown attempt (post)", "[supervisor]") {
  391. rt::system_context_test_t system_context;
  392. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  393. auto act = sup->create_actor<post_shutdown_actor_t>().timeout(rt::default_timeout).finish();
  394. sup->do_process();
  395. CHECK(act->get_state() == r::state_t::OPERATIONAL);
  396. CHECK(sup->get_state() == r::state_t::OPERATIONAL);
  397. sup->do_shutdown();
  398. sup->do_process();
  399. CHECK(act->get_state() == r::state_t::SHUT_DOWN);
  400. CHECK(sup->get_state() == r::state_t::SHUT_DOWN);
  401. }
  402. TEST_CASE("double shutdown attempt (pre)", "[supervisor]") {
  403. rt::system_context_test_t system_context;
  404. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  405. auto act = sup->create_actor<pre_shutdown_actor_t>().timeout(rt::default_timeout).finish();
  406. sup->do_process();
  407. CHECK(act->get_state() == r::state_t::OPERATIONAL);
  408. CHECK(sup->get_state() == r::state_t::OPERATIONAL);
  409. sup->do_shutdown();
  410. sup->do_process();
  411. CHECK(act->get_state() == r::state_t::SHUT_DOWN);
  412. CHECK(sup->get_state() == r::state_t::SHUT_DOWN);
  413. }
  414. TEST_CASE("managed supervisor (autostart child)", "[supervisor]") {
  415. rt::system_context_test_t system_context;
  416. auto sup = system_context.create_supervisor<managed_supervisor_t>().timeout(rt::default_timeout).finish();
  417. auto act = sup->child;
  418. sup->do_process();
  419. CHECK(act->get_state() == r::state_t::OPERATIONAL);
  420. CHECK(sup->get_state() == r::state_t::OPERATIONAL);
  421. sup->do_shutdown();
  422. sup->do_process();
  423. CHECK(act->get_state() == r::state_t::SHUT_DOWN);
  424. CHECK(sup->get_state() == r::state_t::SHUT_DOWN);
  425. }
  426. TEST_CASE("failed to shutdown actor (1)", "[supervisor]") {
  427. rt::system_context_test_t system_context;
  428. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  429. auto act = sup->create_actor<fail_shutdown_actor1_t>().timeout(rt::default_timeout).finish();
  430. sup->do_process();
  431. CHECK(act->get_state() == r::state_t::OPERATIONAL);
  432. CHECK(sup->get_state() == r::state_t::OPERATIONAL);
  433. sup->do_shutdown();
  434. sup->do_process();
  435. CHECK(sup->active_timers.size() == 1);
  436. auto timer_it = *sup->active_timers.begin();
  437. sup->do_invoke_timer(timer_it->request_id);
  438. sup->do_process();
  439. REQUIRE(system_context.reason->ec == r::error_code_t::request_timeout);
  440. CHECK(act->get_state() == r::state_t::SHUTTING_DOWN);
  441. CHECK(sup->get_state() == r::state_t::SHUT_DOWN);
  442. }
  443. TEST_CASE("failed to shutdown actor (2)", "[supervisor]") {
  444. rt::system_context_test_t system_context;
  445. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  446. auto act = sup->create_actor<fail_shutdown_actor2_t>().timeout(rt::default_timeout).finish();
  447. sup->do_process();
  448. CHECK(act->get_state() == r::state_t::OPERATIONAL);
  449. CHECK(sup->get_state() == r::state_t::OPERATIONAL);
  450. sup->do_shutdown();
  451. sup->do_process();
  452. REQUIRE(system_context.reason->ec == r::error_code_t::actor_misconfigured);
  453. act->force_cleanup();
  454. CHECK(act->get_state() == r::state_t::SHUTTING_DOWN);
  455. CHECK(sup->get_state() == r::state_t::SHUT_DOWN);
  456. }
  457. TEST_CASE("failed to shutdown actor (3)", "[supervisor]") {
  458. rt::system_context_test_t system_context;
  459. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  460. auto act = sup->create_actor<rt::actor_test_t>().timeout(rt::default_timeout).finish();
  461. sup->do_process();
  462. CHECK(act->get_state() == r::state_t::OPERATIONAL);
  463. CHECK(sup->get_state() == r::state_t::OPERATIONAL);
  464. act->access<rt::to::resources>()->acquire();
  465. sup->do_shutdown();
  466. sup->do_process();
  467. CHECK(sup->active_timers.size() == 1);
  468. auto timer_it = *sup->active_timers.begin();
  469. sup->do_invoke_timer(timer_it->request_id);
  470. sup->do_process();
  471. REQUIRE(system_context.reason->ec == r::error_code_t::request_timeout);
  472. act->force_cleanup();
  473. CHECK(act->get_state() == r::state_t::SHUTTING_DOWN);
  474. CHECK(sup->get_state() == r::state_t::SHUT_DOWN);
  475. }
  476. TEST_CASE("synchronized start", "[supervisor]") {
  477. rt::system_context_test_t system_context;
  478. auto sup = system_context.create_supervisor<rt::supervisor_test_t>()
  479. .synchronize_start()
  480. .timeout(rt::default_timeout)
  481. .finish();
  482. auto act1 = sup->create_actor<rt::actor_test_t>().timeout(rt::default_timeout).finish();
  483. auto act2 = sup->create_actor<rt::actor_test_t>().timeout(rt::default_timeout).finish();
  484. act1->access<rt::to::resources>()->acquire();
  485. sup->do_process();
  486. CHECK(act1->get_state() == r::state_t::INITIALIZING);
  487. CHECK(act2->get_state() == r::state_t::INITIALIZED);
  488. CHECK(sup->get_state() == r::state_t::INITIALIZING);
  489. act1->access<rt::to::resources>()->release();
  490. sup->do_process();
  491. CHECK(act1->get_state() == r::state_t::OPERATIONAL);
  492. CHECK(act2->get_state() == r::state_t::OPERATIONAL);
  493. CHECK(sup->get_state() == r::state_t::OPERATIONAL);
  494. sup->do_shutdown();
  495. sup->do_process();
  496. }
  497. TEST_CASE("1 child is initializing, and another one started, and then shutted down", "[supervisor]") {
  498. rt::system_context_test_t system_context;
  499. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  500. auto act1 = sup->create_actor<rt::actor_test_t>().timeout(rt::default_timeout).finish();
  501. auto act2 = sup->create_actor<rt::actor_test_t>().timeout(rt::default_timeout).finish();
  502. act1->access<rt::to::resources>()->acquire();
  503. sup->do_process();
  504. CHECK(act1->get_state() == r::state_t::INITIALIZING);
  505. CHECK(act2->get_state() == r::state_t::OPERATIONAL);
  506. CHECK(sup->get_state() == r::state_t::INITIALIZING);
  507. act2->do_shutdown();
  508. sup->do_process();
  509. CHECK(act1->get_state() == r::state_t::INITIALIZING);
  510. CHECK(act2->get_state() == r::state_t::SHUT_DOWN);
  511. CHECK(sup->get_state() == r::state_t::INITIALIZING);
  512. act1->access<rt::to::resources>()->release();
  513. sup->do_process();
  514. CHECK(act1->get_state() == r::state_t::OPERATIONAL);
  515. CHECK(sup->get_state() == r::state_t::OPERATIONAL);
  516. sup->do_shutdown();
  517. sup->do_process();
  518. }
  519. TEST_CASE("race during external unsubscription", "[supervisor]") {
  520. rt::system_context_test_t system_context;
  521. auto sup1 = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  522. auto sup2 = sup1->create_actor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  523. sup1->do_process();
  524. auto addr = sup2->create_address();
  525. auto act = sup1->create_actor<unsubscriber_actor_t>().timeout(rt::default_timeout).finish();
  526. act->some_addr = addr;
  527. sup1->do_process();
  528. CHECK(act->get_state() == r::state_t::OPERATIONAL);
  529. sup1->do_shutdown();
  530. sup1->do_process();
  531. CHECK(act->get_state() == r::state_t::SHUT_DOWN);
  532. sup1->do_shutdown();
  533. sup1->do_process();
  534. }
  535. TEST_CASE("race during external unsubscription (2)", "[supervisor]") {
  536. rt::system_context_test_t system_context;
  537. auto sup1 = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  538. auto sup2 = sup1->create_actor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  539. sup1->do_process();
  540. auto addr = sup2->create_address();
  541. auto act = sup1->create_actor<unsubscriber_actor_t>().timeout(rt::default_timeout).finish();
  542. act->some_addr = addr;
  543. sup1->do_process();
  544. CHECK(act->get_state() == r::state_t::OPERATIONAL);
  545. act->do_shutdown();
  546. sup1->do_process();
  547. CHECK(act->get_state() == r::state_t::SHUT_DOWN);
  548. sup1->do_shutdown();
  549. sup1->do_process();
  550. }