075-controller.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. #include "catch.hpp"
  2. #include "test-utils.h"
  3. #include "access.h"
  4. #include "test_supervisor.h"
  5. #include "model/cluster.h"
  6. #include "model/diff/aggregate.h"
  7. #include "model/diff/modify/create_folder.h"
  8. #include "model/diff/modify/share_folder.h"
  9. #include "hasher/hasher_proxy_actor.h"
  10. #include "hasher/hasher_actor.h"
  11. #include "net/controller_actor.h"
  12. #include "net/names.h"
  13. #include "utils/error_code.h"
  14. using namespace syncspirit;
  15. using namespace syncspirit::test;
  16. using namespace syncspirit::model;
  17. using namespace syncspirit::net;
  18. using namespace syncspirit::hasher;
  19. namespace {
  20. struct sample_peer_config_t : public r::actor_config_t {
  21. model::device_id_t peer_device_id;
  22. };
  23. template <typename Actor> struct sample_peer_config_builder_t : r::actor_config_builder_t<Actor> {
  24. using builder_t = typename Actor::template config_builder_t<Actor>;
  25. using parent_t = r::actor_config_builder_t<Actor>;
  26. using parent_t::parent_t;
  27. builder_t &&peer_device_id(const model::device_id_t &value) &&noexcept {
  28. parent_t::config.peer_device_id = value;
  29. return std::move(*static_cast<typename parent_t::builder_t *>(this));
  30. }
  31. };
  32. struct sample_peer_t : r::actor_base_t {
  33. using config_t = sample_peer_config_t;
  34. template <typename Actor> using config_builder_t = sample_peer_config_builder_t<Actor>;
  35. using remote_message_t = r::intrusive_ptr_t<net::message::forwarded_message_t>;
  36. using remote_messages_t = std::list<remote_message_t>;
  37. struct block_response_t {
  38. size_t block_index;
  39. std::string data;
  40. };
  41. using block_responses_t = std::list<block_response_t>;
  42. using block_request_t = r::intrusive_ptr_t<net::message::block_request_t>;
  43. using block_requests_t = std::list<block_request_t>;
  44. sample_peer_t(config_t& config): r::actor_base_t{config}, peer_device{config.peer_device_id} {
  45. log = utils::get_logger("test.sample_peer");
  46. }
  47. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  48. r::actor_base_t::configure(plugin);
  49. plugin.with_casted<r::plugin::address_maker_plugin_t>([&](auto &p) {
  50. p.set_identity("sample_peer", false);
  51. });
  52. plugin.with_casted<r::plugin::starter_plugin_t>([&](auto &p) {
  53. p.subscribe_actor(&sample_peer_t::on_start_reading);
  54. p.subscribe_actor(&sample_peer_t::on_termination);
  55. p.subscribe_actor(&sample_peer_t::on_forward);
  56. p.subscribe_actor(&sample_peer_t::on_block_request);
  57. });
  58. }
  59. void shutdown_start() noexcept override {
  60. LOG_TRACE(log, "{}, shutdown_start", identity);
  61. if (controller) {
  62. send<net::payload::termination_t>(controller, shutdown_reason);
  63. }
  64. r::actor_base_t::shutdown_start();
  65. }
  66. void shutdown_finish() noexcept override {
  67. r::actor_base_t::shutdown_finish();
  68. LOG_TRACE(log, "{}, shutdown_finish, blocks requested = {}", identity, blocks_requested);
  69. if (controller) {
  70. send<net::payload::termination_t>(controller, shutdown_reason);
  71. }
  72. }
  73. void on_start_reading(net::message::start_reading_t &msg) noexcept {
  74. LOG_TRACE(log, "{}, on_start_reading", identity);
  75. controller = msg.payload.controller;
  76. reading = msg.payload.start;
  77. }
  78. void on_termination(net::message::termination_signal_t &msg) noexcept {
  79. LOG_TRACE(log, "{}, on_termination", identity);
  80. if (!shutdown_reason) {
  81. auto& ee = msg.payload.ee;
  82. auto reason = ee->message();
  83. LOG_TRACE(log, "{}, on_termination: {}", identity, reason);
  84. do_shutdown(ee);
  85. }
  86. }
  87. void on_forward(net::message::forwarded_message_t &message) noexcept {
  88. LOG_TRACE(log, "{}, on_forward", identity);
  89. messages.emplace_back(&message);
  90. }
  91. void on_block_request(net::message::block_request_t &req) noexcept {
  92. block_requests.push_front(&req);
  93. ++blocks_requested;
  94. log->debug("{}, requesting block # {}", identity, block_requests.front()->payload.request_payload.block.block_index());
  95. if (block_responses.size()) {
  96. log->debug("{}, top response block # {}", identity, block_responses.front().block_index);
  97. }
  98. auto condition = [&]() -> bool {
  99. return block_requests.size() && block_responses.size() &&
  100. block_requests.front()->payload.request_payload.block.block_index() == block_responses.front().block_index;
  101. };
  102. while (condition()) {
  103. log->debug("{}, matched replying...", identity);
  104. reply_to(*block_requests.front(), block_responses.front().data);
  105. block_responses.pop_front();
  106. block_requests.pop_front();
  107. }
  108. }
  109. void forward(net::payload::forwarded_message_t payload) noexcept {
  110. send<net::payload::forwarded_message_t>(controller, std::move(payload));
  111. }
  112. static const constexpr size_t next_block = 1000000;
  113. void push_block(std::string_view data, size_t index) {
  114. if (index == next_block) {
  115. index = block_responses.size();
  116. }
  117. block_responses.push_back(block_response_t{index, std::string(data)});
  118. }
  119. size_t blocks_requested = 0;
  120. bool reading = false;
  121. remote_messages_t messages;
  122. r::address_ptr_t controller;
  123. model::device_id_t peer_device;
  124. utils::logger_t log;
  125. block_requests_t block_requests;
  126. block_responses_t block_responses;
  127. };
  128. struct fixture_t {
  129. using peer_ptr_t = r::intrusive_ptr_t<sample_peer_t>;
  130. using target_ptr_t = r::intrusive_ptr_t<net::controller_actor_t>;
  131. fixture_t(bool auto_start_) noexcept: auto_start{auto_start_} {
  132. utils::set_default("trace");
  133. }
  134. virtual void run() noexcept {
  135. auto peer_id = device_id_t::from_string("VUV42CZ-IQD5A37-RPEBPM4-VVQK6E4-6WSKC7B-PVJQHHD-4PZD44V-ENC6WAZ").value();
  136. peer_device = device_t::create(peer_id, "peer-device").value();
  137. auto my_id = device_id_t::from_string("KHQNO2S-5QSILRK-YX4JZZ4-7L77APM-QNVGZJT-EKU7IFI-PNEPBMY-4MXFMQD").value();
  138. my_device = device_t::create(my_id, "my-device").value();
  139. cluster = new cluster_t(my_device, 1);
  140. cluster->get_devices().put(my_device);
  141. cluster->get_devices().put(peer_device);
  142. db::Folder db_folder_1;
  143. db_folder_1.set_id("1234-5678");
  144. db_folder_1.set_label("my-f1");
  145. db::Folder db_folder_2;
  146. db_folder_2.set_id("5555");
  147. db_folder_2.set_label("my-f2");
  148. auto diffs = diff::aggregate_t::diffs_t{};
  149. diffs.push_back(new diff::modify::create_folder_t(db_folder_1));
  150. diffs.push_back(new diff::modify::create_folder_t(db_folder_2));
  151. diffs.push_back(new diff::modify::share_folder_t(peer_id.get_sha256(), db_folder_1.id(), 123ul));
  152. auto diff = diff::cluster_diff_ptr_t(new diff::aggregate_t(std::move(diffs)));
  153. REQUIRE(diff->apply(*cluster));
  154. auto& folders = cluster->get_folders();
  155. folder_1 = folders.by_id(db_folder_1.id());
  156. folder_2 = folders.by_id(db_folder_2.id());
  157. r::system_context_t ctx;
  158. sup = ctx.create_supervisor<supervisor_t>().timeout(timeout).create_registry().finish();
  159. sup->cluster = cluster;
  160. sup->start();
  161. sup->do_process();
  162. CHECK(static_cast<r::actor_base_t*>(sup.get())->access<to::state>() == r::state_t::OPERATIONAL);
  163. sup->create_actor<hasher_actor_t>().index(1).timeout(timeout).finish();
  164. sup->create_actor<hasher::hasher_proxy_actor_t>()
  165. .timeout(timeout)
  166. .hasher_threads(1)
  167. .name(net::names::hasher_proxy)
  168. .finish();
  169. peer_actor = sup->create_actor<sample_peer_t>()
  170. .timeout(timeout)
  171. .finish();
  172. sup->do_process();
  173. target = sup->create_actor<controller_actor_t>()
  174. .peer(peer_device)
  175. .peer_addr(peer_actor->get_address())
  176. .request_pool(1024)
  177. .cluster(cluster)
  178. .timeout(timeout)
  179. .request_timeout(timeout)
  180. .finish();
  181. sup->do_process();
  182. CHECK(static_cast<r::actor_base_t*>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  183. target_addr = target->get_address();
  184. if (auto_start) {
  185. REQUIRE(peer_actor->reading);
  186. REQUIRE(peer_actor->messages.size() == 1);
  187. auto& msg = (*peer_actor->messages.front()).payload;
  188. REQUIRE(std::get_if<proto::message::ClusterConfig>(&msg));
  189. peer_actor->messages.pop_front();
  190. }
  191. main();
  192. sup->shutdown();
  193. sup->do_process();
  194. CHECK(static_cast<r::actor_base_t*>(sup.get())->access<to::state>() == r::state_t::SHUT_DOWN);
  195. }
  196. virtual void main() noexcept {
  197. }
  198. bool auto_start;
  199. peer_ptr_t peer_actor;
  200. target_ptr_t target;
  201. r::address_ptr_t target_addr;
  202. r::pt::time_duration timeout = r::pt::millisec{10};
  203. cluster_ptr_t cluster;
  204. device_ptr_t peer_device;
  205. device_ptr_t my_device;
  206. r::intrusive_ptr_t<supervisor_t> sup;
  207. r::system_context_t ctx;
  208. model::folder_ptr_t folder_1;
  209. model::folder_ptr_t folder_2;
  210. };
  211. }
  212. void test_startup() {
  213. struct F : fixture_t {
  214. using fixture_t::fixture_t;
  215. void main() noexcept override {
  216. REQUIRE(peer_actor->reading);
  217. REQUIRE(peer_actor->messages.size() == 1);
  218. auto& msg = (*peer_actor->messages.front()).payload;
  219. CHECK(std::get_if<proto::message::ClusterConfig>(&msg));
  220. auto cc = proto::ClusterConfig{};
  221. auto payload = proto::message::ClusterConfig(new proto::ClusterConfig(cc));
  222. peer_actor->forward(std::move(payload));
  223. sup->do_process();
  224. CHECK(static_cast<r::actor_base_t*>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  225. }
  226. };
  227. F(false).run();
  228. }
  229. void test_index() {
  230. struct F : fixture_t {
  231. using fixture_t::fixture_t;
  232. void main() noexcept override {
  233. auto cc = proto::ClusterConfig{};
  234. auto index = proto::Index{};
  235. SECTION("wrong index") {
  236. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  237. index.set_folder("non-existing-folder");
  238. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  239. sup->do_process();
  240. CHECK(static_cast<r::actor_base_t*>(target.get())->access<to::state>() == r::state_t::SHUT_DOWN);
  241. CHECK(static_cast<r::actor_base_t*>(peer_actor.get())->access<to::state>() == r::state_t::SHUT_DOWN);
  242. }
  243. SECTION("index is applied") {
  244. auto folder = cc.add_folders();
  245. folder->set_id(std::string(folder_1->get_id()));
  246. auto d_peer = folder->add_devices();
  247. d_peer->set_id(std::string(peer_device->device_id().get_sha256()));
  248. d_peer->set_max_sequence(1ul);
  249. d_peer->set_index_id(123ul);
  250. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  251. index.set_folder(std::string(folder_1->get_id()));
  252. auto file = index.add_files();
  253. file->set_name("some-dir");
  254. file->set_type(proto::FileInfoType::DIRECTORY);
  255. file->set_sequence(1ul);
  256. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  257. sup->do_process();
  258. CHECK(static_cast<r::actor_base_t*>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  259. CHECK(static_cast<r::actor_base_t*>(peer_actor.get())->access<to::state>() == r::state_t::OPERATIONAL);
  260. auto& folder_infos = folder_1->get_folder_infos();
  261. auto folder_peer = folder_infos.by_device(peer_device);
  262. REQUIRE(folder_peer);
  263. CHECK(folder_peer->get_max_sequence() == 1ul);
  264. REQUIRE(folder_peer->get_file_infos().size() == 1);
  265. CHECK(folder_peer->get_file_infos().begin()->item->get_name() == file->name());
  266. auto folder_my = folder_infos.by_device(my_device);
  267. REQUIRE(folder_my);
  268. CHECK(folder_my->get_max_sequence() == 1ul);
  269. REQUIRE(folder_my->get_file_infos().size() == 1);
  270. CHECK(folder_my->get_file_infos().begin()->item->get_name() == file->name());
  271. SECTION("then index update is applied") {
  272. auto index_update = proto::IndexUpdate{};
  273. index_update.set_folder(std::string(folder_1->get_id()));
  274. auto file = index_update.add_files();
  275. file->set_name("some-dir-2");
  276. file->set_type(proto::FileInfoType::DIRECTORY);
  277. file->set_sequence(3ul);
  278. peer_actor->forward(proto::message::IndexUpdate(new proto::IndexUpdate(index_update)));
  279. sup->do_process();
  280. CHECK(static_cast<r::actor_base_t*>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  281. CHECK(static_cast<r::actor_base_t*>(peer_actor.get())->access<to::state>() == r::state_t::OPERATIONAL);
  282. CHECK(folder_peer->get_max_sequence() == 3ul);
  283. REQUIRE(folder_peer->get_file_infos().size() == 2);
  284. CHECK(folder_peer->get_file_infos().by_name("some-dir-2"));
  285. CHECK(folder_my->get_max_sequence() == 2ul);
  286. REQUIRE(folder_my->get_file_infos().size() == 2);
  287. CHECK(folder_my->get_file_infos().by_name("some-dir-2"));
  288. }
  289. }
  290. }
  291. };
  292. F(true).run();
  293. }
  294. void test_downloading() {
  295. struct F : fixture_t {
  296. using fixture_t::fixture_t;
  297. void main() noexcept override {
  298. auto& folder_infos = folder_1->get_folder_infos();
  299. auto folder_my = folder_infos.by_device(my_device);
  300. auto cc = proto::ClusterConfig{};
  301. auto folder = cc.add_folders();
  302. folder->set_id(std::string(folder_1->get_id()));
  303. auto d_peer = folder->add_devices();
  304. d_peer->set_id(std::string(peer_device->device_id().get_sha256()));
  305. SECTION("cluster config & index has a new file => download it") {
  306. d_peer->set_max_sequence(1ul);
  307. d_peer->set_index_id(123ul);
  308. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  309. auto index = proto::Index{};
  310. index.set_folder(std::string(folder_1->get_id()));
  311. auto file = index.add_files();
  312. file->set_name("some-file");
  313. file->set_type(proto::FileInfoType::FILE);
  314. file->set_sequence(1ul);
  315. file->set_block_size(5);
  316. file->set_size(5);
  317. auto version = file->mutable_version();
  318. auto counter = version->add_counters();
  319. counter->set_id(1ul);
  320. counter->set_value(1ul);
  321. auto b1 = file->add_blocks();
  322. b1->set_hash(utils::sha256_digest("12345").value());
  323. b1->set_offset(0);
  324. b1->set_size(5);
  325. auto folder_my = folder_infos.by_device(my_device);
  326. CHECK(folder_my->get_max_sequence() == 0ul);
  327. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  328. peer_actor->push_block("12345", 0);
  329. sup->do_process();
  330. REQUIRE(folder_my);
  331. CHECK(folder_my->get_max_sequence() == 1ul);
  332. REQUIRE(folder_my->get_file_infos().size() == 1);
  333. auto f = folder_my->get_file_infos().begin()->item;
  334. REQUIRE(f);
  335. CHECK(f->get_name() == file->name());
  336. CHECK(f->get_size() == 5);
  337. CHECK(f->get_blocks().size() == 1);
  338. CHECK(f->is_locally_available());
  339. CHECK(!f->is_locked());
  340. CHECK(peer_actor->blocks_requested == 1);
  341. SECTION("dont redownload file only if metadata has changed") {
  342. auto index_update = proto::IndexUpdate{};
  343. index_update.set_folder(index.folder());
  344. file->set_sequence(2ul);
  345. counter->set_value(2ul);
  346. *index_update.add_files() = *file;
  347. peer_actor->forward(proto::message::IndexUpdate(new proto::IndexUpdate(index_update)));
  348. sup->do_process();
  349. CHECK(peer_actor->blocks_requested == 1);
  350. CHECK(folder_my->get_max_sequence() == 2ul);
  351. f = folder_my->get_file_infos().begin()->item;
  352. CHECK(f->is_locally_available());
  353. CHECK(f->get_sequence() == 2ul);
  354. }
  355. }
  356. SECTION("cluster config is the same, but there are non-downloaded files") {
  357. auto folder_peer = folder_infos.by_device(peer_device);
  358. CHECK(folder_peer->get_max_sequence() == 0ul);
  359. auto pr_fi = proto::FileInfo{};
  360. pr_fi.set_name("some-file");
  361. pr_fi.set_type(proto::FileInfoType::FILE);
  362. pr_fi.set_sequence(1ul);
  363. pr_fi.set_block_size(5);
  364. pr_fi.set_size(5);
  365. auto version = pr_fi.mutable_version();
  366. auto counter = version->add_counters();
  367. counter->set_id(1);
  368. counter->set_value(peer_device->as_uint());
  369. auto b1 = pr_fi.add_blocks();
  370. b1->set_hash(utils::sha256_digest("12345").value());
  371. b1->set_offset(0);
  372. b1->set_size(5);
  373. auto b = model::block_info_t::create(*b1).value();
  374. auto file_info = model::file_info_t::create(cluster->next_uuid(), pr_fi, folder_peer).value();
  375. file_info->assign_block(b, 0);
  376. folder_peer->add(file_info);
  377. folder_peer->set_max_sequence(1ul);
  378. d_peer->set_max_sequence(1ul);
  379. d_peer->set_index_id(123ul);
  380. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  381. peer_actor->push_block("12345", 0);
  382. sup->do_process();
  383. CHECK(folder_my->get_max_sequence() == 1ul);
  384. REQUIRE(folder_my->get_file_infos().size() == 1);
  385. auto f = folder_my->get_file_infos().begin()->item;
  386. REQUIRE(f);
  387. CHECK(f->get_name() == pr_fi.name());
  388. CHECK(f->get_size() == 5);
  389. CHECK(f->get_blocks().size() == 1);
  390. CHECK(f->is_locally_available());
  391. CHECK(!f->is_locked());
  392. }
  393. SECTION("don't attempt to download a file, which is deleted") {
  394. auto folder_peer = folder_infos.by_device(peer_device);
  395. CHECK(folder_peer->get_max_sequence() == 0ul);
  396. auto pr_fi = proto::FileInfo{};
  397. pr_fi.set_name("some-file");
  398. pr_fi.set_type(proto::FileInfoType::FILE);
  399. pr_fi.set_sequence(1ul);
  400. pr_fi.set_block_size(5);
  401. pr_fi.set_size(5);
  402. auto b1 = pr_fi.add_blocks();
  403. b1->set_hash(utils::sha256_digest("12345").value());
  404. b1->set_offset(0);
  405. b1->set_size(5);
  406. auto b = model::block_info_t::create(*b1).value();
  407. auto file_info = model::file_info_t::create(cluster->next_uuid(), pr_fi, folder_peer).value();
  408. file_info->assign_block(b, 0);
  409. folder_peer->add(file_info);
  410. folder_peer->set_max_sequence(1ul);
  411. d_peer->set_max_sequence(2ul);
  412. d_peer->set_index_id(123ul);
  413. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  414. auto index = proto::Index{};
  415. index.set_folder(std::string(folder_1->get_id()));
  416. auto file = index.add_files();
  417. file->set_name("some-file");
  418. file->set_type(proto::FileInfoType::FILE);
  419. file->set_deleted(true);
  420. file->set_sequence(2ul);
  421. file->set_block_size(0);
  422. file->set_size(0);
  423. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  424. sup->do_process();
  425. CHECK(folder_my->get_max_sequence() == 1ul);
  426. REQUIRE(folder_my->get_file_infos().size() == 1);
  427. auto f = folder_my->get_file_infos().begin()->item;
  428. REQUIRE(f);
  429. CHECK(f->get_name() == pr_fi.name());
  430. CHECK(f->get_size() == 0);
  431. CHECK(f->get_blocks().size() == 0);
  432. CHECK(f->is_locally_available());
  433. CHECK(f->is_deleted());
  434. CHECK(!f->is_locked());
  435. CHECK(f->get_sequence() == 1ul);
  436. CHECK(peer_actor->blocks_requested == 0);
  437. }
  438. SECTION("new file via index_update => download it") {
  439. d_peer->set_index_id(123ul);
  440. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  441. auto index = proto::Index{};
  442. index.set_folder(std::string(folder_1->get_id()));
  443. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  444. auto index_update = proto::IndexUpdate{};
  445. index_update.set_folder(std::string(folder_1->get_id()));
  446. auto file = index_update.add_files();
  447. file->set_name("some-file");
  448. file->set_type(proto::FileInfoType::FILE);
  449. file->set_sequence(1ul);
  450. file->set_block_size(5);
  451. file->set_size(5);
  452. auto version = file->mutable_version();
  453. auto counter = version->add_counters();
  454. counter->set_id(1);
  455. counter->set_value(peer_device->as_uint());
  456. auto b1 = file->add_blocks();
  457. b1->set_hash(utils::sha256_digest("12345").value());
  458. b1->set_offset(0);
  459. b1->set_size(5);
  460. peer_actor->forward(proto::message::IndexUpdate(new proto::IndexUpdate(index_update)));
  461. peer_actor->push_block("12345", 0);
  462. sup->do_process();
  463. auto folder_my = folder_infos.by_device(my_device);
  464. CHECK(folder_my->get_max_sequence() == 1ul);
  465. REQUIRE(folder_my->get_file_infos().size() == 1);
  466. auto f = folder_my->get_file_infos().begin()->item;
  467. REQUIRE(f);
  468. CHECK(f->get_name() == file->name());
  469. CHECK(f->get_size() == 5);
  470. CHECK(f->get_blocks().size() == 1);
  471. CHECK(f->is_locally_available());
  472. CHECK(!f->is_locked());
  473. }
  474. SECTION("deleted file, has been restored => download it") {
  475. auto index = proto::Index{};
  476. index.set_folder(std::string(folder_1->get_id()));
  477. auto file_1 = index.add_files();
  478. file_1->set_name("some-file");
  479. file_1->set_type(proto::FileInfoType::FILE);
  480. file_1->set_sequence(2ul);
  481. file_1->set_deleted(true);
  482. auto v1 = file_1->mutable_version();
  483. auto c1 = v1->add_counters();
  484. c1->set_id(1u);
  485. c1->set_value(1u);
  486. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  487. sup->do_process();
  488. auto folder_my = folder_infos.by_device(my_device);
  489. CHECK(folder_my->get_max_sequence() == 1ul);
  490. auto index_update = proto::IndexUpdate{};
  491. index_update.set_folder(std::string(folder_1->get_id()));
  492. auto file_2 = index_update.add_files();
  493. file_2->set_name("some-file");
  494. file_2->set_type(proto::FileInfoType::FILE);
  495. file_2->set_sequence(3ul);
  496. file_2->set_block_size(128 * 1024);
  497. file_2->set_size(5);
  498. auto v2 = file_2->mutable_version();
  499. auto c2 = v2->add_counters();
  500. c2->set_id(1u);
  501. c2->set_value(2u);
  502. auto b1 = file_2->add_blocks();
  503. b1->set_hash(utils::sha256_digest("12345").value());
  504. b1->set_offset(0);
  505. b1->set_size(5);
  506. peer_actor->forward(proto::message::IndexUpdate(new proto::IndexUpdate(index_update)));
  507. peer_actor->push_block("12345", 0);
  508. sup->do_process();
  509. REQUIRE(folder_my->get_file_infos().size() == 1);
  510. auto f = folder_my->get_file_infos().begin()->item;
  511. REQUIRE(f);
  512. CHECK(f->get_name() == file_1->name());
  513. CHECK(f->get_size() == 5);
  514. CHECK(f->get_blocks().size() == 1);
  515. CHECK(f->is_locally_available());
  516. CHECK(!f->is_locked());
  517. }
  518. }
  519. };
  520. F(true).run();
  521. }
  522. REGISTER_TEST_CASE(test_startup, "test_startup", "[net]");
  523. REGISTER_TEST_CASE(test_index, "test_index", "[net]");
  524. REGISTER_TEST_CASE(test_downloading, "test_downloading", "[net]");