023-supervisor-children.cpp 26 KB

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