073-dialer.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou
  3. #include "model/diff/contact/peer_state.h"
  4. #include "test-utils.h"
  5. #include "access.h"
  6. #include "model/cluster.h"
  7. #include "model/diff/contact/dial_request.h"
  8. #include "diff-builder.h"
  9. #include "net/dialer_actor.h"
  10. #include "access.h"
  11. #include "test_supervisor.h"
  12. using namespace syncspirit;
  13. using namespace syncspirit::test;
  14. using namespace syncspirit::model;
  15. using namespace syncspirit::net;
  16. using state_t = model::device_state_t;
  17. namespace {
  18. struct test_supervisor_t : supervisor_t {
  19. using supervisor_t::supervisor_t;
  20. outcome::result<void> operator()(const model::diff::contact::peer_state_t &diff, void *custom) noexcept override {
  21. if (diff.state.is_unknown()) {
  22. ++seen_unknown;
  23. }
  24. return diff.visit_next(*this, custom);
  25. }
  26. outcome::result<void> operator()(const model::diff::contact::dial_request_t &diff, void *custom) noexcept override {
  27. ++seen_dial_requests;
  28. return diff.visit_next(*this, custom);
  29. }
  30. uint32_t seen_unknown = 0;
  31. uint32_t seen_dial_requests = 0;
  32. };
  33. struct fixture_t {
  34. fixture_t(bool start_dialer_) noexcept : start_dialer{start_dialer_} { test::init_logging(); }
  35. virtual void run() noexcept {
  36. auto peer_id =
  37. device_id_t::from_string("VUV42CZ-IQD5A37-RPEBPM4-VVQK6E4-6WSKC7B-PVJQHHD-4PZD44V-ENC6WAZ").value();
  38. peer_device = device_t::create(peer_id, "peer-device").value();
  39. auto my_id =
  40. device_id_t::from_string("KHQNO2S-5QSILRK-YX4JZZ4-7L77APM-QNVGZJT-EKU7IFI-PNEPBMY-4MXFMQD").value();
  41. auto my_device = device_t::create(my_id, "my-device").value();
  42. cluster = new cluster_t(my_device, 1);
  43. cluster->get_devices().put(my_device);
  44. cluster->get_devices().put(peer_device);
  45. r::system_context_t ctx;
  46. sup = ctx.create_supervisor<test_supervisor_t>().timeout(timeout).create_registry().finish();
  47. sup->cluster = cluster;
  48. sup->start();
  49. sup->do_process();
  50. CHECK(static_cast<r::actor_base_t *>(sup.get())->access<to::state>() == r::state_t::OPERATIONAL);
  51. auto global_device_id =
  52. model::device_id_t::from_string("LYXKCHX-VI3NYZR-ALCJBHF-WMZYSPK-QG6QJA3-MPFYMSO-U56GTUK-NA2MIAW");
  53. auto cfg = config::dialer_config_t{true, 500, 1};
  54. auto dialer = sup->create_actor<dialer_actor_t>().cluster(cluster).dialer_config(cfg).timeout(timeout).finish();
  55. target_addr = dialer->get_address();
  56. if (start_dialer) {
  57. sup->do_process();
  58. CHECK(static_cast<r::actor_base_t *>(dialer.get())->access<to::state>() == r::state_t::OPERATIONAL);
  59. }
  60. main();
  61. sup->shutdown();
  62. sup->do_process();
  63. CHECK(static_cast<r::actor_base_t *>(sup.get())->access<to::state>() == r::state_t::SHUT_DOWN);
  64. }
  65. virtual void main() noexcept {}
  66. bool start_dialer;
  67. r::address_ptr_t target_addr;
  68. r::pt::time_duration timeout = r::pt::millisec{10};
  69. cluster_ptr_t cluster;
  70. device_ptr_t peer_device;
  71. r::intrusive_ptr_t<test_supervisor_t> sup;
  72. r::system_context_t ctx;
  73. };
  74. } // namespace
  75. void test_dialer() {
  76. struct F : fixture_t {
  77. using fixture_t::fixture_t;
  78. void main() noexcept override {
  79. auto builder = diff_builder_t(*cluster);
  80. REQUIRE(peer_device->get_state().get_connection_state() == connection_state_t::offline);
  81. sup->send<net::payload::announce_notification_t>(sup->get_address());
  82. sup->do_process();
  83. SECTION("peer is not online => discover it on timeout") {
  84. CHECK(peer_device->get_state().get_connection_state() == connection_state_t::offline);
  85. CHECK(sup->seen_unknown == 1);
  86. }
  87. SECTION("peer online & offline") {
  88. builder.update_state(*peer_device, {}, peer_device->get_state().connecting())
  89. .then()
  90. .update_state(*peer_device, {}, peer_device->get_state().offline())
  91. .apply(*sup);
  92. REQUIRE(sup->timers.size() == 1);
  93. sup->do_invoke_timer((*sup->timers.begin())->request_id);
  94. sup->do_process();
  95. CHECK(sup->seen_unknown == 2);
  96. CHECK(sup->seen_dial_requests == 0);
  97. CHECK(peer_device->get_state().get_connection_state() == connection_state_t::offline);
  98. auto uri = utils::parse("tcp://127.0.0.1");
  99. builder.update_contact(peer_device->device_id(), {uri}).apply(*sup);
  100. CHECK(peer_device->get_state().get_connection_state() == connection_state_t::offline);
  101. CHECK(sup->timers.size() == 1);
  102. CHECK(sup->seen_unknown == 2);
  103. CHECK(sup->seen_dial_requests == 1);
  104. builder.update_state(*peer_device, {}, peer_device->get_state().connecting().connected())
  105. .then()
  106. .update_state(*peer_device, {}, peer_device->get_state().online(uri->c_str()))
  107. .apply(*sup);
  108. CHECK(sup->timers.size() == 0);
  109. CHECK(sup->seen_unknown == 2);
  110. CHECK(sup->seen_dial_requests == 1);
  111. builder.update_state(*peer_device, {}, peer_device->get_state().offline()).apply(*sup);
  112. CHECK(sup->timers.size() == 1);
  113. sup->do_invoke_timer((*sup->timers.begin())->request_id);
  114. sup->do_process();
  115. CHECK(sup->timers.size() == 0);
  116. CHECK(sup->seen_dial_requests == 2);
  117. }
  118. SECTION("remove peer") {
  119. sup->seen_dial_requests = 0;
  120. sup->seen_unknown = 0;
  121. SECTION("start discover") {
  122. builder.update_state(*peer_device, {}, peer_device->get_state().connecting().connected())
  123. .then()
  124. .update_state(*peer_device, {}, peer_device->get_state().offline())
  125. .apply(*sup);
  126. CHECK(sup->timers.size() == 1);
  127. }
  128. builder.remove_peer(*peer_device).apply(*sup);
  129. CHECK(sup->timers.size() == 0);
  130. }
  131. }
  132. };
  133. F(true).run();
  134. }
  135. void test_static_address() {
  136. struct F : fixture_t {
  137. using fixture_t::fixture_t;
  138. void main() noexcept override {
  139. auto builder = diff_builder_t(*cluster);
  140. auto uri = utils::parse("tcp://127.0.0.1");
  141. peer_device->set_static_uris({uri});
  142. sup->do_process();
  143. CHECK(peer_device->get_state().is_offline());
  144. CHECK(sup->seen_dial_requests == 1);
  145. builder.update_state(*peer_device, {}, peer_device->get_state().connecting())
  146. .then()
  147. .update_state(*peer_device, {}, peer_device->get_state().offline())
  148. .apply(*sup);
  149. CHECK(sup->timers.size() == 1);
  150. SECTION("remove") {
  151. builder.remove_peer(*peer_device).apply(*sup);
  152. CHECK(sup->timers.size() == 0);
  153. }
  154. SECTION("invoke") {
  155. sup->do_invoke_timer((*sup->timers.begin())->request_id);
  156. sup->do_process();
  157. CHECK(sup->seen_dial_requests == 2);
  158. }
  159. }
  160. };
  161. F(false).run();
  162. }
  163. void test_peer_removal() {
  164. struct F : fixture_t {
  165. using fixture_t::fixture_t;
  166. void main() noexcept override {
  167. REQUIRE(peer_device->get_state().get_connection_state() == connection_state_t::offline);
  168. SECTION("with announce") {
  169. sup->send<net::payload::announce_notification_t>(sup->get_address());
  170. sup->do_process();
  171. diff_builder_t(*cluster).remove_peer(*peer_device).apply(*sup);
  172. REQUIRE(sup->timers.size() == 0);
  173. }
  174. SECTION("without announce") {
  175. diff_builder_t(*cluster).remove_peer(*peer_device).apply(*sup);
  176. REQUIRE(sup->timers.size() == 0);
  177. }
  178. }
  179. };
  180. F(true).run();
  181. }
  182. int _init() {
  183. REGISTER_TEST_CASE(test_dialer, "test_dialer", "[net]");
  184. REGISTER_TEST_CASE(test_static_address, "test_static_address", "[net]");
  185. REGISTER_TEST_CASE(test_peer_removal, "test_peer_removal", "[net]");
  186. return 1;
  187. }
  188. static int v = _init();