085-scan-scheduler.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. // SPDX-FileCopyrightText: 2019-2024 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. utils::set_default("trace");
  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. }
  92. };
  93. F().run();
  94. };
  95. void test_2_folders() {
  96. struct F : fixture_t {
  97. void main() noexcept override {
  98. auto f1_id = "1111";
  99. auto f2_id = "2222";
  100. auto db_folder_1 = db::Folder();
  101. auto db_folder_2 = db::Folder();
  102. db_folder_1.set_id(f1_id);
  103. db_folder_2.set_id(f2_id);
  104. db_folder_1.set_rescan_interval(4000);
  105. db_folder_2.set_rescan_interval(2000);
  106. auto builder = diff_builder_t(*cluster);
  107. builder.upsert_folder(db_folder_1)
  108. .upsert_folder(db_folder_2)
  109. .apply(*sup)
  110. .scan_finish(f2_id)
  111. .apply(*sup)
  112. .scan_finish(f1_id)
  113. .apply(*sup);
  114. REQUIRE(sup->timers.size() == 1);
  115. sup->do_invoke_timer((*sup->timers.begin())->request_id);
  116. sup->do_process();
  117. auto f1 = cluster->get_folders().by_id(f1_id);
  118. auto f2 = cluster->get_folders().by_id(f2_id);
  119. REQUIRE(!f1->is_scanning());
  120. REQUIRE(f2->is_scanning());
  121. auto at = r::pt::microsec_clock::local_time() + r::pt::seconds{db_folder_2.rescan_interval() + 1};
  122. builder.scan_finish(f2_id, at).apply(*sup);
  123. REQUIRE(sup->timers.size() == 1);
  124. sup->do_invoke_timer((*sup->timers.begin())->request_id);
  125. sup->do_process();
  126. REQUIRE(f1->is_scanning());
  127. REQUIRE(!f2->is_scanning());
  128. f2->set_scan_finish({});
  129. builder.scan_finish(f1_id, at).scan_request(f2_id).apply(*sup);
  130. REQUIRE(!f1->is_scanning());
  131. REQUIRE(f2->is_scanning());
  132. }
  133. };
  134. F().run();
  135. };
  136. int _init() {
  137. REGISTER_TEST_CASE(test_1_folder, "test_1_folder", "[fs]");
  138. REGISTER_TEST_CASE(test_2_folders, "test_2_folders", "[fs]");
  139. return 1;
  140. }
  141. static int v = _init();