023-supervisor-children.cpp 22 KB

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