017-req-res.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  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 "supervisor_test.h"
  9. #include "access.h"
  10. namespace r = rotor;
  11. namespace rt = r::test;
  12. struct response_sample_t {
  13. int value;
  14. };
  15. struct request_sample_t {
  16. using response_t = response_sample_t;
  17. int value;
  18. };
  19. struct res2_t : r::arc_base_t<res2_t> {
  20. int value;
  21. explicit res2_t(int value_) : value{value_} {}
  22. virtual ~res2_t() {}
  23. };
  24. struct req2_t {
  25. using response_t = r::intrusive_ptr_t<res2_t>;
  26. int value;
  27. };
  28. struct res3_t : r::arc_base_t<res3_t> {
  29. int value;
  30. explicit res3_t(int value_) : value{value_} {}
  31. res3_t(const res3_t &) = delete;
  32. res3_t(res3_t &&) = delete;
  33. virtual ~res3_t() {}
  34. };
  35. struct req3_t : r::arc_base_t<req3_t> {
  36. using response_t = r::intrusive_ptr_t<res3_t>;
  37. int value;
  38. explicit req3_t(int value_) : value{value_} {}
  39. req3_t(const req3_t &) = delete;
  40. req3_t(req3_t &&) = delete;
  41. virtual ~req3_t() {}
  42. };
  43. static_assert(std::is_base_of_v<r::arc_base_t<req3_t>, req3_t>, "zzz");
  44. using traits_t = r::request_traits_t<request_sample_t>;
  45. struct good_actor_t : public r::actor_base_t {
  46. using r::actor_base_t::actor_base_t;
  47. int req_val = 0;
  48. int res_val = 0;
  49. std::error_code ec;
  50. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  51. plugin.with_casted<r::plugin::starter_plugin_t>([](auto &p) {
  52. p.subscribe_actor(&good_actor_t::on_request);
  53. p.subscribe_actor(&good_actor_t::on_response);
  54. });
  55. }
  56. void on_start() noexcept override {
  57. r::actor_base_t::on_start();
  58. request<request_sample_t>(address, 4).send(r::pt::seconds(1));
  59. }
  60. void on_request(traits_t::request::message_t &msg) noexcept { reply_to(msg, 5); }
  61. void on_response(traits_t::response::message_t &msg) noexcept {
  62. req_val += msg.payload.req->payload.request_payload.value;
  63. res_val += msg.payload.res.value;
  64. ec = msg.payload.ec;
  65. }
  66. };
  67. struct bad_actor_t : public r::actor_base_t {
  68. using r::actor_base_t::actor_base_t;
  69. int req_val = 0;
  70. int res_val = 0;
  71. std::error_code ec;
  72. r::intrusive_ptr_t<traits_t::request::message_t> req_msg;
  73. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  74. plugin.with_casted<r::plugin::starter_plugin_t>([](auto &p) {
  75. p.subscribe_actor(&bad_actor_t::on_request);
  76. p.subscribe_actor(&bad_actor_t::on_response);
  77. });
  78. }
  79. void shutdown_start() noexcept override {
  80. req_msg.reset();
  81. r::actor_base_t::shutdown_start();
  82. }
  83. void on_start() noexcept override {
  84. r::actor_base_t::on_start();
  85. request<request_sample_t>(address, 4).send(rt::default_timeout);
  86. }
  87. void on_request(traits_t::request::message_t &msg) noexcept { req_msg.reset(&msg); }
  88. void on_response(traits_t::response::message_t &msg) noexcept {
  89. req_val += msg.payload.req->payload.request_payload.value;
  90. ec = msg.payload.ec;
  91. if (!ec) {
  92. res_val += 9;
  93. }
  94. }
  95. };
  96. struct bad_actor2_t : public r::actor_base_t {
  97. using r::actor_base_t::actor_base_t;
  98. int req_val = 0;
  99. int res_val = 0;
  100. std::error_code ec;
  101. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  102. plugin.with_casted<r::plugin::starter_plugin_t>([](auto &p) {
  103. p.subscribe_actor(&bad_actor2_t::on_request);
  104. p.subscribe_actor(&bad_actor2_t::on_response);
  105. });
  106. }
  107. void on_start() noexcept override {
  108. r::actor_base_t::on_start();
  109. request<request_sample_t>(address, 4).send(rt::default_timeout);
  110. }
  111. void on_request(traits_t::request::message_t &msg) noexcept {
  112. reply_with_error(msg, r::make_error_code(r::error_code_t::request_timeout));
  113. }
  114. void on_response(traits_t::response::message_t &msg) noexcept {
  115. req_val += msg.payload.req->payload.request_payload.value;
  116. ec = msg.payload.ec;
  117. if (!ec) {
  118. res_val += 9;
  119. }
  120. }
  121. };
  122. struct good_supervisor_t : rt::supervisor_test_t {
  123. int req_val = 0;
  124. int res_val = 0;
  125. std::error_code ec;
  126. using rt::supervisor_test_t::supervisor_test_t;
  127. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  128. plugin.with_casted<r::plugin::starter_plugin_t>([](auto &p) {
  129. p.subscribe_actor(&good_supervisor_t::on_request);
  130. p.subscribe_actor(&good_supervisor_t::on_response);
  131. });
  132. }
  133. void on_start() noexcept override {
  134. rt::supervisor_test_t::on_start();
  135. request<request_sample_t>(this->address, 4).send(rt::default_timeout);
  136. }
  137. void on_request(traits_t::request::message_t &msg) noexcept { reply_to(msg, 5); }
  138. void on_response(traits_t::response::message_t &msg) noexcept {
  139. req_val += msg.payload.req->payload.request_payload.value;
  140. res_val += msg.payload.res.value;
  141. ec = msg.payload.ec;
  142. }
  143. };
  144. struct good_actor2_t : public r::actor_base_t {
  145. using traits2_t = r::request_traits_t<req2_t>;
  146. using r::actor_base_t::actor_base_t;
  147. int req_val = 0;
  148. int res_val = 0;
  149. r::address_ptr_t reply_addr;
  150. std::error_code ec;
  151. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  152. plugin.with_casted<r::plugin::starter_plugin_t>([this](auto &p) {
  153. reply_addr = create_address();
  154. p.subscribe_actor(&good_actor2_t::on_response, reply_addr);
  155. p.subscribe_actor(&good_actor2_t::on_request);
  156. });
  157. }
  158. void on_start() noexcept override {
  159. r::actor_base_t::on_start();
  160. request_via<req2_t>(address, reply_addr, 4).send(rt::default_timeout);
  161. }
  162. void on_request(traits2_t::request::message_t &msg) noexcept { reply_to(msg, 5); }
  163. void on_response(traits2_t::response::message_t &msg) noexcept {
  164. req_val += msg.payload.req->payload.request_payload.value;
  165. res_val += msg.payload.res->value;
  166. ec = msg.payload.ec;
  167. }
  168. };
  169. struct good_actor3_t : public r::actor_base_t {
  170. using traits2_t = r::request_traits_t<req2_t>;
  171. using r::actor_base_t::actor_base_t;
  172. int req_left = 1;
  173. int req_val = 0;
  174. int res_val = 0;
  175. std::error_code ec;
  176. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  177. plugin.with_casted<r::plugin::starter_plugin_t>([](auto &p) {
  178. p.subscribe_actor(&good_actor3_t::on_response);
  179. p.subscribe_actor(&good_actor3_t::on_request);
  180. });
  181. }
  182. void on_start() noexcept override {
  183. r::actor_base_t::on_start();
  184. request<req2_t>(address, 4).send(rt::default_timeout);
  185. }
  186. void on_request(traits2_t::request::message_t &msg) noexcept { reply_to(msg, 5); }
  187. void on_response(traits2_t::response::message_t &msg) noexcept {
  188. req_val += msg.payload.req->payload.request_payload.value;
  189. res_val += msg.payload.res->value;
  190. ec = msg.payload.ec;
  191. if (req_left) {
  192. --req_left;
  193. request<req2_t>(address, 4).send(rt::default_timeout);
  194. }
  195. }
  196. };
  197. struct request_forwarder_t : public r::actor_base_t {
  198. using traits2_t = r::request_traits_t<req2_t>;
  199. using req_ptr_t = traits2_t::request::message_ptr_t;
  200. using r::actor_base_t::actor_base_t;
  201. int req_val = 0;
  202. int res_val = 0;
  203. r::address_ptr_t back_addr;
  204. r::request_id_t back_req1_id = 0;
  205. r::request_id_t back_req2_id = 0;
  206. req_ptr_t req_ptr;
  207. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  208. plugin.with_casted<r::plugin::starter_plugin_t>([this](auto &p) {
  209. back_addr = supervisor->create_address();
  210. p.subscribe_actor(&request_forwarder_t::on_request_front);
  211. p.subscribe_actor(&request_forwarder_t::on_response_front);
  212. p.subscribe_actor(&request_forwarder_t::on_request_back, back_addr);
  213. p.subscribe_actor(&request_forwarder_t::on_response_back, back_addr);
  214. });
  215. }
  216. void shutdown_start() noexcept override {
  217. req_ptr.reset();
  218. r::actor_base_t::shutdown_start();
  219. }
  220. void on_start() noexcept override {
  221. r::actor_base_t::on_start();
  222. request<req2_t>(address, 4).send(rt::default_timeout);
  223. }
  224. void on_request_front(traits2_t::request::message_t &msg) noexcept {
  225. auto &payload = msg.payload.request_payload;
  226. back_req1_id = request_via<req2_t>(back_addr, back_addr, payload).send(r::pt::seconds(1));
  227. req_ptr = &msg;
  228. }
  229. void on_response_front(traits2_t::response::message_t &msg) noexcept {
  230. req_val += msg.payload.req->payload.request_payload.value;
  231. res_val += msg.payload.res->value;
  232. }
  233. void on_request_back(traits2_t::request::message_t &msg) noexcept { reply_to(msg, 5); }
  234. void on_response_back(traits2_t::response::message_t &msg) noexcept {
  235. req_val += msg.payload.req->payload.request_payload.value * 2;
  236. res_val += msg.payload.res->value * 2;
  237. back_req2_id = msg.payload.request_id();
  238. reply_to(*req_ptr, msg.payload.ec, std::move(msg.payload.res));
  239. }
  240. };
  241. struct intrusive_actor_t : public r::actor_base_t {
  242. using traits3_t = r::request_traits_t<req3_t>;
  243. using req_ptr_t = traits3_t::request::message_ptr_t;
  244. using r::actor_base_t::actor_base_t;
  245. int req_val = 0;
  246. int res_val = 0;
  247. r::address_ptr_t back_addr;
  248. req_ptr_t req_ptr;
  249. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  250. plugin.with_casted<r::plugin::starter_plugin_t>([this](auto &p) {
  251. back_addr = supervisor->create_address();
  252. p.subscribe_actor(&intrusive_actor_t::on_request_front);
  253. p.subscribe_actor(&intrusive_actor_t::on_response_front);
  254. p.subscribe_actor(&intrusive_actor_t::on_request_back, back_addr);
  255. p.subscribe_actor(&intrusive_actor_t::on_response_back, back_addr);
  256. });
  257. }
  258. void shutdown_start() noexcept override {
  259. req_ptr.reset();
  260. r::actor_base_t::shutdown_start();
  261. }
  262. void on_start() noexcept override {
  263. r::actor_base_t::on_start();
  264. request<req3_t>(address, 4).send(r::pt::seconds(1));
  265. }
  266. void on_request_front(traits3_t::request::message_t &msg) noexcept {
  267. auto &payload = msg.payload.request_payload;
  268. request_via<req3_t>(back_addr, back_addr, payload).send(r::pt::seconds(1));
  269. req_ptr = &msg;
  270. }
  271. void on_response_front(traits3_t::response::message_t &msg) noexcept {
  272. req_val += msg.payload.req->payload.request_payload->value;
  273. res_val += msg.payload.res->value;
  274. }
  275. void on_request_back(traits3_t::request::message_t &msg) noexcept { reply_to(msg, 5); }
  276. void on_response_back(traits3_t::response::message_t &msg) noexcept {
  277. req_val += msg.payload.req->payload.request_payload->value * 2;
  278. res_val += msg.payload.res->value * 2;
  279. reply_to(*req_ptr, msg.payload.ec, std::move(msg.payload.res));
  280. }
  281. };
  282. struct duplicating_actor_t : public r::actor_base_t {
  283. using r::actor_base_t::actor_base_t;
  284. int req_val = 0;
  285. int res_val = 0;
  286. std::error_code ec;
  287. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  288. plugin.with_casted<r::plugin::starter_plugin_t>([](auto &p) {
  289. p.subscribe_actor(&duplicating_actor_t::on_request);
  290. p.subscribe_actor(&duplicating_actor_t::on_response);
  291. });
  292. }
  293. void on_start() noexcept override {
  294. r::actor_base_t::on_start();
  295. request<request_sample_t>(address, 4).send(rt::default_timeout);
  296. }
  297. void on_request(traits_t::request::message_t &msg) noexcept {
  298. reply_to(msg, 5);
  299. reply_to(msg, 5);
  300. }
  301. void on_response(traits_t::response::message_t &msg) noexcept {
  302. req_val += msg.payload.req->payload.request_payload.value;
  303. res_val += msg.payload.res.value;
  304. ec = msg.payload.ec;
  305. }
  306. };
  307. TEST_CASE("request-response successfull delivery", "[actor]") {
  308. r::system_context_t system_context;
  309. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  310. sup->do_process();
  311. auto init_subs_count = sup->get_subscription().access<rt::to::mine_handlers>().size();
  312. auto init_pts_count = sup->get_points().size();
  313. auto actor = sup->create_actor<good_actor_t>().timeout(rt::default_timeout).finish();
  314. sup->do_process();
  315. REQUIRE(sup->active_timers.size() == 0);
  316. REQUIRE(actor->req_val == 4);
  317. REQUIRE(actor->res_val == 5);
  318. REQUIRE(actor->ec == r::error_code_t::success);
  319. actor->do_shutdown();
  320. sup->do_process();
  321. REQUIRE(sup->active_timers.size() == 0);
  322. std::size_t delta = 1; /* + shutdown confirmation triggered on self */
  323. REQUIRE(sup->get_points().size() == init_pts_count + delta);
  324. REQUIRE(sup->get_subscription().access<rt::to::mine_handlers>().size() == init_subs_count + delta);
  325. sup->do_shutdown();
  326. sup->do_process();
  327. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  328. REQUIRE(sup->get_leader_queue().size() == 0);
  329. REQUIRE(sup->get_points().size() == 0);
  330. CHECK(rt::empty(sup->get_subscription()));
  331. REQUIRE(sup->get_children_count() == 0);
  332. REQUIRE(sup->get_requests().size() == 0);
  333. REQUIRE(sup->active_timers.size() == 0);
  334. }
  335. TEST_CASE("request-response successfull delivery indentical message to 2 actors", "[actor]") {
  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 actor1 = sup->create_actor<good_actor_t>().timeout(rt::default_timeout).finish();
  339. auto actor2 = sup->create_actor<good_actor_t>().timeout(rt::default_timeout).finish();
  340. sup->do_process();
  341. REQUIRE(sup->active_timers.size() == 0);
  342. REQUIRE(actor1->req_val == 4);
  343. REQUIRE(actor1->res_val == 5);
  344. REQUIRE(actor1->ec == r::error_code_t::success);
  345. REQUIRE(actor2->req_val == 4);
  346. REQUIRE(actor2->res_val == 5);
  347. REQUIRE(actor2->ec == r::error_code_t::success);
  348. sup->do_shutdown();
  349. sup->do_process();
  350. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  351. REQUIRE(sup->get_leader_queue().size() == 0);
  352. REQUIRE(sup->get_points().size() == 0);
  353. CHECK(rt::empty(sup->get_subscription()));
  354. REQUIRE(sup->get_children_count() == 0);
  355. REQUIRE(sup->get_requests().size() == 0);
  356. REQUIRE(sup->active_timers.size() == 0);
  357. }
  358. TEST_CASE("request-response timeout", "[actor]") {
  359. r::system_context_t system_context;
  360. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  361. auto actor = sup->create_actor<bad_actor_t>().timeout(rt::default_timeout).finish();
  362. sup->do_process();
  363. REQUIRE(actor->req_val == 0);
  364. REQUIRE(actor->res_val == 0);
  365. REQUIRE(sup->active_timers.size() == 1);
  366. REQUIRE(!actor->ec);
  367. auto timer_it = *sup->active_timers.begin();
  368. ((r::actor_base_t *)sup.get())
  369. ->access<rt::to::on_timer_trigger, r::request_id_t, bool>(timer_it->request_id, false);
  370. sup->do_process();
  371. REQUIRE(actor->req_msg);
  372. REQUIRE(actor->req_val == 4);
  373. REQUIRE(actor->res_val == 0);
  374. REQUIRE(actor->ec);
  375. REQUIRE(actor->ec == r::error_code_t::request_timeout);
  376. REQUIRE(actor->ec.message() == std::string("request timeout"));
  377. sup->active_timers.clear();
  378. actor->reply_to(*actor->req_msg, 1);
  379. sup->do_process();
  380. // nothing should be changed, i.e. reply should just be dropped
  381. REQUIRE(actor->req_val == 4);
  382. REQUIRE(actor->res_val == 0);
  383. REQUIRE(actor->ec == r::error_code_t::request_timeout);
  384. sup->do_shutdown();
  385. sup->do_process();
  386. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  387. REQUIRE(sup->get_leader_queue().size() == 0);
  388. REQUIRE(sup->get_points().size() == 0);
  389. CHECK(rt::empty(sup->get_subscription()));
  390. REQUIRE(sup->active_timers.size() == 0);
  391. }
  392. TEST_CASE("response with custom error", "[actor]") {
  393. r::system_context_t system_context;
  394. auto sup = system_context.create_supervisor<rt::supervisor_test_t>().timeout(rt::default_timeout).finish();
  395. auto actor = sup->create_actor<bad_actor2_t>().timeout(rt::default_timeout).finish();
  396. sup->do_process();
  397. REQUIRE(actor->req_val == 4);
  398. REQUIRE(actor->res_val == 0);
  399. REQUIRE(actor->ec);
  400. REQUIRE(actor->ec == r::error_code_t::request_timeout);
  401. REQUIRE(sup->active_timers.size() == 0);
  402. sup->do_shutdown();
  403. sup->do_process();
  404. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  405. REQUIRE(sup->get_leader_queue().size() == 0);
  406. REQUIRE(sup->get_points().size() == 0);
  407. CHECK(rt::empty(sup->get_subscription()));
  408. }
  409. TEST_CASE("request-response successfull delivery (supervisor)", "[supervisor]") {
  410. r::system_context_t system_context;
  411. auto sup = system_context.create_supervisor<good_supervisor_t>().timeout(rt::default_timeout).finish();
  412. sup->do_process();
  413. REQUIRE(sup->active_timers.size() == 0);
  414. REQUIRE(sup->req_val == 4);
  415. REQUIRE(sup->res_val == 5);
  416. REQUIRE(sup->ec == r::error_code_t::success);
  417. sup->do_shutdown();
  418. sup->do_process();
  419. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  420. REQUIRE(sup->get_leader_queue().size() == 0);
  421. REQUIRE(sup->get_points().size() == 0);
  422. CHECK(rt::empty(sup->get_subscription()));
  423. REQUIRE(sup->get_children_count() == 0);
  424. REQUIRE(sup->get_requests().size() == 0);
  425. REQUIRE(sup->active_timers.size() == 0);
  426. }
  427. TEST_CASE("request-response successfull delivery, ref-counted response", "[actor]") {
  428. r::system_context_t system_context;
  429. auto sup = system_context.create_supervisor<good_supervisor_t>().timeout(rt::default_timeout).finish();
  430. auto actor = sup->create_actor<good_actor2_t>().timeout(rt::default_timeout).finish();
  431. sup->do_process();
  432. REQUIRE(sup->active_timers.size() == 0);
  433. REQUIRE(actor->req_val == 4);
  434. REQUIRE(actor->res_val == 5);
  435. REQUIRE(actor->ec == r::error_code_t::success);
  436. sup->do_shutdown();
  437. sup->do_process();
  438. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  439. REQUIRE(sup->get_leader_queue().size() == 0);
  440. REQUIRE(sup->get_points().size() == 0);
  441. CHECK(rt::empty(sup->get_subscription()));
  442. REQUIRE(sup->get_children_count() == 0);
  443. REQUIRE(sup->get_requests().size() == 0);
  444. REQUIRE(sup->active_timers.size() == 0);
  445. }
  446. TEST_CASE("request-response successfull delivery, twice", "[actor]") {
  447. r::system_context_t system_context;
  448. auto sup = system_context.create_supervisor<good_supervisor_t>().timeout(rt::default_timeout).finish();
  449. auto actor = sup->create_actor<good_actor3_t>().timeout(rt::default_timeout).finish();
  450. sup->do_process();
  451. REQUIRE(sup->active_timers.size() == 0);
  452. REQUIRE(actor->req_val == 4 * 2);
  453. REQUIRE(actor->res_val == 5 * 2);
  454. REQUIRE(actor->ec == r::error_code_t::success);
  455. sup->do_shutdown();
  456. sup->do_process();
  457. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  458. REQUIRE(sup->get_leader_queue().size() == 0);
  459. REQUIRE(sup->get_points().size() == 0);
  460. CHECK(rt::empty(sup->get_subscription()));
  461. REQUIRE(sup->get_children_count() == 0);
  462. REQUIRE(sup->get_requests().size() == 0);
  463. REQUIRE(sup->active_timers.size() == 0);
  464. }
  465. TEST_CASE("responce is sent twice, but received once", "[supervisor]") {
  466. r::system_context_t system_context;
  467. auto sup = system_context.create_supervisor<good_supervisor_t>().timeout(rt::default_timeout).finish();
  468. auto actor = sup->create_actor<duplicating_actor_t>().timeout(rt::default_timeout).finish();
  469. sup->do_process();
  470. REQUIRE(sup->active_timers.size() == 0);
  471. REQUIRE(actor->req_val == 4);
  472. REQUIRE(actor->res_val == 5);
  473. REQUIRE(actor->ec == r::error_code_t::success);
  474. sup->do_shutdown();
  475. sup->do_process();
  476. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  477. REQUIRE(sup->get_leader_queue().size() == 0);
  478. REQUIRE(sup->get_points().size() == 0);
  479. CHECK(rt::empty(sup->get_subscription()));
  480. REQUIRE(sup->get_children_count() == 0);
  481. REQUIRE(sup->get_requests().size() == 0);
  482. REQUIRE(sup->active_timers.size() == 0);
  483. }
  484. TEST_CASE("ref-counted response forwarding", "[actor]") {
  485. r::system_context_t system_context;
  486. auto sup = system_context.create_supervisor<good_supervisor_t>().timeout(rt::default_timeout).finish();
  487. auto actor = sup->create_actor<request_forwarder_t>().timeout(rt::default_timeout).finish();
  488. sup->do_process();
  489. REQUIRE(sup->active_timers.size() == 0);
  490. REQUIRE(actor->req_val == 4 + 4 * 2);
  491. REQUIRE(actor->res_val == 5 + 5 * 2);
  492. REQUIRE(actor->back_req1_id == actor->back_req2_id);
  493. sup->do_shutdown();
  494. sup->do_process();
  495. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  496. REQUIRE(sup->get_leader_queue().size() == 0);
  497. REQUIRE(sup->get_points().size() == 0);
  498. CHECK(rt::empty(sup->get_subscription()));
  499. REQUIRE(sup->get_children_count() == 0);
  500. REQUIRE(sup->get_requests().size() == 0);
  501. REQUIRE(sup->active_timers.size() == 0);
  502. }
  503. TEST_CASE("intrusive pointer request/responce", "[actor]") {
  504. r::system_context_t system_context;
  505. auto sup = system_context.create_supervisor<good_supervisor_t>().timeout(rt::default_timeout).finish();
  506. auto actor = sup->create_actor<intrusive_actor_t>().timeout(rt::default_timeout).finish();
  507. sup->do_process();
  508. REQUIRE(sup->active_timers.size() == 0);
  509. REQUIRE(actor->req_val == 4 + 4 * 2);
  510. REQUIRE(actor->res_val == 5 + 5 * 2);
  511. sup->do_shutdown();
  512. sup->do_process();
  513. REQUIRE(sup->get_state() == r::state_t::SHUT_DOWN);
  514. REQUIRE(sup->get_leader_queue().size() == 0);
  515. REQUIRE(sup->get_points().size() == 0);
  516. CHECK(rt::empty(sup->get_subscription()));
  517. REQUIRE(sup->get_children_count() == 0);
  518. REQUIRE(sup->get_requests().size() == 0);
  519. REQUIRE(sup->active_timers.size() == 0);
  520. }