075-controller.cpp 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121
  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 "model/cluster.h"
  7. #include "diff-builder.h"
  8. #include "hasher/hasher_proxy_actor.h"
  9. #include "hasher/hasher_actor.h"
  10. #include "net/controller_actor.h"
  11. #include "net/names.h"
  12. #include "fs/messages.h"
  13. #include "utils/error_code.h"
  14. #include "proto/bep_support.h"
  15. #include <boost/core/demangle.hpp>
  16. using namespace syncspirit;
  17. using namespace syncspirit::test;
  18. using namespace syncspirit::model;
  19. using namespace syncspirit::net;
  20. using namespace syncspirit::hasher;
  21. namespace {
  22. struct sample_peer_config_t : public r::actor_config_t {
  23. model::device_id_t peer_device_id;
  24. };
  25. template <typename Actor> struct sample_peer_config_builder_t : r::actor_config_builder_t<Actor> {
  26. using builder_t = typename Actor::template config_builder_t<Actor>;
  27. using parent_t = r::actor_config_builder_t<Actor>;
  28. using parent_t::parent_t;
  29. builder_t &&peer_device_id(const model::device_id_t &value) && noexcept {
  30. parent_t::config.peer_device_id = value;
  31. return std::move(*static_cast<typename parent_t::builder_t *>(this));
  32. }
  33. };
  34. struct sample_peer_t : r::actor_base_t {
  35. using config_t = sample_peer_config_t;
  36. template <typename Actor> using config_builder_t = sample_peer_config_builder_t<Actor>;
  37. using remote_message_t = r::intrusive_ptr_t<net::message::forwarded_message_t>;
  38. using remote_messages_t = std::list<remote_message_t>;
  39. struct block_response_t {
  40. size_t block_index;
  41. std::string data;
  42. sys::error_code ec;
  43. };
  44. using block_responses_t = std::list<block_response_t>;
  45. using block_request_t = r::intrusive_ptr_t<net::message::block_request_t>;
  46. using block_requests_t = std::list<block_request_t>;
  47. using uploaded_blocks_t = std::list<proto::message::Response>;
  48. sample_peer_t(config_t &config) : r::actor_base_t{config}, peer_device{config.peer_device_id} {
  49. log = utils::get_logger("test.sample_peer");
  50. }
  51. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  52. r::actor_base_t::configure(plugin);
  53. plugin.with_casted<r::plugin::address_maker_plugin_t>([&](auto &p) { p.set_identity("sample_peer", false); });
  54. plugin.with_casted<r::plugin::starter_plugin_t>([&](auto &p) {
  55. p.subscribe_actor(&sample_peer_t::on_start_reading);
  56. p.subscribe_actor(&sample_peer_t::on_termination);
  57. p.subscribe_actor(&sample_peer_t::on_transfer);
  58. p.subscribe_actor(&sample_peer_t::on_block_request);
  59. });
  60. }
  61. void shutdown_start() noexcept override {
  62. LOG_TRACE(log, "{}, shutdown_start", identity);
  63. if (controller) {
  64. send<net::payload::termination_t>(controller, shutdown_reason);
  65. }
  66. r::actor_base_t::shutdown_start();
  67. }
  68. void shutdown_finish() noexcept override {
  69. r::actor_base_t::shutdown_finish();
  70. LOG_TRACE(log, "{}, shutdown_finish, blocks requested = {}", identity, blocks_requested);
  71. if (controller) {
  72. send<net::payload::termination_t>(controller, shutdown_reason);
  73. }
  74. }
  75. void on_start_reading(net::message::start_reading_t &msg) noexcept {
  76. LOG_TRACE(log, "{}, on_start_reading", identity);
  77. controller = msg.payload.controller;
  78. reading = msg.payload.start;
  79. }
  80. void on_termination(net::message::termination_signal_t &msg) noexcept {
  81. LOG_TRACE(log, "{}, on_termination", identity);
  82. if (!shutdown_reason) {
  83. auto &ee = msg.payload.ee;
  84. auto reason = ee->message();
  85. LOG_TRACE(log, "{}, on_termination: {}", identity, reason);
  86. do_shutdown(ee);
  87. }
  88. }
  89. void on_transfer(net::message::transfer_data_t &message) noexcept {
  90. auto &data = message.payload.data;
  91. LOG_TRACE(log, "{}, on_transfer, bytes = {}", identity, data.size());
  92. auto buff = boost::asio::buffer(data.data(), data.size());
  93. auto result = proto::parse_bep(buff);
  94. auto orig = std::move(result.value().message);
  95. auto variant = net::payload::forwarded_message_t();
  96. std::visit(
  97. [&](auto &msg) {
  98. using boost::core::demangle;
  99. using T = std::decay_t<decltype(msg)>;
  100. LOG_TRACE(log, "{}, received '{}' message", identity, demangle(typeid(T).name()));
  101. using V = net::payload::forwarded_message_t;
  102. if constexpr (std::is_constructible_v<V, T>) {
  103. variant = std::move(msg);
  104. } else if constexpr (std::is_same_v<T, proto::message::Response>) {
  105. uploaded_blocks.push_back(std::move(msg));
  106. }
  107. },
  108. orig);
  109. auto fwd_msg = new net::message::forwarded_message_t(address, std::move(variant));
  110. messages.emplace_back(fwd_msg);
  111. }
  112. void on_block_request(net::message::block_request_t &req) noexcept {
  113. block_requests.push_front(&req);
  114. ++blocks_requested;
  115. log->debug("{}, requesting block # {}", identity,
  116. block_requests.front()->payload.request_payload.block.block_index());
  117. if (block_responses.size()) {
  118. log->debug("{}, top response block # {}", identity, block_responses.front().block_index);
  119. }
  120. auto condition = [&]() -> bool {
  121. return block_requests.size() && block_responses.size() &&
  122. block_requests.front()->payload.request_payload.block.block_index() ==
  123. block_responses.front().block_index;
  124. };
  125. while (condition()) {
  126. auto &reply = block_responses.front();
  127. auto &request = *block_requests.front();
  128. log->debug("{}, matched, replying..., ec = {}", identity, reply.ec.value());
  129. if (!reply.ec) {
  130. reply_to(request, reply.data);
  131. } else {
  132. reply_with_error(request, make_error(reply.ec));
  133. }
  134. block_responses.pop_front();
  135. block_requests.pop_front();
  136. }
  137. }
  138. void forward(net::payload::forwarded_message_t payload) noexcept {
  139. send<net::payload::forwarded_message_t>(controller, std::move(payload));
  140. }
  141. static const constexpr size_t next_block = 1000000;
  142. void push_block(std::string_view data, size_t index) {
  143. if (index == next_block) {
  144. index = block_responses.size();
  145. }
  146. block_responses.push_back(block_response_t{index, std::string(data)});
  147. }
  148. void push_block(sys::error_code ec, size_t index) {
  149. if (index == next_block) {
  150. index = block_responses.size();
  151. }
  152. block_responses.push_back(block_response_t{index, std::string{}, ec});
  153. }
  154. size_t blocks_requested = 0;
  155. bool reading = false;
  156. remote_messages_t messages;
  157. r::address_ptr_t controller;
  158. model::device_id_t peer_device;
  159. utils::logger_t log;
  160. block_requests_t block_requests;
  161. block_responses_t block_responses;
  162. uploaded_blocks_t uploaded_blocks;
  163. };
  164. struct fixture_t {
  165. using peer_ptr_t = r::intrusive_ptr_t<sample_peer_t>;
  166. using target_ptr_t = r::intrusive_ptr_t<net::controller_actor_t>;
  167. using blk_req_t = fs::message::block_request_t;
  168. using blk_req_ptr_t = r::intrusive_ptr_t<blk_req_t>;
  169. using blk_res_t = fs::message::block_response_t;
  170. using blk_res_ptr_t = r::intrusive_ptr_t<blk_res_t>;
  171. using block_requests_t = std::deque<blk_req_ptr_t>;
  172. using block_responses_t = std::deque<r::message_ptr_t>;
  173. fixture_t(bool auto_start_, int64_t max_sequence_, bool auto_share_ = true) noexcept
  174. : auto_start{auto_start_}, max_sequence{max_sequence_}, auto_share{auto_share_} {
  175. utils::set_default("trace");
  176. }
  177. virtual void run() noexcept {
  178. auto peer_id =
  179. device_id_t::from_string("VUV42CZ-IQD5A37-RPEBPM4-VVQK6E4-6WSKC7B-PVJQHHD-4PZD44V-ENC6WAZ").value();
  180. peer_device = device_t::create(peer_id, "peer-device").value();
  181. auto my_id =
  182. device_id_t::from_string("KHQNO2S-5QSILRK-YX4JZZ4-7L77APM-QNVGZJT-EKU7IFI-PNEPBMY-4MXFMQD").value();
  183. my_device = device_t::create(my_id, "my-device").value();
  184. cluster = new cluster_t(my_device, 1);
  185. cluster->get_devices().put(my_device);
  186. cluster->get_devices().put(peer_device);
  187. auto folder_id_1 = "1234-5678";
  188. auto folder_id_2 = "5555";
  189. auto builder = diff_builder_t(*cluster);
  190. auto sha256 = peer_id.get_sha256();
  191. builder.upsert_folder(folder_id_1, "")
  192. .upsert_folder(folder_id_2, "")
  193. .configure_cluster(sha256)
  194. .add(sha256, folder_id_1, 123, max_sequence)
  195. .finish();
  196. REQUIRE(builder.apply());
  197. if (auto_share) {
  198. REQUIRE(builder.share_folder(peer_id.get_sha256(), folder_id_1).apply());
  199. }
  200. r::system_context_t ctx;
  201. sup = ctx.create_supervisor<supervisor_t>().timeout(timeout).create_registry().finish();
  202. sup->cluster = cluster;
  203. sup->configure_callback = [&](r::plugin::plugin_base_t &plugin) {
  204. plugin.template with_casted<r::plugin::registry_plugin_t>(
  205. [&](auto &p) { p.register_name(net::names::fs_actor, sup->get_address()); });
  206. plugin.template with_casted<r::plugin::starter_plugin_t>([&](auto &p) {
  207. p.subscribe_actor(r::lambda<blk_req_t>([&](blk_req_t &msg) {
  208. block_requests.push_back(&msg);
  209. if (block_responses.size()) {
  210. sup->put(block_responses.front());
  211. block_responses.pop_front();
  212. }
  213. }));
  214. });
  215. };
  216. sup->start();
  217. sup->do_process();
  218. CHECK(static_cast<r::actor_base_t *>(sup.get())->access<to::state>() == r::state_t::OPERATIONAL);
  219. sup->create_actor<hasher_actor_t>().index(1).timeout(timeout).finish();
  220. sup->create_actor<hasher::hasher_proxy_actor_t>()
  221. .timeout(timeout)
  222. .hasher_threads(1)
  223. .name(net::names::hasher_proxy)
  224. .finish();
  225. peer_actor = sup->create_actor<sample_peer_t>().timeout(timeout).finish();
  226. auto &folders = cluster->get_folders();
  227. folder_1 = folders.by_id(folder_id_1);
  228. folder_2 = folders.by_id(folder_id_2);
  229. folder_1_peer = folder_1->get_folder_infos().by_device_id(peer_id.get_sha256());
  230. target = sup->create_actor<controller_actor_t>()
  231. .peer(peer_device)
  232. .peer_addr(peer_actor->get_address())
  233. .request_pool(1024)
  234. .outgoing_buffer_max(1024'000)
  235. .cluster(cluster)
  236. .sequencer(sup->sequencer)
  237. .timeout(timeout)
  238. .request_timeout(timeout)
  239. .finish();
  240. sup->do_process();
  241. CHECK(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  242. target_addr = target->get_address();
  243. if (auto_start) {
  244. REQUIRE(peer_actor->reading);
  245. REQUIRE(peer_actor->messages.size() == 1);
  246. auto &msg = (*peer_actor->messages.front()).payload;
  247. REQUIRE(std::get_if<proto::message::ClusterConfig>(&msg));
  248. peer_actor->messages.pop_front();
  249. }
  250. main(builder);
  251. sup->shutdown();
  252. sup->do_process();
  253. CHECK(static_cast<r::actor_base_t *>(sup.get())->access<to::state>() == r::state_t::SHUT_DOWN);
  254. }
  255. virtual void main(diff_builder_t &) noexcept {}
  256. bool auto_start;
  257. bool auto_share;
  258. int64_t max_sequence;
  259. peer_ptr_t peer_actor;
  260. target_ptr_t target;
  261. r::address_ptr_t target_addr;
  262. r::pt::time_duration timeout = r::pt::millisec{10};
  263. cluster_ptr_t cluster;
  264. device_ptr_t peer_device;
  265. device_ptr_t my_device;
  266. r::intrusive_ptr_t<supervisor_t> sup;
  267. r::system_context_t ctx;
  268. model::folder_ptr_t folder_1;
  269. model::folder_info_ptr_t folder_1_peer;
  270. model::folder_ptr_t folder_2;
  271. block_requests_t block_requests;
  272. block_responses_t block_responses;
  273. };
  274. } // namespace
  275. void test_startup() {
  276. struct F : fixture_t {
  277. using fixture_t::fixture_t;
  278. void main(diff_builder_t &) noexcept override {
  279. REQUIRE(peer_actor->reading);
  280. REQUIRE(peer_actor->messages.size() == 1);
  281. auto &msg = (*peer_actor->messages.front()).payload;
  282. REQUIRE(std::get_if<proto::message::ClusterConfig>(&msg));
  283. peer_actor->messages.pop_front();
  284. CHECK(peer_actor->messages.empty());
  285. auto cc = proto::ClusterConfig{};
  286. auto payload = proto::message::ClusterConfig(new proto::ClusterConfig(cc));
  287. peer_actor->forward(std::move(payload));
  288. sup->do_process();
  289. CHECK(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  290. CHECK(peer_actor->messages.empty());
  291. }
  292. };
  293. F(false, 10, false).run();
  294. }
  295. void test_index_receiving() {
  296. struct F : fixture_t {
  297. using fixture_t::fixture_t;
  298. void main(diff_builder_t &) noexcept override {
  299. auto cc = proto::ClusterConfig{};
  300. auto index = proto::Index{};
  301. SECTION("wrong index") {
  302. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  303. index.set_folder("non-existing-folder");
  304. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  305. sup->do_process();
  306. CHECK(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::SHUT_DOWN);
  307. CHECK(static_cast<r::actor_base_t *>(peer_actor.get())->access<to::state>() == r::state_t::SHUT_DOWN);
  308. }
  309. SECTION("index is applied") {
  310. auto folder = cc.add_folders();
  311. folder->set_id(std::string(folder_1->get_id()));
  312. auto d_peer = folder->add_devices();
  313. d_peer->set_id(std::string(peer_device->device_id().get_sha256()));
  314. REQUIRE(cluster->get_pending_folders().size() == 0);
  315. d_peer->set_max_sequence(folder_1_peer->get_max_sequence());
  316. d_peer->set_index_id(folder_1_peer->get_index());
  317. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  318. index.set_folder(std::string(folder_1->get_id()));
  319. auto file = index.add_files();
  320. file->set_name("some-dir");
  321. file->set_type(proto::FileInfoType::DIRECTORY);
  322. file->set_sequence(folder_1_peer->get_max_sequence());
  323. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  324. sup->do_process();
  325. CHECK(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  326. CHECK(static_cast<r::actor_base_t *>(peer_actor.get())->access<to::state>() == r::state_t::OPERATIONAL);
  327. auto &folder_infos = folder_1->get_folder_infos();
  328. auto folder_peer = folder_infos.by_device(*peer_device);
  329. REQUIRE(folder_peer);
  330. CHECK(folder_peer->get_max_sequence() == 10ul);
  331. REQUIRE(folder_peer->get_file_infos().size() == 1);
  332. CHECK(folder_peer->get_file_infos().begin()->item->get_name() == file->name());
  333. auto folder_my = folder_infos.by_device(*my_device);
  334. REQUIRE(folder_my);
  335. CHECK(folder_my->get_max_sequence() == 1ul);
  336. REQUIRE(folder_my->get_file_infos().size() == 1);
  337. CHECK(folder_my->get_file_infos().begin()->item->get_name() == file->name());
  338. SECTION("then index update is applied") {
  339. auto index_update = proto::IndexUpdate{};
  340. index_update.set_folder(std::string(folder_1->get_id()));
  341. auto file = index_update.add_files();
  342. file->set_name("some-dir-2");
  343. file->set_type(proto::FileInfoType::DIRECTORY);
  344. file->set_sequence(folder_1_peer->get_max_sequence() + 1);
  345. peer_actor->forward(proto::message::IndexUpdate(new proto::IndexUpdate(index_update)));
  346. sup->do_process();
  347. CHECK(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  348. CHECK(static_cast<r::actor_base_t *>(peer_actor.get())->access<to::state>() ==
  349. r::state_t::OPERATIONAL);
  350. CHECK(folder_peer->get_max_sequence() == file->sequence());
  351. REQUIRE(folder_peer->get_file_infos().size() == 2);
  352. CHECK(folder_peer->get_file_infos().by_name("some-dir-2"));
  353. CHECK(folder_my->get_max_sequence() == 2ul);
  354. REQUIRE(folder_my->get_file_infos().size() == 2);
  355. CHECK(folder_my->get_file_infos().by_name("some-dir-2"));
  356. }
  357. }
  358. }
  359. };
  360. F(true, 10).run();
  361. }
  362. void test_index_sending() {
  363. struct F : fixture_t {
  364. using fixture_t::fixture_t;
  365. void main(diff_builder_t &) noexcept override {
  366. proto::FileInfo pr_file_info;
  367. pr_file_info.set_name("link");
  368. pr_file_info.set_type(proto::FileInfoType::SYMLINK);
  369. pr_file_info.set_symlink_target("/some/where");
  370. auto builder = diff_builder_t(*cluster);
  371. builder.local_update(folder_1->get_id(), pr_file_info);
  372. builder.apply(*sup);
  373. auto folder_1_my = folder_1->get_folder_infos().by_device(*my_device);
  374. auto cc = proto::ClusterConfig{};
  375. auto folder = cc.add_folders();
  376. folder->set_id(std::string(folder_1->get_id()));
  377. auto d_peer = folder->add_devices();
  378. d_peer->set_id(std::string(peer_device->device_id().get_sha256()));
  379. d_peer->set_max_sequence(folder_1_peer->get_max_sequence());
  380. d_peer->set_index_id(folder_1_peer->get_index());
  381. SECTION("peer has outdated by sequence view") {
  382. auto d_my = folder->add_devices();
  383. d_my->set_id(std::string(my_device->device_id().get_sha256()));
  384. d_my->set_max_sequence(folder_1_my->get_max_sequence() - 1);
  385. d_my->set_index_id(folder_1_my->get_index());
  386. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  387. sup->do_process();
  388. auto &queue = peer_actor->messages;
  389. REQUIRE(queue.size() == 2);
  390. auto msg = &(*queue.front()).payload;
  391. auto &my_index = *std::get<proto::message::Index>(*msg);
  392. REQUIRE(my_index.files_size() == 0);
  393. queue.pop_front();
  394. msg = &(*queue.front()).payload;
  395. auto &my_index_update = *std::get<proto::message::IndexUpdate>(*msg);
  396. REQUIRE(my_index_update.files_size() == 1);
  397. }
  398. SECTION("peer has outdated by index view") {
  399. auto d_my = folder->add_devices();
  400. d_my->set_id(std::string(my_device->device_id().get_sha256()));
  401. d_my->set_max_sequence(folder_1_my->get_max_sequence());
  402. d_my->set_index_id(folder_1_my->get_index() + 5);
  403. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  404. sup->do_process();
  405. auto &queue = peer_actor->messages;
  406. REQUIRE(queue.size() == 2);
  407. auto msg = &(*queue.front()).payload;
  408. auto &my_index = *std::get<proto::message::Index>(*msg);
  409. REQUIRE(my_index.files_size() == 0);
  410. queue.pop_front();
  411. msg = &(*queue.front()).payload;
  412. auto &my_index_update = *std::get<proto::message::IndexUpdate>(*msg);
  413. REQUIRE(my_index_update.files_size() == 1);
  414. }
  415. SECTION("peer has actual view") {
  416. auto d_my = folder->add_devices();
  417. d_my->set_id(std::string(my_device->device_id().get_sha256()));
  418. d_my->set_max_sequence(folder_1_my->get_max_sequence());
  419. d_my->set_index_id(folder_1_my->get_index());
  420. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  421. sup->do_process();
  422. auto &queue = peer_actor->messages;
  423. REQUIRE(queue.size() == 0);
  424. }
  425. }
  426. };
  427. F(true, 10).run();
  428. }
  429. void test_downloading() {
  430. struct F : fixture_t {
  431. using fixture_t::fixture_t;
  432. void main(diff_builder_t &) noexcept override {
  433. auto &folder_infos = folder_1->get_folder_infos();
  434. auto folder_my = folder_infos.by_device(*my_device);
  435. auto cc = proto::ClusterConfig{};
  436. auto folder = cc.add_folders();
  437. folder->set_id(std::string(folder_1->get_id()));
  438. auto d_peer = folder->add_devices();
  439. d_peer->set_id(std::string(peer_device->device_id().get_sha256()));
  440. d_peer->set_max_sequence(folder_1_peer->get_max_sequence());
  441. d_peer->set_index_id(folder_1_peer->get_index());
  442. auto d_my = folder->add_devices();
  443. d_my->set_id(std::string(my_device->device_id().get_sha256()));
  444. d_my->set_max_sequence(folder_my->get_max_sequence());
  445. d_my->set_index_id(folder_my->get_index());
  446. SECTION("cluster config & index has a new file => download it") {
  447. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  448. auto index = proto::Index{};
  449. index.set_folder(std::string(folder_1->get_id()));
  450. auto file = index.add_files();
  451. file->set_name("some-file");
  452. file->set_type(proto::FileInfoType::FILE);
  453. file->set_sequence(folder_1_peer->get_max_sequence());
  454. file->set_block_size(5);
  455. file->set_size(5);
  456. auto version = file->mutable_version();
  457. auto counter = version->add_counters();
  458. counter->set_id(1ul);
  459. counter->set_value(1ul);
  460. auto b1 = file->add_blocks();
  461. b1->set_hash(utils::sha256_digest("12345").value());
  462. b1->set_offset(0);
  463. b1->set_size(5);
  464. auto folder_my = folder_infos.by_device(*my_device);
  465. CHECK(folder_my->get_max_sequence() == 0ul);
  466. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  467. peer_actor->push_block("12345", 0);
  468. sup->do_process();
  469. REQUIRE(folder_my);
  470. CHECK(folder_my->get_max_sequence() == 1ul);
  471. REQUIRE(folder_my->get_file_infos().size() == 1);
  472. auto f = folder_my->get_file_infos().begin()->item;
  473. REQUIRE(f);
  474. CHECK(f->get_name() == file->name());
  475. CHECK(f->get_size() == 5);
  476. CHECK(f->get_blocks().size() == 1);
  477. CHECK(f->is_locally_available());
  478. CHECK(!f->is_locked());
  479. CHECK(peer_actor->blocks_requested == 1);
  480. auto &queue = peer_actor->messages;
  481. REQUIRE(queue.size() > 0);
  482. auto msg = &(*queue.front()).payload;
  483. auto &my_index = *std::get<proto::message::Index>(*msg);
  484. REQUIRE(my_index.files_size() == 0);
  485. queue.pop_front();
  486. msg = &(*queue.back()).payload;
  487. auto &my_index_update = *std::get<proto::message::IndexUpdate>(*msg);
  488. REQUIRE(my_index_update.files_size() == 1);
  489. SECTION("dont redownload file only if metadata has changed") {
  490. auto index_update = proto::IndexUpdate{};
  491. index_update.set_folder(index.folder());
  492. file->set_sequence(folder_1_peer->get_max_sequence() + 1);
  493. counter->set_value(2ul);
  494. *index_update.add_files() = *file;
  495. peer_actor->forward(proto::message::IndexUpdate(new proto::IndexUpdate(index_update)));
  496. sup->do_process();
  497. CHECK(peer_actor->blocks_requested == 1);
  498. CHECK(folder_my->get_max_sequence() == 2ul);
  499. f = folder_my->get_file_infos().begin()->item;
  500. CHECK(f->is_locally_available());
  501. CHECK(f->get_sequence() == 2ul);
  502. }
  503. }
  504. SECTION("cluster config is the same, but there are non-downloaded files") {
  505. auto folder_peer = folder_infos.by_device(*peer_device);
  506. auto pr_fi = proto::FileInfo{};
  507. pr_fi.set_name("some-file");
  508. pr_fi.set_type(proto::FileInfoType::FILE);
  509. pr_fi.set_sequence(folder_1_peer->get_max_sequence());
  510. pr_fi.set_block_size(5);
  511. pr_fi.set_size(5);
  512. auto version = pr_fi.mutable_version();
  513. auto counter = version->add_counters();
  514. counter->set_id(1);
  515. counter->set_value(peer_device->as_uint());
  516. auto b1 = pr_fi.add_blocks();
  517. b1->set_hash(utils::sha256_digest("12345").value());
  518. b1->set_offset(0);
  519. b1->set_size(5);
  520. auto b = model::block_info_t::create(*b1).value();
  521. auto uuid = sup->sequencer->next_uuid();
  522. auto file_info = model::file_info_t::create(uuid, pr_fi, folder_peer).value();
  523. file_info->assign_block(b, 0);
  524. folder_peer->add(file_info, true);
  525. d_peer->set_max_sequence(folder_peer->get_max_sequence());
  526. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  527. peer_actor->push_block("12345", 0);
  528. sup->do_process();
  529. CHECK(folder_my->get_max_sequence() == 1ul);
  530. REQUIRE(folder_my->get_file_infos().size() == 1);
  531. auto f = folder_my->get_file_infos().begin()->item;
  532. REQUIRE(f);
  533. CHECK(f->get_name() == pr_fi.name());
  534. CHECK(f->get_size() == 5);
  535. CHECK(f->get_blocks().size() == 1);
  536. CHECK(f->is_locally_available());
  537. CHECK(!f->is_locked());
  538. }
  539. SECTION("don't attempt to download a file, which is deleted") {
  540. auto folder_peer = folder_infos.by_device(*peer_device);
  541. auto pr_fi = proto::FileInfo{};
  542. pr_fi.set_name("some-file");
  543. pr_fi.set_type(proto::FileInfoType::FILE);
  544. pr_fi.set_sequence(folder_1_peer->get_max_sequence());
  545. pr_fi.set_block_size(5);
  546. pr_fi.set_size(5);
  547. auto b1 = pr_fi.add_blocks();
  548. b1->set_hash(utils::sha256_digest("12345").value());
  549. b1->set_offset(0);
  550. b1->set_size(5);
  551. auto b = model::block_info_t::create(*b1).value();
  552. auto uuid = sup->sequencer->next_uuid();
  553. auto file_info = model::file_info_t::create(uuid, pr_fi, folder_peer).value();
  554. file_info->assign_block(b, 0);
  555. folder_peer->add(file_info, true);
  556. d_peer->set_max_sequence(folder_1_peer->get_max_sequence() + 1);
  557. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  558. sup->do_process();
  559. auto index = proto::IndexUpdate{};
  560. index.set_folder(std::string(folder_1->get_id()));
  561. auto file = index.add_files();
  562. file->set_name("some-file");
  563. file->set_type(proto::FileInfoType::FILE);
  564. file->set_deleted(true);
  565. file->set_sequence(folder_1_peer->get_max_sequence() + 1);
  566. file->set_block_size(0);
  567. file->set_size(0);
  568. peer_actor->forward(proto::message::IndexUpdate(new proto::IndexUpdate(index)));
  569. sup->do_process();
  570. CHECK(folder_my->get_max_sequence() == 1ul);
  571. REQUIRE(folder_my->get_file_infos().size() == 1);
  572. auto f = folder_my->get_file_infos().begin()->item;
  573. REQUIRE(f);
  574. CHECK(f->get_name() == pr_fi.name());
  575. CHECK(f->get_size() == 0);
  576. CHECK(f->get_blocks().size() == 0);
  577. CHECK(f->is_locally_available());
  578. CHECK(f->is_deleted());
  579. CHECK(!f->is_locked());
  580. CHECK(f->get_sequence() == 1ul);
  581. CHECK(peer_actor->blocks_requested == 0);
  582. }
  583. SECTION("new file via index_update => download it") {
  584. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  585. auto index = proto::Index{};
  586. index.set_folder(std::string(folder_1->get_id()));
  587. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  588. auto index_update = proto::IndexUpdate{};
  589. index_update.set_folder(std::string(folder_1->get_id()));
  590. auto file = index_update.add_files();
  591. file->set_name("some-file");
  592. file->set_type(proto::FileInfoType::FILE);
  593. file->set_sequence(folder_1_peer->get_max_sequence() + 1);
  594. file->set_block_size(5);
  595. file->set_size(5);
  596. auto version = file->mutable_version();
  597. auto counter = version->add_counters();
  598. counter->set_id(1);
  599. counter->set_value(peer_device->as_uint());
  600. auto b1 = file->add_blocks();
  601. b1->set_hash(utils::sha256_digest("12345").value());
  602. b1->set_offset(0);
  603. b1->set_size(5);
  604. peer_actor->forward(proto::message::IndexUpdate(new proto::IndexUpdate(index_update)));
  605. peer_actor->push_block("12345", 0);
  606. sup->do_process();
  607. auto folder_my = folder_infos.by_device(*my_device);
  608. CHECK(folder_my->get_max_sequence() == 1);
  609. REQUIRE(folder_my->get_file_infos().size() == 1);
  610. auto f = folder_my->get_file_infos().begin()->item;
  611. REQUIRE(f);
  612. CHECK(f->get_name() == file->name());
  613. CHECK(f->get_size() == 5);
  614. CHECK(f->get_blocks().size() == 1);
  615. CHECK(f->is_locally_available());
  616. CHECK(!f->is_locked());
  617. auto fp = folder_1_peer->get_file_infos().begin()->item;
  618. REQUIRE(fp);
  619. CHECK(!fp->is_locked());
  620. }
  621. SECTION("deleted file, has been restored => download it") {
  622. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  623. sup->do_process();
  624. auto index = proto::Index{};
  625. index.set_folder(std::string(folder_1->get_id()));
  626. auto file_1 = index.add_files();
  627. file_1->set_name("some-file");
  628. file_1->set_type(proto::FileInfoType::FILE);
  629. file_1->set_sequence(folder_1_peer->get_max_sequence());
  630. file_1->set_deleted(true);
  631. auto v1 = file_1->mutable_version();
  632. auto c1 = v1->add_counters();
  633. c1->set_id(1u);
  634. c1->set_value(1u);
  635. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  636. sup->do_process();
  637. auto folder_my = folder_infos.by_device(*my_device);
  638. CHECK(folder_my->get_max_sequence() == 1ul);
  639. auto index_update = proto::IndexUpdate{};
  640. index_update.set_folder(std::string(folder_1->get_id()));
  641. auto file_2 = index_update.add_files();
  642. file_2->set_name("some-file");
  643. file_2->set_type(proto::FileInfoType::FILE);
  644. file_2->set_sequence(folder_1_peer->get_max_sequence() + 1);
  645. file_2->set_block_size(128 * 1024);
  646. file_2->set_size(5);
  647. auto v2 = file_2->mutable_version();
  648. auto c2 = v2->add_counters();
  649. c2->set_id(1u);
  650. c2->set_value(2u);
  651. auto b1 = file_2->add_blocks();
  652. b1->set_hash(utils::sha256_digest("12345").value());
  653. b1->set_offset(0);
  654. b1->set_size(5);
  655. peer_actor->forward(proto::message::IndexUpdate(new proto::IndexUpdate(index_update)));
  656. peer_actor->push_block("12345", 0);
  657. sup->do_process();
  658. REQUIRE(folder_my->get_file_infos().size() == 1);
  659. auto f = folder_my->get_file_infos().begin()->item;
  660. REQUIRE(f);
  661. CHECK(f->get_name() == file_1->name());
  662. CHECK(f->get_size() == 5);
  663. CHECK(f->get_blocks().size() == 1);
  664. CHECK(f->is_locally_available());
  665. CHECK(!f->is_locked());
  666. }
  667. SECTION("download a file, which has the same blocks locally") {
  668. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  669. sup->do_process();
  670. auto index = proto::Index{};
  671. index.set_folder(std::string(folder_1->get_id()));
  672. auto file_1 = index.add_files();
  673. file_1->set_name("some-file");
  674. file_1->set_type(proto::FileInfoType::FILE);
  675. file_1->set_sequence(folder_1_peer->get_max_sequence());
  676. auto v1 = file_1->mutable_version();
  677. auto c1 = v1->add_counters();
  678. c1->set_id(1u);
  679. c1->set_value(1u);
  680. file_1->set_block_size(5);
  681. file_1->set_size(10);
  682. auto b1 = file_1->add_blocks();
  683. b1->set_hash(utils::sha256_digest("12345").value());
  684. b1->set_offset(0);
  685. b1->set_size(5);
  686. auto bi_1 = model::block_info_t::create(*b1).value();
  687. auto b2 = file_1->add_blocks();
  688. b2->set_hash(utils::sha256_digest("67890").value());
  689. b2->set_offset(5);
  690. b2->set_size(5);
  691. auto bi_2 = model::block_info_t::create(*b2).value();
  692. auto &blocks = cluster->get_blocks();
  693. blocks.put(bi_1);
  694. blocks.put(bi_2);
  695. auto pr_my = proto::FileInfo{};
  696. pr_my.set_name("some-file.source");
  697. pr_my.set_type(proto::FileInfoType::FILE);
  698. pr_my.set_sequence(2ul);
  699. pr_my.set_block_size(5);
  700. pr_my.set_size(5);
  701. auto uuid = sup->sequencer->next_uuid();
  702. auto file_my = model::file_info_t::create(uuid, pr_my, folder_my).value();
  703. file_my->assign_block(bi_1, 0);
  704. file_my->mark_local_available(0);
  705. folder_my->add(file_my, true);
  706. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  707. peer_actor->push_block("67890", 1);
  708. cluster->modify_write_requests(10);
  709. sup->do_process();
  710. REQUIRE(folder_my->get_file_infos().size() == 2);
  711. auto f = folder_my->get_file_infos().by_name(file_1->name());
  712. REQUIRE(f);
  713. CHECK(f->get_name() == file_1->name());
  714. CHECK(f->get_size() == 10);
  715. CHECK(f->get_blocks().size() == 2);
  716. CHECK(f->is_locally_available());
  717. CHECK(!f->is_locked());
  718. }
  719. }
  720. };
  721. F(true, 10).run();
  722. }
  723. void test_downloading_errors() {
  724. struct F : fixture_t {
  725. using fixture_t::fixture_t;
  726. void main(diff_builder_t &) noexcept override {
  727. auto &folder_infos = folder_1->get_folder_infos();
  728. auto folder_my = folder_infos.by_device(*my_device);
  729. auto cc = proto::ClusterConfig{};
  730. auto folder = cc.add_folders();
  731. folder->set_id(std::string(folder_1->get_id()));
  732. auto d_peer = folder->add_devices();
  733. d_peer->set_id(std::string(peer_device->device_id().get_sha256()));
  734. d_peer->set_max_sequence(folder_1_peer->get_max_sequence());
  735. d_peer->set_index_id(folder_1_peer->get_index());
  736. auto d_my = folder->add_devices();
  737. d_my->set_id(std::string(my_device->device_id().get_sha256()));
  738. d_my->set_max_sequence(folder_my->get_max_sequence());
  739. d_my->set_index_id(folder_my->get_index());
  740. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  741. auto index = proto::Index{};
  742. index.set_folder(std::string(folder_1->get_id()));
  743. auto file = index.add_files();
  744. file->set_name("some-file");
  745. file->set_type(proto::FileInfoType::FILE);
  746. file->set_sequence(folder_1_peer->get_max_sequence());
  747. file->set_block_size(5);
  748. file->set_size(5);
  749. auto version = file->mutable_version();
  750. auto counter = version->add_counters();
  751. counter->set_id(1ul);
  752. counter->set_value(1ul);
  753. auto b1 = file->add_blocks();
  754. b1->set_hash(utils::sha256_digest("12345").value());
  755. b1->set_offset(0);
  756. b1->set_size(5);
  757. CHECK(folder_my->get_max_sequence() == 0ul);
  758. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  759. SECTION("general error, ok, do not shutdown") {
  760. auto ec = utils::make_error_code(utils::request_error_code_t::generic);
  761. peer_actor->push_block(ec, 0);
  762. }
  763. SECTION("hash mismatch, do not shutdown") { peer_actor->push_block("zzz", 0); }
  764. sup->do_process();
  765. CHECK(peer_actor->blocks_requested == 1);
  766. CHECK(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  767. auto folder_peer = folder_infos.by_device(*peer_device);
  768. REQUIRE(folder_peer->get_file_infos().size() == 1);
  769. auto f = folder_peer->get_file_infos().begin()->item;
  770. REQUIRE(f);
  771. CHECK(f->is_unreachable());
  772. CHECK(!f->is_locally_locked());
  773. CHECK(!f->is_locked());
  774. auto lf = f->local_file();
  775. CHECK(!lf->is_locally_locked());
  776. CHECK(!lf->is_locked());
  777. sup->do_process();
  778. }
  779. };
  780. F(true, 10).run();
  781. }
  782. void test_my_sharing() {
  783. struct F : fixture_t {
  784. using fixture_t::fixture_t;
  785. void main(diff_builder_t &) noexcept override {
  786. sup->do_process();
  787. auto cc = proto::ClusterConfig{};
  788. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  789. // nothing is shared
  790. sup->do_process();
  791. REQUIRE(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  792. REQUIRE(static_cast<r::actor_base_t *>(peer_actor.get())->access<to::state>() == r::state_t::OPERATIONAL);
  793. REQUIRE(peer_actor->messages.size() == 1);
  794. auto peer_msg = &peer_actor->messages.front()->payload;
  795. auto peer_cluster_msg = std::get_if<proto::message::ClusterConfig>(peer_msg);
  796. REQUIRE(peer_cluster_msg);
  797. REQUIRE(*peer_cluster_msg);
  798. REQUIRE((*peer_cluster_msg)->folders_size() == 0);
  799. // share folder_1
  800. peer_actor->messages.clear();
  801. auto sha256 = peer_device->device_id().get_sha256();
  802. diff_builder_t(*cluster).share_folder(sha256, folder_1->get_id()).apply(*sup);
  803. REQUIRE(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  804. REQUIRE(static_cast<r::actor_base_t *>(peer_actor.get())->access<to::state>() == r::state_t::OPERATIONAL);
  805. REQUIRE(peer_actor->messages.size() == 1);
  806. peer_msg = &peer_actor->messages.front()->payload;
  807. peer_cluster_msg = std::get_if<proto::message::ClusterConfig>(peer_msg);
  808. REQUIRE(peer_cluster_msg);
  809. REQUIRE(*peer_cluster_msg);
  810. REQUIRE((*peer_cluster_msg)->folders_size() == 1);
  811. // unshare folder_1
  812. auto peer_fi = folder_1->get_folder_infos().by_device(*peer_device);
  813. peer_actor->messages.clear();
  814. diff_builder_t(*cluster).unshare_folder(*peer_fi).apply(*sup);
  815. REQUIRE(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  816. REQUIRE(static_cast<r::actor_base_t *>(peer_actor.get())->access<to::state>() == r::state_t::OPERATIONAL);
  817. REQUIRE(peer_actor->messages.size() == 1);
  818. peer_msg = &peer_actor->messages.front()->payload;
  819. peer_cluster_msg = std::get_if<proto::message::ClusterConfig>(peer_msg);
  820. REQUIRE(peer_cluster_msg);
  821. REQUIRE(*peer_cluster_msg);
  822. REQUIRE((*peer_cluster_msg)->folders_size() == 0);
  823. }
  824. };
  825. F(false, 10, false).run();
  826. }
  827. void test_sending_index_updates() {
  828. struct F : fixture_t {
  829. using fixture_t::fixture_t;
  830. void main(diff_builder_t &) noexcept override {
  831. auto &folder_infos = folder_1->get_folder_infos();
  832. auto folder_my = folder_infos.by_device(*my_device);
  833. auto cc = proto::ClusterConfig{};
  834. auto folder = cc.add_folders();
  835. folder->set_id(std::string(folder_1->get_id()));
  836. auto d_peer = folder->add_devices();
  837. d_peer->set_id(std::string(peer_device->device_id().get_sha256()));
  838. d_peer->set_max_sequence(folder_1_peer->get_max_sequence());
  839. d_peer->set_index_id(folder_1_peer->get_index());
  840. auto d_my = folder->add_devices();
  841. d_my->set_id(std::string(my_device->device_id().get_sha256()));
  842. d_my->set_max_sequence(folder_my->get_max_sequence());
  843. d_my->set_index_id(folder_my->get_index());
  844. auto index = proto::Index{};
  845. auto folder_id = std::string(folder_1->get_id());
  846. index.set_folder(folder_id);
  847. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  848. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  849. sup->do_process();
  850. auto builder = diff_builder_t(*cluster);
  851. auto pr_file = proto::FileInfo();
  852. pr_file.set_name("a.txt");
  853. peer_actor->messages.clear();
  854. builder.local_update(folder_id, pr_file).apply(*sup);
  855. REQUIRE(peer_actor->messages.size() == 1);
  856. auto &msg = peer_actor->messages.front();
  857. auto &index_update = *std::get<proto::message::IndexUpdate>(msg->payload);
  858. REQUIRE(index_update.files_size() == 1);
  859. CHECK(index_update.files(0).name() == "a.txt");
  860. }
  861. };
  862. F(true, 10).run();
  863. }
  864. void test_uploading() {
  865. struct F : fixture_t {
  866. using fixture_t::fixture_t;
  867. void main(diff_builder_t &) noexcept override {
  868. auto &folder_infos = folder_1->get_folder_infos();
  869. auto folder_my = folder_infos.by_device(*my_device);
  870. auto cc = proto::ClusterConfig{};
  871. auto folder = cc.add_folders();
  872. folder->set_id(std::string(folder_1->get_id()));
  873. auto d_peer = folder->add_devices();
  874. d_peer->set_id(std::string(peer_device->device_id().get_sha256()));
  875. d_peer->set_max_sequence(folder_1_peer->get_max_sequence());
  876. d_peer->set_index_id(folder_1_peer->get_index());
  877. auto d_my = folder->add_devices();
  878. d_my->set_id(std::string(my_device->device_id().get_sha256()));
  879. d_my->set_max_sequence(folder_my->get_max_sequence());
  880. d_my->set_index_id(folder_my->get_index());
  881. auto pr_fi = proto::FileInfo{};
  882. pr_fi.set_name("data.bin");
  883. pr_fi.set_type(proto::FileInfoType::FILE);
  884. pr_fi.set_sequence(folder_1_peer->get_max_sequence());
  885. pr_fi.set_block_size(5);
  886. pr_fi.set_size(5);
  887. auto version = pr_fi.mutable_version();
  888. auto counter = version->add_counters();
  889. counter->set_id(1);
  890. counter->set_value(my_device->as_uint());
  891. auto b1 = pr_fi.add_blocks();
  892. b1->set_hash(utils::sha256_digest("12345").value());
  893. b1->set_offset(0);
  894. b1->set_size(5);
  895. auto b = model::block_info_t::create(*b1).value();
  896. auto uuid = sup->sequencer->next_uuid();
  897. auto file_info = model::file_info_t::create(uuid, pr_fi, folder_my).value();
  898. file_info->assign_block(b, 0);
  899. folder_my->add(file_info, true);
  900. auto req = proto::Request();
  901. req.set_id(1);
  902. req.set_folder(std::string(folder_1->get_id()));
  903. req.set_name("data.bin");
  904. req.set_offset(0);
  905. req.set_size(5);
  906. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  907. SECTION("upload regular file, no hash") {
  908. peer_actor->forward(proto::message::Request(new proto::Request(req)));
  909. auto req_ptr = proto::message::Request(new proto::Request(req));
  910. auto res = r::make_message<fs::payload::block_response_t>(target->get_address(), std::move(req_ptr),
  911. sys::error_code{}, std::string("12345"));
  912. block_responses.push_back(res);
  913. sup->do_process();
  914. REQUIRE(block_requests.size() == 1);
  915. CHECK(block_requests[0]->payload.remote_request->id() == 1);
  916. CHECK(block_requests[0]->payload.remote_request->name() == "data.bin");
  917. REQUIRE(peer_actor->uploaded_blocks.size() == 1);
  918. auto &peer_res = *peer_actor->uploaded_blocks.front();
  919. CHECK(peer_res.id() == 1);
  920. CHECK(peer_res.code() == proto::ErrorCode::NO_BEP_ERROR);
  921. CHECK(peer_res.data() == "12345");
  922. }
  923. }
  924. };
  925. F(true, 10).run();
  926. }
  927. void test_peer_removal() {
  928. struct F : fixture_t {
  929. using fixture_t::fixture_t;
  930. void main(diff_builder_t &builder) noexcept override {
  931. builder.remove_peer(*peer_device).apply(*sup);
  932. CHECK(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::SHUT_DOWN);
  933. CHECK(static_cast<r::actor_base_t *>(peer_actor.get())->access<to::state>() == r::state_t::SHUT_DOWN);
  934. CHECK(target->get_shutdown_reason()->root()->ec == utils::error_code_t::peer_has_been_removed);
  935. }
  936. };
  937. F(true, 10).run();
  938. }
  939. int _init() {
  940. REGISTER_TEST_CASE(test_startup, "test_startup", "[net]");
  941. REGISTER_TEST_CASE(test_index_receiving, "test_index_receiving", "[net]");
  942. REGISTER_TEST_CASE(test_index_sending, "test_index_sending", "[net]");
  943. REGISTER_TEST_CASE(test_downloading, "test_downloading", "[net]");
  944. REGISTER_TEST_CASE(test_downloading_errors, "test_downloading_errors", "[net]");
  945. REGISTER_TEST_CASE(test_my_sharing, "test_my_sharing", "[net]");
  946. REGISTER_TEST_CASE(test_sending_index_updates, "test_sending_index_updates", "[net]");
  947. REGISTER_TEST_CASE(test_uploading, "test_uploading", "[net]");
  948. REGISTER_TEST_CASE(test_peer_removal, "test_peer_removal", "[net]");
  949. return 1;
  950. }
  951. static int v = _init();