tristate_obj.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #define BOOST_TEST_DYN_LINK
  2. #include "core/tristate_obj.h"
  3. #include "utility/bit_operations.hpp"
  4. #include "utility/debug_utility.hpp"
  5. #include <boost/asio/co_spawn.hpp>
  6. #include <boost/asio/detached.hpp>
  7. #include <boost/asio/high_resolution_timer.hpp>
  8. #include <boost/asio/this_coro.hpp>
  9. #include <boost/asio/use_awaitable.hpp>
  10. #include <boost/test/unit_test.hpp>
  11. #include <chrono>
  12. using boost::asio::awaitable;
  13. using boost::asio::co_spawn;
  14. using boost::asio::detached;
  15. using boost::asio::use_awaitable;
  16. using namespace sophiar;
  17. using namespace std::chrono_literals;
  18. awaitable<void> test_tristate_obj_1() {
  19. struct type_a : public tristate_obj {
  20. unsigned int cnt = 0;
  21. awaitable<bool> on_init(const nlohmann::json &) noexcept {
  22. set_bit(cnt, 0);
  23. co_return true;
  24. }
  25. awaitable<bool> on_start(const nlohmann::json &) noexcept {
  26. set_bit(cnt, 1);
  27. co_return true;
  28. }
  29. awaitable<void> on_stop() noexcept {
  30. set_bit(cnt, 2);
  31. co_return;
  32. }
  33. awaitable<void> on_reset() noexcept {
  34. set_bit(cnt, 3);
  35. co_return;
  36. }
  37. } node_a;
  38. co_await node_a.init({});
  39. BOOST_TEST(node_a.cnt == 0b0001);
  40. BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING));
  41. co_await node_a.start({});
  42. BOOST_TEST(node_a.cnt == 0b0011);
  43. BOOST_TEST((node_a.get_state() == type_a::state_type::RUNNING));
  44. co_await node_a.stop();
  45. BOOST_TEST(node_a.cnt == 0b0111);
  46. BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING));
  47. co_await node_a.reset();
  48. BOOST_TEST(node_a.cnt == 0b1111);
  49. BOOST_TEST((node_a.get_state() == type_a::state_type::INITIAL));
  50. node_a.cnt = 0;
  51. co_await node_a.start({}); // test start before init
  52. BOOST_TEST(node_a.cnt == 0b0000);
  53. BOOST_TEST((node_a.get_state() == type_a::state_type::INITIAL));
  54. co_await node_a.init({});
  55. co_await node_a.start({});
  56. BOOST_TEST(node_a.cnt == 0b0011);
  57. BOOST_TEST((node_a.get_state() == type_a::state_type::RUNNING));
  58. co_await node_a.reset(); // test force reset
  59. BOOST_TEST(node_a.cnt == 0b1111);
  60. BOOST_TEST((node_a.get_state() == type_a::state_type::INITIAL));
  61. co_return;
  62. }
  63. awaitable<void> test_tristate_obj_2() {
  64. struct type_a : public tristate_obj {
  65. int cnt = 0;
  66. boost::asio::high_resolution_timer timer;
  67. type_a()
  68. : timer(*global_context) {}
  69. awaitable<bool> on_init(const nlohmann::json &) noexcept {
  70. timer.expires_from_now(100ms);
  71. co_await timer.async_wait(use_awaitable);
  72. set_bit(cnt, 0);
  73. co_return true;
  74. }
  75. awaitable<bool> on_start(const nlohmann::json &) noexcept {
  76. timer.expires_from_now(100ms);
  77. co_await timer.async_wait(use_awaitable);
  78. set_bit(cnt, 1);
  79. co_return true;
  80. }
  81. awaitable<void> on_stop() noexcept {
  82. timer.expires_from_now(100ms);
  83. co_await timer.async_wait(use_awaitable);
  84. set_bit(cnt, 2);
  85. co_return;
  86. }
  87. awaitable<void> on_reset() noexcept {
  88. timer.expires_from_now(100ms);
  89. co_await timer.async_wait(use_awaitable);
  90. set_bit(cnt, 3);
  91. co_return;
  92. }
  93. } node_a;
  94. co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable<void> {
  95. co_await coro_sleep(50ms);
  96. co_await node_a.reset();
  97. co_return;
  98. }, detached);
  99. BOOST_TEST((co_await node_a.init({}) == false));
  100. BOOST_TEST(node_a.cnt == 0b1000);
  101. BOOST_TEST((node_a.get_state() == type_a::state_type::INITIAL));
  102. node_a.cnt = 0;
  103. BOOST_TEST((co_await node_a.init({}) == true));
  104. BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING));
  105. co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable<void> {
  106. co_await coro_sleep(50ms);
  107. co_await node_a.stop();
  108. co_return;
  109. }, detached);
  110. BOOST_TEST((co_await node_a.start({}) == false));
  111. BOOST_TEST(node_a.cnt == 0b0101);
  112. BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING));
  113. node_a.cnt = 0b0001;
  114. co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable<void> {
  115. co_await coro_sleep(50ms);
  116. co_await node_a.reset();
  117. co_return;
  118. }, detached);
  119. BOOST_TEST((co_await node_a.start({}) == false));
  120. BOOST_TEST(node_a.cnt = 0b0101);
  121. BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING));
  122. co_await coro_sleep(150ms);
  123. BOOST_TEST(node_a.cnt == 0b1101);
  124. BOOST_TEST((node_a.get_state() == type_a::state_type::INITIAL));
  125. co_return;
  126. }
  127. awaitable<void> test_tristate_obj_3() {
  128. struct type_a : public tristate_obj {
  129. int cnt = 0;
  130. boost::asio::high_resolution_timer timer;
  131. type_a()
  132. : timer(*global_context) {}
  133. awaitable<bool> on_init(const nlohmann::json &) noexcept {
  134. timer.expires_from_now(100ms);
  135. co_await timer.async_wait(use_awaitable);
  136. ++cnt;
  137. co_return true;
  138. }
  139. awaitable<bool> on_start(const nlohmann::json &) noexcept {
  140. timer.expires_from_now(100ms);
  141. co_await timer.async_wait(use_awaitable);
  142. ++cnt;
  143. co_return true;
  144. }
  145. awaitable<void> on_stop() noexcept {
  146. timer.expires_from_now(100ms);
  147. co_await timer.async_wait(use_awaitable);
  148. ++cnt;
  149. co_return;
  150. }
  151. awaitable<void> on_reset() noexcept {
  152. timer.expires_from_now(100ms);
  153. co_await timer.async_wait(use_awaitable);
  154. ++cnt;
  155. co_return;
  156. }
  157. } node_a;
  158. node_a.cnt = 0;
  159. co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable<void> {
  160. BOOST_TEST(co_await node_a.init({}) == true);
  161. BOOST_TEST(node_a.cnt == 1);
  162. }, detached);
  163. BOOST_TEST(co_await node_a.init({}) == true);
  164. BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING));
  165. BOOST_TEST(node_a.cnt == 1);
  166. node_a.cnt = 0;
  167. co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable<void> {
  168. BOOST_TEST(co_await node_a.start({}) == true);
  169. BOOST_TEST(node_a.cnt == 1);
  170. }, detached);
  171. BOOST_TEST(co_await node_a.start({}) == true);
  172. BOOST_TEST((node_a.get_state() == type_a::state_type::RUNNING));
  173. BOOST_TEST(node_a.cnt == 1);
  174. node_a.cnt = 0;
  175. co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable<void> {
  176. co_await node_a.stop();
  177. BOOST_TEST(node_a.cnt == 1);
  178. }, detached);
  179. co_await node_a.stop();
  180. BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING));
  181. BOOST_TEST(node_a.cnt == 1);
  182. node_a.cnt = 0;
  183. co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable<void> {
  184. co_await node_a.reset();
  185. BOOST_TEST(node_a.cnt == 1);
  186. }, detached);
  187. co_await node_a.reset();
  188. BOOST_TEST((node_a.get_state() == type_a::state_type::INITIAL));
  189. BOOST_TEST(node_a.cnt == 1);
  190. node_a.cnt = 0;
  191. co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable<void> {
  192. co_await coro_sleep(50ms);
  193. co_await node_a.reset();
  194. co_return;
  195. }, detached);
  196. co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable<void> {
  197. BOOST_TEST(co_await node_a.init({}) == false);
  198. BOOST_TEST(node_a.cnt == 1);
  199. }, detached);
  200. BOOST_TEST(co_await node_a.init({}) == false);
  201. BOOST_TEST((node_a.get_state() == type_a::state_type::INITIAL));
  202. BOOST_TEST(node_a.cnt == 1);
  203. co_await node_a.init({});
  204. node_a.cnt = 0;
  205. co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable<void> {
  206. co_await coro_sleep(50ms);
  207. co_await node_a.stop();
  208. co_return;
  209. }, detached);
  210. co_spawn(co_await boost::asio::this_coro::executor, [&]() -> awaitable<void> {
  211. BOOST_TEST(co_await node_a.start({}) == false);
  212. BOOST_TEST(node_a.cnt == 1);
  213. }, detached);
  214. BOOST_TEST(co_await node_a.start({}) == false);
  215. BOOST_TEST((node_a.get_state() == type_a::state_type::PENDING));
  216. BOOST_TEST(node_a.cnt == 1);
  217. }
  218. BOOST_AUTO_TEST_CASE(test_tristate_obj) {
  219. initialize({});
  220. co_spawn(*global_context, test_tristate_obj_1(), detached);
  221. co_spawn(*global_context, test_tristate_obj_2(), detached);
  222. co_spawn(*global_context, test_tristate_obj_3(), detached);
  223. global_context->run();
  224. }