085-scan-scheduler.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. // SPDX-FileCopyrightText: 2019-2025 Ivan Baidakou
  3. #include "test-utils.h"
  4. #include "access.h"
  5. #include "test_supervisor.h"
  6. #include "diff-builder.h"
  7. #include "model/cluster.h"
  8. #include "fs/scan_scheduler.h"
  9. #include "net/names.h"
  10. using namespace syncspirit;
  11. using namespace syncspirit::test;
  12. using namespace syncspirit::model;
  13. struct fixture_t {
  14. using target_ptr_t = r::intrusive_ptr_t<fs::scan_scheduler_t>;
  15. fixture_t() noexcept {
  16. test::init_logging();
  17. log = utils::get_logger("fixture");
  18. }
  19. void run() noexcept {
  20. auto my_id =
  21. device_id_t::from_string("KHQNO2S-5QSILRK-YX4JZZ4-7L77APM-QNVGZJT-EKU7IFI-PNEPBMY-4MXFMQD").value();
  22. my_device = device_t::create(my_id, "my-device").value();
  23. cluster = new cluster_t(my_device, 1);
  24. cluster->get_devices().put(my_device);
  25. r::system_context_t ctx;
  26. sup = ctx.create_supervisor<supervisor_t>().timeout(timeout).create_registry().finish();
  27. sup->cluster = cluster;
  28. sup->configure_callback = [&](r::plugin::plugin_base_t &plugin) {
  29. plugin.template with_casted<r::plugin::registry_plugin_t>(
  30. [&](auto &p) { p.register_name(net::names::fs_scanner, sup->get_address()); });
  31. };
  32. sup->start();
  33. sup->do_process();
  34. folder_id = "1234-5678";
  35. CHECK(static_cast<r::actor_base_t *>(sup.get())->access<to::state>() == r::state_t::OPERATIONAL);
  36. sup->do_process();
  37. target = sup->create_actor<fs::scan_scheduler_t>().timeout(timeout).cluster(cluster).finish();
  38. sup->do_process();
  39. REQUIRE(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  40. main();
  41. sup->do_process();
  42. sup->shutdown();
  43. sup->do_process();
  44. CHECK(static_cast<r::actor_base_t *>(sup.get())->access<to::state>() == r::state_t::SHUT_DOWN);
  45. }
  46. virtual void main() noexcept {}
  47. utils::logger_t log;
  48. r::pt::time_duration timeout = r::pt::millisec{10};
  49. r::intrusive_ptr_t<supervisor_t> sup;
  50. cluster_ptr_t cluster;
  51. device_ptr_t my_device;
  52. std::string folder_id;
  53. target_ptr_t target;
  54. model::folder_ptr_t folder;
  55. };
  56. void test_1_folder() {
  57. struct F : fixture_t {
  58. void main() noexcept override {
  59. auto db_folder = db::Folder();
  60. db_folder.set_id(folder_id);
  61. auto builder = diff_builder_t(*cluster);
  62. SECTION("zero rescan time => no scan") {
  63. builder.upsert_folder(db_folder).apply(*sup);
  64. auto folder = cluster->get_folders().by_id(folder_id);
  65. CHECK(!folder->is_scanning());
  66. }
  67. SECTION("non-zero rescan time") {
  68. db_folder.set_rescan_interval(3600);
  69. builder.upsert_folder(db_folder).apply(*sup);
  70. auto folder = cluster->get_folders().by_id(folder_id);
  71. CHECK(folder->is_scanning());
  72. SECTION("scan start/finish") {
  73. builder.scan_finish(folder_id).apply(*sup);
  74. REQUIRE(!folder->is_scanning());
  75. REQUIRE(sup->timers.size() == 1);
  76. sup->do_invoke_timer((*sup->timers.begin())->request_id);
  77. sup->do_process();
  78. REQUIRE(folder->is_scanning());
  79. }
  80. SECTION("synchronization start/finish") {
  81. builder.scan_finish(folder_id).synchronization_start(folder_id).scan_request(folder_id).apply(*sup);
  82. REQUIRE(!folder->is_scanning());
  83. REQUIRE(sup->timers.size() == 0);
  84. builder.synchronization_finish(folder_id).apply(*sup);
  85. REQUIRE(sup->timers.size() == 1);
  86. sup->do_invoke_timer((*sup->timers.begin())->request_id);
  87. sup->do_process();
  88. REQUIRE(folder->is_scanning());
  89. }
  90. }
  91. SECTION("suspending") {
  92. db_folder.set_rescan_interval(3600);
  93. builder.upsert_folder(db_folder).apply(*sup);
  94. auto folder = cluster->get_folders().by_id(folder_id);
  95. CHECK(folder->is_scanning());
  96. builder.suspend(*folder).scan_finish(folder_id).apply(*sup);
  97. REQUIRE(sup->timers.size() == 0);
  98. }
  99. }
  100. };
  101. F().run();
  102. };
  103. void test_2_folders() {
  104. struct F : fixture_t {
  105. void main() noexcept override {
  106. auto f1_id = "1111";
  107. auto f2_id = "2222";
  108. auto db_folder_1 = db::Folder();
  109. auto db_folder_2 = db::Folder();
  110. db_folder_1.set_id(f1_id);
  111. db_folder_2.set_id(f2_id);
  112. db_folder_1.set_rescan_interval(4000);
  113. db_folder_2.set_rescan_interval(2000);
  114. auto builder = diff_builder_t(*cluster);
  115. builder.upsert_folder(db_folder_1)
  116. .upsert_folder(db_folder_2)
  117. .apply(*sup)
  118. .scan_finish(f2_id)
  119. .apply(*sup)
  120. .scan_finish(f1_id)
  121. .apply(*sup);
  122. REQUIRE(sup->timers.size() == 1);
  123. sup->do_invoke_timer((*sup->timers.begin())->request_id);
  124. sup->do_process();
  125. auto f1 = cluster->get_folders().by_id(f1_id);
  126. auto f2 = cluster->get_folders().by_id(f2_id);
  127. REQUIRE(!f1->is_scanning());
  128. REQUIRE(f2->is_scanning());
  129. auto at = r::pt::microsec_clock::local_time() + r::pt::seconds{db_folder_2.rescan_interval() + 1};
  130. builder.scan_finish(f2_id, at).apply(*sup);
  131. REQUIRE(sup->timers.size() == 1);
  132. sup->do_invoke_timer((*sup->timers.begin())->request_id);
  133. sup->do_process();
  134. REQUIRE(f1->is_scanning());
  135. REQUIRE(!f2->is_scanning());
  136. f2->set_scan_finish({});
  137. builder.scan_finish(f1_id, at).scan_request(f2_id).apply(*sup);
  138. REQUIRE(!f1->is_scanning());
  139. REQUIRE(f2->is_scanning());
  140. }
  141. };
  142. F().run();
  143. };
  144. int _init() {
  145. REGISTER_TEST_CASE(test_1_folder, "test_1_folder", "[fs]");
  146. REGISTER_TEST_CASE(test_2_folders, "test_2_folders", "[fs]");
  147. return 1;
  148. }
  149. static int v = _init();