075-controller.cpp 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. // SPDX-FileCopyrightText: 2019-2023 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. #include <vector>
  17. using namespace syncspirit;
  18. using namespace syncspirit::test;
  19. using namespace syncspirit::model;
  20. using namespace syncspirit::net;
  21. using namespace syncspirit::hasher;
  22. namespace {
  23. struct sample_peer_config_t : public r::actor_config_t {
  24. model::device_id_t peer_device_id;
  25. };
  26. template <typename Actor> struct sample_peer_config_builder_t : r::actor_config_builder_t<Actor> {
  27. using builder_t = typename Actor::template config_builder_t<Actor>;
  28. using parent_t = r::actor_config_builder_t<Actor>;
  29. using parent_t::parent_t;
  30. builder_t &&peer_device_id(const model::device_id_t &value) && noexcept {
  31. parent_t::config.peer_device_id = value;
  32. return std::move(*static_cast<typename parent_t::builder_t *>(this));
  33. }
  34. };
  35. struct sample_peer_t : r::actor_base_t {
  36. using config_t = sample_peer_config_t;
  37. template <typename Actor> using config_builder_t = sample_peer_config_builder_t<Actor>;
  38. using remote_message_t = r::intrusive_ptr_t<net::message::forwarded_message_t>;
  39. using remote_messages_t = std::list<remote_message_t>;
  40. struct block_response_t {
  41. size_t block_index;
  42. std::string data;
  43. sys::error_code ec;
  44. };
  45. using block_responses_t = std::list<block_response_t>;
  46. using block_request_t = r::intrusive_ptr_t<net::message::block_request_t>;
  47. using block_requests_t = std::list<block_request_t>;
  48. using uploaded_blocks_t = std::list<proto::message::Response>;
  49. sample_peer_t(config_t &config) : r::actor_base_t{config}, peer_device{config.peer_device_id} {
  50. log = utils::get_logger("test.sample_peer");
  51. }
  52. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  53. r::actor_base_t::configure(plugin);
  54. plugin.with_casted<r::plugin::address_maker_plugin_t>([&](auto &p) { p.set_identity("sample_peer", false); });
  55. plugin.with_casted<r::plugin::starter_plugin_t>([&](auto &p) {
  56. p.subscribe_actor(&sample_peer_t::on_start_reading);
  57. p.subscribe_actor(&sample_peer_t::on_termination);
  58. p.subscribe_actor(&sample_peer_t::on_transfer);
  59. p.subscribe_actor(&sample_peer_t::on_block_request);
  60. });
  61. }
  62. void shutdown_start() noexcept override {
  63. LOG_TRACE(log, "{}, shutdown_start", identity);
  64. if (controller) {
  65. send<net::payload::termination_t>(controller, shutdown_reason);
  66. }
  67. r::actor_base_t::shutdown_start();
  68. }
  69. void shutdown_finish() noexcept override {
  70. r::actor_base_t::shutdown_finish();
  71. LOG_TRACE(log, "{}, shutdown_finish, blocks requested = {}", identity, blocks_requested);
  72. if (controller) {
  73. send<net::payload::termination_t>(controller, shutdown_reason);
  74. }
  75. }
  76. void on_start_reading(net::message::start_reading_t &msg) noexcept {
  77. LOG_TRACE(log, "{}, on_start_reading", identity);
  78. controller = msg.payload.controller;
  79. reading = msg.payload.start;
  80. }
  81. void on_termination(net::message::termination_signal_t &msg) noexcept {
  82. LOG_TRACE(log, "{}, on_termination", identity);
  83. if (!shutdown_reason) {
  84. auto &ee = msg.payload.ee;
  85. auto reason = ee->message();
  86. LOG_TRACE(log, "{}, on_termination: {}", identity, reason);
  87. do_shutdown(ee);
  88. }
  89. }
  90. void on_transfer(net::message::transfer_data_t &message) noexcept {
  91. auto &data = message.payload.data;
  92. LOG_TRACE(log, "{}, on_transfer, bytes = {}", identity, data.size());
  93. auto buff = boost::asio::buffer(data.data(), data.size());
  94. auto result = proto::parse_bep(buff);
  95. auto orig = std::move(result.value().message);
  96. auto variant = net::payload::forwarded_message_t();
  97. std::visit(
  98. [&](auto &msg) {
  99. using boost::core::demangle;
  100. using T = std::decay_t<decltype(msg)>;
  101. LOG_TRACE(log, "{}, received '{}' message", identity, demangle(typeid(T).name()));
  102. using V = net::payload::forwarded_message_t;
  103. if constexpr (std::is_constructible_v<V, T>) {
  104. variant = std::move(msg);
  105. } else if constexpr (std::is_same_v<T, proto::message::Response>) {
  106. uploaded_blocks.push_back(std::move(msg));
  107. }
  108. },
  109. orig);
  110. auto fwd_msg = new net::message::forwarded_message_t(address, std::move(variant));
  111. messages.emplace_back(fwd_msg);
  112. }
  113. void on_block_request(net::message::block_request_t &req) noexcept {
  114. block_requests.push_front(&req);
  115. ++blocks_requested;
  116. log->debug("{}, requesting block # {}", identity,
  117. block_requests.front()->payload.request_payload.block.block_index());
  118. if (block_responses.size()) {
  119. log->debug("{}, top response block # {}", identity, block_responses.front().block_index);
  120. }
  121. auto condition = [&]() -> bool {
  122. return block_requests.size() && block_responses.size() &&
  123. block_requests.front()->payload.request_payload.block.block_index() ==
  124. block_responses.front().block_index;
  125. };
  126. while (condition()) {
  127. auto &reply = block_responses.front();
  128. auto &request = *block_requests.front();
  129. log->debug("{}, matched, replying..., ec = {}", identity, reply.ec.value());
  130. if (!reply.ec) {
  131. reply_to(request, reply.data);
  132. } else {
  133. reply_with_error(request, make_error(reply.ec));
  134. }
  135. block_responses.pop_front();
  136. block_requests.pop_front();
  137. }
  138. }
  139. void forward(net::payload::forwarded_message_t payload) noexcept {
  140. send<net::payload::forwarded_message_t>(controller, std::move(payload));
  141. }
  142. static const constexpr size_t next_block = 1000000;
  143. void push_block(std::string_view data, size_t index) {
  144. if (index == next_block) {
  145. index = block_responses.size();
  146. }
  147. block_responses.push_back(block_response_t{index, std::string(data)});
  148. }
  149. void push_block(sys::error_code ec, size_t index) {
  150. if (index == next_block) {
  151. index = block_responses.size();
  152. }
  153. block_responses.push_back(block_response_t{index, std::string{}, ec});
  154. }
  155. size_t blocks_requested = 0;
  156. bool reading = false;
  157. remote_messages_t messages;
  158. r::address_ptr_t controller;
  159. model::device_id_t peer_device;
  160. utils::logger_t log;
  161. block_requests_t block_requests;
  162. block_responses_t block_responses;
  163. uploaded_blocks_t uploaded_blocks;
  164. };
  165. struct fixture_t {
  166. using peer_ptr_t = r::intrusive_ptr_t<sample_peer_t>;
  167. using target_ptr_t = r::intrusive_ptr_t<net::controller_actor_t>;
  168. using blk_req_t = fs::message::block_request_t;
  169. using blk_req_ptr_t = r::intrusive_ptr_t<blk_req_t>;
  170. using blk_res_t = fs::message::block_response_t;
  171. using blk_res_ptr_t = r::intrusive_ptr_t<blk_res_t>;
  172. using block_requests_t = std::deque<blk_req_ptr_t>;
  173. using block_responses_t = std::deque<r::message_ptr_t>;
  174. fixture_t(bool auto_start_, int64_t max_sequence_, bool auto_share_ = true) noexcept
  175. : auto_start{auto_start_}, max_sequence{max_sequence_}, auto_share{auto_share_} {
  176. utils::set_default("trace");
  177. }
  178. virtual void run() noexcept {
  179. auto peer_id =
  180. device_id_t::from_string("VUV42CZ-IQD5A37-RPEBPM4-VVQK6E4-6WSKC7B-PVJQHHD-4PZD44V-ENC6WAZ").value();
  181. peer_device = device_t::create(peer_id, "peer-device").value();
  182. auto my_id =
  183. device_id_t::from_string("KHQNO2S-5QSILRK-YX4JZZ4-7L77APM-QNVGZJT-EKU7IFI-PNEPBMY-4MXFMQD").value();
  184. my_device = device_t::create(my_id, "my-device").value();
  185. cluster = new cluster_t(my_device, 1, 1);
  186. cluster->get_devices().put(my_device);
  187. cluster->get_devices().put(peer_device);
  188. auto folder_id_1 = "1234-5678";
  189. auto folder_id_2 = "5555";
  190. auto builder = diff_builder_t(*cluster);
  191. auto sha256 = peer_id.get_sha256();
  192. builder.create_folder(folder_id_1, "")
  193. .create_folder(folder_id_2, "")
  194. .configure_cluster(sha256)
  195. .add(sha256, folder_id_1, 123, max_sequence)
  196. .finish();
  197. if (auto_share) {
  198. builder.share_folder(peer_id.get_sha256(), folder_id_1);
  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. builder.apply(*sup);
  227. auto &folders = cluster->get_folders();
  228. folder_1 = folders.by_id(folder_id_1);
  229. folder_2 = folders.by_id(folder_id_2);
  230. folder_1_peer = folder_1->get_folder_infos().by_device_id(peer_id.get_sha256());
  231. target = sup->create_actor<controller_actor_t>()
  232. .peer(peer_device)
  233. .peer_addr(peer_actor->get_address())
  234. .request_pool(1024)
  235. .outgoing_buffer_max(1024'000)
  236. .cluster(cluster)
  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).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_unknown_folders().empty());
  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 file_info = model::file_info_t::create(cluster->next_uuid(), pr_fi, folder_peer).value();
  522. file_info->assign_block(b, 0);
  523. folder_peer->add(file_info, true);
  524. d_peer->set_max_sequence(folder_peer->get_max_sequence());
  525. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  526. peer_actor->push_block("12345", 0);
  527. sup->do_process();
  528. CHECK(folder_my->get_max_sequence() == 1ul);
  529. REQUIRE(folder_my->get_file_infos().size() == 1);
  530. auto f = folder_my->get_file_infos().begin()->item;
  531. REQUIRE(f);
  532. CHECK(f->get_name() == pr_fi.name());
  533. CHECK(f->get_size() == 5);
  534. CHECK(f->get_blocks().size() == 1);
  535. CHECK(f->is_locally_available());
  536. CHECK(!f->is_locked());
  537. }
  538. SECTION("don't attempt to download a file, which is deleted") {
  539. auto folder_peer = folder_infos.by_device(*peer_device);
  540. auto pr_fi = proto::FileInfo{};
  541. pr_fi.set_name("some-file");
  542. pr_fi.set_type(proto::FileInfoType::FILE);
  543. pr_fi.set_sequence(folder_1_peer->get_max_sequence());
  544. pr_fi.set_block_size(5);
  545. pr_fi.set_size(5);
  546. auto b1 = pr_fi.add_blocks();
  547. b1->set_hash(utils::sha256_digest("12345").value());
  548. b1->set_offset(0);
  549. b1->set_size(5);
  550. auto b = model::block_info_t::create(*b1).value();
  551. auto file_info = model::file_info_t::create(cluster->next_uuid(), pr_fi, folder_peer).value();
  552. file_info->assign_block(b, 0);
  553. folder_peer->add(file_info, true);
  554. d_peer->set_max_sequence(folder_1_peer->get_max_sequence() + 1);
  555. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  556. sup->do_process();
  557. auto index = proto::IndexUpdate{};
  558. index.set_folder(std::string(folder_1->get_id()));
  559. auto file = index.add_files();
  560. file->set_name("some-file");
  561. file->set_type(proto::FileInfoType::FILE);
  562. file->set_deleted(true);
  563. file->set_sequence(folder_1_peer->get_max_sequence() + 1);
  564. file->set_block_size(0);
  565. file->set_size(0);
  566. peer_actor->forward(proto::message::IndexUpdate(new proto::IndexUpdate(index)));
  567. sup->do_process();
  568. CHECK(folder_my->get_max_sequence() == 1ul);
  569. REQUIRE(folder_my->get_file_infos().size() == 1);
  570. auto f = folder_my->get_file_infos().begin()->item;
  571. REQUIRE(f);
  572. CHECK(f->get_name() == pr_fi.name());
  573. CHECK(f->get_size() == 0);
  574. CHECK(f->get_blocks().size() == 0);
  575. CHECK(f->is_locally_available());
  576. CHECK(f->is_deleted());
  577. CHECK(!f->is_locked());
  578. CHECK(f->get_sequence() == 1ul);
  579. CHECK(peer_actor->blocks_requested == 0);
  580. }
  581. SECTION("new file via index_update => download it") {
  582. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  583. auto index = proto::Index{};
  584. index.set_folder(std::string(folder_1->get_id()));
  585. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  586. auto index_update = proto::IndexUpdate{};
  587. index_update.set_folder(std::string(folder_1->get_id()));
  588. auto file = index_update.add_files();
  589. file->set_name("some-file");
  590. file->set_type(proto::FileInfoType::FILE);
  591. file->set_sequence(folder_1_peer->get_max_sequence() + 1);
  592. file->set_block_size(5);
  593. file->set_size(5);
  594. auto version = file->mutable_version();
  595. auto counter = version->add_counters();
  596. counter->set_id(1);
  597. counter->set_value(peer_device->as_uint());
  598. auto b1 = file->add_blocks();
  599. b1->set_hash(utils::sha256_digest("12345").value());
  600. b1->set_offset(0);
  601. b1->set_size(5);
  602. peer_actor->forward(proto::message::IndexUpdate(new proto::IndexUpdate(index_update)));
  603. peer_actor->push_block("12345", 0);
  604. sup->do_process();
  605. auto folder_my = folder_infos.by_device(*my_device);
  606. CHECK(folder_my->get_max_sequence() == 1);
  607. REQUIRE(folder_my->get_file_infos().size() == 1);
  608. auto f = folder_my->get_file_infos().begin()->item;
  609. REQUIRE(f);
  610. CHECK(f->get_name() == file->name());
  611. CHECK(f->get_size() == 5);
  612. CHECK(f->get_blocks().size() == 1);
  613. CHECK(f->is_locally_available());
  614. CHECK(!f->is_locked());
  615. auto fp = folder_1_peer->get_file_infos().begin()->item;
  616. REQUIRE(fp);
  617. CHECK(!fp->is_locked());
  618. }
  619. SECTION("deleted file, has been restored => download it") {
  620. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  621. sup->do_process();
  622. auto index = proto::Index{};
  623. index.set_folder(std::string(folder_1->get_id()));
  624. auto file_1 = index.add_files();
  625. file_1->set_name("some-file");
  626. file_1->set_type(proto::FileInfoType::FILE);
  627. file_1->set_sequence(folder_1_peer->get_max_sequence());
  628. file_1->set_deleted(true);
  629. auto v1 = file_1->mutable_version();
  630. auto c1 = v1->add_counters();
  631. c1->set_id(1u);
  632. c1->set_value(1u);
  633. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  634. sup->do_process();
  635. auto folder_my = folder_infos.by_device(*my_device);
  636. CHECK(folder_my->get_max_sequence() == 1ul);
  637. auto index_update = proto::IndexUpdate{};
  638. index_update.set_folder(std::string(folder_1->get_id()));
  639. auto file_2 = index_update.add_files();
  640. file_2->set_name("some-file");
  641. file_2->set_type(proto::FileInfoType::FILE);
  642. file_2->set_sequence(folder_1_peer->get_max_sequence() + 1);
  643. file_2->set_block_size(128 * 1024);
  644. file_2->set_size(5);
  645. auto v2 = file_2->mutable_version();
  646. auto c2 = v2->add_counters();
  647. c2->set_id(1u);
  648. c2->set_value(2u);
  649. auto b1 = file_2->add_blocks();
  650. b1->set_hash(utils::sha256_digest("12345").value());
  651. b1->set_offset(0);
  652. b1->set_size(5);
  653. peer_actor->forward(proto::message::IndexUpdate(new proto::IndexUpdate(index_update)));
  654. peer_actor->push_block("12345", 0);
  655. sup->do_process();
  656. REQUIRE(folder_my->get_file_infos().size() == 1);
  657. auto f = folder_my->get_file_infos().begin()->item;
  658. REQUIRE(f);
  659. CHECK(f->get_name() == file_1->name());
  660. CHECK(f->get_size() == 5);
  661. CHECK(f->get_blocks().size() == 1);
  662. CHECK(f->is_locally_available());
  663. CHECK(!f->is_locked());
  664. }
  665. SECTION("download a file, which has the same blocks locally") {
  666. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  667. sup->do_process();
  668. auto index = proto::Index{};
  669. index.set_folder(std::string(folder_1->get_id()));
  670. auto file_1 = index.add_files();
  671. file_1->set_name("some-file");
  672. file_1->set_type(proto::FileInfoType::FILE);
  673. file_1->set_sequence(folder_1_peer->get_max_sequence());
  674. auto v1 = file_1->mutable_version();
  675. auto c1 = v1->add_counters();
  676. c1->set_id(1u);
  677. c1->set_value(1u);
  678. file_1->set_block_size(5);
  679. file_1->set_size(10);
  680. auto b1 = file_1->add_blocks();
  681. b1->set_hash(utils::sha256_digest("12345").value());
  682. b1->set_offset(0);
  683. b1->set_size(5);
  684. auto bi_1 = model::block_info_t::create(*b1).value();
  685. auto b2 = file_1->add_blocks();
  686. b2->set_hash(utils::sha256_digest("67890").value());
  687. b2->set_offset(5);
  688. b2->set_size(5);
  689. auto bi_2 = model::block_info_t::create(*b2).value();
  690. auto &blocks = cluster->get_blocks();
  691. blocks.put(bi_1);
  692. blocks.put(bi_2);
  693. auto pr_my = proto::FileInfo{};
  694. pr_my.set_name("some-file.source");
  695. pr_my.set_type(proto::FileInfoType::FILE);
  696. pr_my.set_sequence(2ul);
  697. pr_my.set_block_size(5);
  698. pr_my.set_size(5);
  699. auto file_my = model::file_info_t::create(cluster->next_uuid(), pr_my, folder_my).value();
  700. file_my->assign_block(bi_1, 0);
  701. file_my->mark_local_available(0);
  702. folder_my->add(file_my, true);
  703. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  704. peer_actor->push_block("67890", 1);
  705. cluster->modify_write_requests(10);
  706. sup->do_process();
  707. REQUIRE(folder_my->get_file_infos().size() == 2);
  708. auto f = folder_my->get_file_infos().by_name(file_1->name());
  709. REQUIRE(f);
  710. CHECK(f->get_name() == file_1->name());
  711. CHECK(f->get_size() == 10);
  712. CHECK(f->get_blocks().size() == 2);
  713. CHECK(f->is_locally_available());
  714. CHECK(!f->is_locked());
  715. }
  716. }
  717. };
  718. F(true, 10).run();
  719. }
  720. void test_downloading_errors() {
  721. struct F : fixture_t {
  722. using fixture_t::fixture_t;
  723. void main(diff_builder_t &) noexcept override {
  724. auto &folder_infos = folder_1->get_folder_infos();
  725. auto folder_my = folder_infos.by_device(*my_device);
  726. auto cc = proto::ClusterConfig{};
  727. auto folder = cc.add_folders();
  728. folder->set_id(std::string(folder_1->get_id()));
  729. auto d_peer = folder->add_devices();
  730. d_peer->set_id(std::string(peer_device->device_id().get_sha256()));
  731. d_peer->set_max_sequence(folder_1_peer->get_max_sequence());
  732. d_peer->set_index_id(folder_1_peer->get_index());
  733. auto d_my = folder->add_devices();
  734. d_my->set_id(std::string(my_device->device_id().get_sha256()));
  735. d_my->set_max_sequence(folder_my->get_max_sequence());
  736. d_my->set_index_id(folder_my->get_index());
  737. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  738. auto index = proto::Index{};
  739. index.set_folder(std::string(folder_1->get_id()));
  740. auto file = index.add_files();
  741. file->set_name("some-file");
  742. file->set_type(proto::FileInfoType::FILE);
  743. file->set_sequence(folder_1_peer->get_max_sequence());
  744. file->set_block_size(5);
  745. file->set_size(5);
  746. auto version = file->mutable_version();
  747. auto counter = version->add_counters();
  748. counter->set_id(1ul);
  749. counter->set_value(1ul);
  750. auto b1 = file->add_blocks();
  751. b1->set_hash(utils::sha256_digest("12345").value());
  752. b1->set_offset(0);
  753. b1->set_size(5);
  754. CHECK(folder_my->get_max_sequence() == 0ul);
  755. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  756. SECTION("general error, ok, do not shutdown") {
  757. auto ec = utils::make_error_code(utils::request_error_code_t::generic);
  758. peer_actor->push_block(ec, 0);
  759. }
  760. SECTION("hash mismatch, do not shutdown") { peer_actor->push_block("zzz", 0); }
  761. sup->do_process();
  762. CHECK(peer_actor->blocks_requested == 1);
  763. CHECK(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  764. auto folder_peer = folder_infos.by_device(*peer_device);
  765. REQUIRE(folder_peer->get_file_infos().size() == 1);
  766. auto f = folder_peer->get_file_infos().begin()->item;
  767. REQUIRE(f);
  768. CHECK(f->is_unreachable());
  769. CHECK(!f->is_locally_locked());
  770. CHECK(!f->is_locked());
  771. auto lf = f->local_file();
  772. CHECK(!lf->is_locally_locked());
  773. CHECK(!lf->is_locked());
  774. sup->do_process();
  775. }
  776. };
  777. F(true, 10).run();
  778. }
  779. void test_my_sharing() {
  780. struct F : fixture_t {
  781. using fixture_t::fixture_t;
  782. void main(diff_builder_t &) noexcept override {
  783. sup->do_process();
  784. auto cc = proto::ClusterConfig{};
  785. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  786. // nothing is shared
  787. sup->do_process();
  788. REQUIRE(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  789. REQUIRE(static_cast<r::actor_base_t *>(peer_actor.get())->access<to::state>() == r::state_t::OPERATIONAL);
  790. REQUIRE(peer_actor->messages.size() == 1);
  791. auto peer_msg = &peer_actor->messages.front()->payload;
  792. auto peer_cluster_msg = std::get_if<proto::message::ClusterConfig>(peer_msg);
  793. REQUIRE(peer_cluster_msg);
  794. REQUIRE(*peer_cluster_msg);
  795. REQUIRE((*peer_cluster_msg)->folders_size() == 0);
  796. // share folder_1
  797. peer_actor->messages.clear();
  798. auto sha256 = peer_device->device_id().get_sha256();
  799. diff_builder_t(*cluster).share_folder(sha256, folder_1->get_id()).apply(*sup);
  800. REQUIRE(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  801. REQUIRE(static_cast<r::actor_base_t *>(peer_actor.get())->access<to::state>() == r::state_t::OPERATIONAL);
  802. REQUIRE(peer_actor->messages.size() == 1);
  803. peer_msg = &peer_actor->messages.front()->payload;
  804. peer_cluster_msg = std::get_if<proto::message::ClusterConfig>(peer_msg);
  805. REQUIRE(peer_cluster_msg);
  806. REQUIRE(*peer_cluster_msg);
  807. REQUIRE((*peer_cluster_msg)->folders_size() == 1);
  808. // unshare folder_1
  809. peer_actor->messages.clear();
  810. diff_builder_t(*cluster).unshare_folder(sha256, folder_1->get_id()).apply(*sup);
  811. REQUIRE(static_cast<r::actor_base_t *>(target.get())->access<to::state>() == r::state_t::OPERATIONAL);
  812. REQUIRE(static_cast<r::actor_base_t *>(peer_actor.get())->access<to::state>() == r::state_t::OPERATIONAL);
  813. REQUIRE(peer_actor->messages.size() == 1);
  814. peer_msg = &peer_actor->messages.front()->payload;
  815. peer_cluster_msg = std::get_if<proto::message::ClusterConfig>(peer_msg);
  816. REQUIRE(peer_cluster_msg);
  817. REQUIRE(*peer_cluster_msg);
  818. REQUIRE((*peer_cluster_msg)->folders_size() == 0);
  819. }
  820. };
  821. F(false, 10, false).run();
  822. }
  823. void test_sending_index_updates() {
  824. struct F : fixture_t {
  825. using fixture_t::fixture_t;
  826. void main(diff_builder_t &) noexcept override {
  827. auto &folder_infos = folder_1->get_folder_infos();
  828. auto folder_my = folder_infos.by_device(*my_device);
  829. auto cc = proto::ClusterConfig{};
  830. auto folder = cc.add_folders();
  831. folder->set_id(std::string(folder_1->get_id()));
  832. auto d_peer = folder->add_devices();
  833. d_peer->set_id(std::string(peer_device->device_id().get_sha256()));
  834. d_peer->set_max_sequence(folder_1_peer->get_max_sequence());
  835. d_peer->set_index_id(folder_1_peer->get_index());
  836. auto d_my = folder->add_devices();
  837. d_my->set_id(std::string(my_device->device_id().get_sha256()));
  838. d_my->set_max_sequence(folder_my->get_max_sequence());
  839. d_my->set_index_id(folder_my->get_index());
  840. auto index = proto::Index{};
  841. auto folder_id = std::string(folder_1->get_id());
  842. index.set_folder(folder_id);
  843. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  844. peer_actor->forward(proto::message::Index(new proto::Index(index)));
  845. sup->do_process();
  846. auto builder = diff_builder_t(*cluster);
  847. auto pr_file = proto::FileInfo();
  848. pr_file.set_name("a.txt");
  849. peer_actor->messages.clear();
  850. builder.local_update(folder_id, pr_file).apply(*sup);
  851. REQUIRE(peer_actor->messages.size() == 1);
  852. auto &msg = peer_actor->messages.front();
  853. auto &index_update = *std::get<proto::message::IndexUpdate>(msg->payload);
  854. REQUIRE(index_update.files_size() == 1);
  855. CHECK(index_update.files(0).name() == "a.txt");
  856. }
  857. };
  858. F(true, 10).run();
  859. }
  860. void test_uploading() {
  861. struct F : fixture_t {
  862. using fixture_t::fixture_t;
  863. void main(diff_builder_t &) noexcept override {
  864. auto &folder_infos = folder_1->get_folder_infos();
  865. auto folder_my = folder_infos.by_device(*my_device);
  866. auto cc = proto::ClusterConfig{};
  867. auto folder = cc.add_folders();
  868. folder->set_id(std::string(folder_1->get_id()));
  869. auto d_peer = folder->add_devices();
  870. d_peer->set_id(std::string(peer_device->device_id().get_sha256()));
  871. d_peer->set_max_sequence(folder_1_peer->get_max_sequence());
  872. d_peer->set_index_id(folder_1_peer->get_index());
  873. auto d_my = folder->add_devices();
  874. d_my->set_id(std::string(my_device->device_id().get_sha256()));
  875. d_my->set_max_sequence(folder_my->get_max_sequence());
  876. d_my->set_index_id(folder_my->get_index());
  877. auto pr_fi = proto::FileInfo{};
  878. pr_fi.set_name("data.bin");
  879. pr_fi.set_type(proto::FileInfoType::FILE);
  880. pr_fi.set_sequence(folder_1_peer->get_max_sequence());
  881. pr_fi.set_block_size(5);
  882. pr_fi.set_size(5);
  883. auto version = pr_fi.mutable_version();
  884. auto counter = version->add_counters();
  885. counter->set_id(1);
  886. counter->set_value(my_device->as_uint());
  887. auto b1 = pr_fi.add_blocks();
  888. b1->set_hash(utils::sha256_digest("12345").value());
  889. b1->set_offset(0);
  890. b1->set_size(5);
  891. auto b = model::block_info_t::create(*b1).value();
  892. auto file_info = model::file_info_t::create(cluster->next_uuid(), pr_fi, folder_my).value();
  893. file_info->assign_block(b, 0);
  894. folder_my->add(file_info, true);
  895. auto req = proto::Request();
  896. req.set_id(1);
  897. req.set_folder(std::string(folder_1->get_id()));
  898. req.set_name("data.bin");
  899. req.set_offset(0);
  900. req.set_size(5);
  901. peer_actor->forward(proto::message::ClusterConfig(new proto::ClusterConfig(cc)));
  902. SECTION("upload regular file, no hash") {
  903. peer_actor->forward(proto::message::Request(new proto::Request(req)));
  904. auto req_ptr = proto::message::Request(new proto::Request(req));
  905. auto res = r::make_message<fs::payload::block_response_t>(target->get_address(), std::move(req_ptr),
  906. sys::error_code{}, std::string("12345"));
  907. block_responses.push_back(res);
  908. sup->do_process();
  909. REQUIRE(block_requests.size() == 1);
  910. CHECK(block_requests[0]->payload.remote_request->id() == 1);
  911. CHECK(block_requests[0]->payload.remote_request->name() == "data.bin");
  912. REQUIRE(peer_actor->uploaded_blocks.size() == 1);
  913. auto &peer_res = *peer_actor->uploaded_blocks.front();
  914. CHECK(peer_res.id() == 1);
  915. CHECK(peer_res.code() == proto::ErrorCode::NO_BEP_ERROR);
  916. CHECK(peer_res.data() == "12345");
  917. }
  918. }
  919. };
  920. F(true, 10).run();
  921. }
  922. int _init() {
  923. REGISTER_TEST_CASE(test_startup, "test_startup", "[net]");
  924. REGISTER_TEST_CASE(test_index_receiving, "test_index_receiving", "[net]");
  925. REGISTER_TEST_CASE(test_index_sending, "test_index_sending", "[net]");
  926. REGISTER_TEST_CASE(test_downloading, "test_downloading", "[net]");
  927. REGISTER_TEST_CASE(test_downloading_errors, "test_downloading_errors", "[net]");
  928. REGISTER_TEST_CASE(test_my_sharing, "test_my_sharing", "[net]");
  929. REGISTER_TEST_CASE(test_sending_index_updates, "test_sending_index_updates", "[net]");
  930. REGISTER_TEST_CASE(test_uploading, "test_uploading", "[net]");
  931. return 1;
  932. }
  933. static int v = _init();