blob: 29938eb62bd04f9a2e5473f627acd3b8578117d9 [file] [log] [blame]
Mickey Sweatt527b0492016-03-02 11:07:48 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3* Copyright (c) 2016 Regents of the University of California.
4*
5* This file is part of the nTorrent codebase.
6*
7* nTorrent is free software: you can redistribute it and/or modify it under the
8* terms of the GNU Lesser General Public License as published by the Free Software
9* Foundation, either version 3 of the License, or (at your option) any later version.
10*
11* nTorrent is distributed in the hope that it will be useful, but WITHOUT ANY
12* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14*
15* You should have received copies of the GNU General Public License and GNU Lesser
16* General Public License along with nTorrent, e.g., in COPYING.md file. If not, see
17* <http://www.gnu.org/licenses/>.
18*
19* See AUTHORS for complete list of nTorrent authors and contributors.
20*/
21
22#include "boost-test.hpp"
23
24#include "torrent-manager.hpp"
25#include "torrent-file.hpp"
spirosmastorakisa46eee42016-04-05 14:24:45 -070026#include "unit-test-time-fixture.hpp"
Mickey Sweatt527b0492016-03-02 11:07:48 -080027
Mickey Sweattafda1f12016-04-04 17:15:11 -070028#include <set>
29
Mickey Sweatt527b0492016-03-02 11:07:48 -080030#include <boost/filesystem.hpp>
31
spirosmastorakisa46eee42016-04-05 14:24:45 -070032#include <ndn-cxx/util/dummy-client-face.hpp>
Mickey Sweatt527b0492016-03-02 11:07:48 -080033#include <ndn-cxx/util/io.hpp>
34
35namespace ndn {
36namespace ntorrent {
37namespace tests {
38
39using std::vector;
40using ndn::Name;
spirosmastorakisa46eee42016-04-05 14:24:45 -070041using ndn::util::DummyClientFace;
Mickey Sweatt527b0492016-03-02 11:07:48 -080042
43namespace fs = boost::filesystem;
44
45class TestTorrentManager : public TorrentManager {
46 public:
47 TestTorrentManager(const ndn::Name& torrentFileName,
48 const std::string& filePath)
49 : TorrentManager(torrentFileName, filePath)
spirosmastorakisa46eee42016-04-05 14:24:45 -070050 {
51 }
52
53 TestTorrentManager(const ndn::Name& torrentFileName,
54 const std::string& filePath,
55 DummyClientFace& face)
56 : TorrentManager(torrentFileName, filePath, face)
57 {
58 }
Mickey Sweatt527b0492016-03-02 11:07:48 -080059
60 std::vector<TorrentFile> torrentSegments() const {
61 return m_torrentSegments;
62 }
63
64 std::vector<FileManifest> fileManifests() const {
65 return m_fileManifests;
66 }
67
spirosmastorakis50642f82016-04-08 12:11:18 -070068 void pushTorrentSegment(const TorrentFile& t) {
69 m_torrentSegments.push_back(t);
70 }
71
72 void pushFileManifestSegment(const FileManifest& m) {
73 m_fileManifests.push_back(m);
74 }
75
76 shared_ptr<Name> findTorrentFileSegmentToDownload() {
77 return TorrentManager::findTorrentFileSegmentToDownload();
78 }
79
80 shared_ptr<Name> findManifestSegmentToDownload(const Name& manifestName) {
81 return TorrentManager::findManifestSegmentToDownload(manifestName);
82 }
83
84 bool dataAlreadyDownloaded(const Name& name) {
85 return TorrentManager::dataAlreadyDownloaded(name);
86 }
87
Mickey Sweatt527b0492016-03-02 11:07:48 -080088 std::vector<bool> fileState(const ndn::Name& manifestName) {
Mickey Sweattafda1f12016-04-04 17:15:11 -070089 auto fout = m_fileStates[manifestName].first;
90 if (nullptr != fout) {
91 fout->flush();
92 }
Mickey Sweatt527b0492016-03-02 11:07:48 -080093 return m_fileStates[manifestName].second;
94 }
Mickey Sweattafda1f12016-04-04 17:15:11 -070095
spirosmastorakis50642f82016-04-08 12:11:18 -070096 void setFileState(const ndn::Name manifestName,
97 std::shared_ptr<fs::fstream> f,
98 const std::vector<bool>& stateVec) {
99
100 m_fileStates.insert({ manifestName, std::make_pair(f, stateVec) });
101 }
102
Mickey Sweattafda1f12016-04-04 17:15:11 -0700103 bool writeData(const Data& data) {
104 return TorrentManager::writeData(data);
105 }
Mickey Sweatt599bfef2016-04-05 19:11:20 -0700106
107 bool writeTorrentSegment(const TorrentFile& segment, const std::string& path) {
108 return TorrentManager::writeTorrentSegment(segment, path);
109 }
spirosmastorakis50642f82016-04-08 12:11:18 -0700110
Mickey Sweatt599bfef2016-04-05 19:11:20 -0700111 bool writeFileManifest(const FileManifest& manifest, const std::string& path) {
112 return TorrentManager::writeFileManifest(manifest, path);
113 }
Mickey Sweatt527b0492016-03-02 11:07:48 -0800114};
115
spirosmastorakisa46eee42016-04-05 14:24:45 -0700116class FaceFixture : public UnitTestTimeFixture
117{
118public:
119 explicit
120 FaceFixture(bool enableRegistrationReply = true)
121 : face(io, { true, enableRegistrationReply })
122 {
123 }
124
125public:
126 DummyClientFace face;
127};
128
129class FacesNoRegistrationReplyFixture : public FaceFixture
130{
131public:
132 FacesNoRegistrationReplyFixture()
133 : FaceFixture(false)
134 {
135 }
136};
137
Mickey Sweatt527b0492016-03-02 11:07:48 -0800138BOOST_AUTO_TEST_SUITE(TestTorrentManagerInitialize)
139
140BOOST_AUTO_TEST_CASE(CheckInitializeComplete)
141{
142 vector<FileManifest> manifests;
143 vector<TorrentFile> torrentSegments;
144 std::string filePath = "tests/testdata/";
145 // get torrent files and manifests
146 {
147 auto temp = TorrentFile::generate("tests/testdata/foo",
148 1024,
149 1024,
150 1024,
151 false);
152 torrentSegments = temp.first;
153 auto temp1 = temp.second;
154 for (const auto& ms : temp1) {
Mickey Sweattafda1f12016-04-04 17:15:11 -0700155 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
Mickey Sweatt527b0492016-03-02 11:07:48 -0800156 }
157 }
158 // write the torrent segments and manifests to disk
159 std::string dirPath = ".appdata/foo/";
160 boost::filesystem::create_directories(dirPath);
161 std::string torrentPath = dirPath + "torrent_files/";
162 boost::filesystem::create_directory(torrentPath);
163 auto fileNum = 0;
164 for (const auto& t : torrentSegments) {
165 fileNum++;
166 auto filename = torrentPath + to_string(fileNum);
167 io::save(t, filename);
168 }
Mickey Sweatt599bfef2016-04-05 19:11:20 -0700169 //fileNum = 0;
Mickey Sweatt527b0492016-03-02 11:07:48 -0800170 auto manifestPath = dirPath + "manifests/";
171 boost::filesystem::create_directory(manifestPath);
172 for (const auto& m : manifests) {
Mickey Sweatt599bfef2016-04-05 19:11:20 -0700173 fs::path filename = manifestPath + m.file_name() + "/" + to_string(m.submanifest_number());
174 boost::filesystem::create_directories(filename.parent_path());
175 io::save(m, filename.string());
Mickey Sweatt527b0492016-03-02 11:07:48 -0800176 }
177 // Initialize and verify
178 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253",
179 filePath);
180 manager.Initialize();
181
182 // Check that the torrent segments and file manifests match (content and order)
183 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
184 BOOST_CHECK(manager.fileManifests() == manifests);
185 // next check the data packet state vectors
186 for (auto m : manager.fileManifests()) {
187 auto fileState = manager.fileState(m.getFullName());
188 BOOST_CHECK(fileState.size() == m.catalog().size());
189 for (auto s : fileState) {
190 BOOST_CHECK(s);
191 }
192 }
193 fs::remove_all(dirPath);
194}
195
196BOOST_AUTO_TEST_CASE(CheckInitializeEmpty)
197{
198 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253",
199 "tests/testdata/");
200 manager.Initialize();
201 BOOST_CHECK(manager.torrentSegments() == vector<TorrentFile>());
202 BOOST_CHECK(manager.fileManifests() == vector<FileManifest>());
203}
204
205BOOST_AUTO_TEST_CASE(CheckInitializeNoManifests)
206{
207 vector<TorrentFile> torrentSegments;
208 std::string filePath = "tests/testdata/";
209 // get torrent files and manifests
210 {
211 auto temp = TorrentFile::generate("tests/testdata/foo",
212 1024,
213 1024,
214 1024,
215 false);
216 torrentSegments = temp.first;
217 }
218 // write the torrent segments but no manifests to disk
219 std::string dirPath = ".appdata/foo/";
220 boost::filesystem::create_directories(dirPath);
221 std::string torrentPath = dirPath + "torrent_files/";
222 boost::filesystem::create_directory(torrentPath);
223 auto fileNum = 0;
224 for (const auto& t : torrentSegments) {
225 fileNum++;
226 auto filename = torrentPath + to_string(fileNum);
227 io::save(t, filename);
228 }
229 // Initialize and verify
230 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253",
231 filePath);
232 manager.Initialize();
233
234 // Check that the torrent segments and file manifests match (content and order)
235 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
236 BOOST_CHECK(manager.fileManifests() == vector<FileManifest>());
237
238 fs::remove_all(dirPath);
239}
240
241BOOST_AUTO_TEST_CASE(CheckInitializeMissingManifests)
242{
243 vector<FileManifest> manifests;
244 vector<TorrentFile> torrentSegments;
245 std::string filePath = "tests/testdata/";
246 // get torrent files and manifests
247 {
248 auto temp = TorrentFile::generate("tests/testdata/foo",
249 1024,
250 1024,
251 1024,
252 false);
253 torrentSegments = temp.first;
254 auto temp1 = temp.second;
255 temp1.pop_back(); // remove the manifests for the last file
Mickey Sweattafda1f12016-04-04 17:15:11 -0700256 for (const auto& ms : temp1) {
257 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
Mickey Sweatt527b0492016-03-02 11:07:48 -0800258 }
259 }
260 // write the torrent segments and manifests to disk
261 std::string dirPath = ".appdata/foo/";
262 boost::filesystem::create_directories(dirPath);
263 std::string torrentPath = dirPath + "torrent_files/";
264 boost::filesystem::create_directories(torrentPath);
265 auto fileNum = 0;
266 for (const auto& t : torrentSegments) {
267 fileNum++;
268 auto filename = torrentPath + to_string(fileNum);
269 io::save(t, filename);
Mickey Sweatt527b0492016-03-02 11:07:48 -0800270 }
Mickey Sweatt527b0492016-03-02 11:07:48 -0800271 auto manifestPath = dirPath + "manifests/";
272 boost::filesystem::create_directory(manifestPath);
273 for (const auto& m : manifests) {
Mickey Sweatt599bfef2016-04-05 19:11:20 -0700274 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
275 boost::filesystem::create_directory(filename.parent_path());
276 io::save(m, filename.string());
Mickey Sweatt527b0492016-03-02 11:07:48 -0800277 }
278 // Initialize and verify
279 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253",
280 filePath);
281 manager.Initialize();
282
283 // Check that the torrent segments and file manifests match (content and order)
284 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
285 BOOST_CHECK(manager.fileManifests() == manifests);
286 // next check the data packet state vectors
287 for (auto m : manager.fileManifests()) {
288 auto fileState = manager.fileState(m.getFullName());
289 BOOST_CHECK(fileState.size() == m.catalog().size());
290 for (auto s : fileState) {
291 BOOST_CHECK(s);
292 }
293 }
294 fs::remove_all(dirPath);
295}
296
spirosmastorakisa46eee42016-04-05 14:24:45 -0700297BOOST_FIXTURE_TEST_SUITE(TestTorrentManagerNetworkingStuff, FaceFixture)
298
299BOOST_AUTO_TEST_CASE(TestDownloadingTorrentFile)
300{
301 vector<FileManifest> manifests;
302 vector<TorrentFile> torrentSegments;
303 std::string filePath = ".appdata/foo/";
304 // get torrent files and manifests
305 {
306 auto temp = TorrentFile::generate("tests/testdata/foo", 1, 10, 10, false);
307
308 torrentSegments = temp.first;
309 auto temp1 = temp.second;
310 temp1.pop_back(); // remove the manifests for the last file
311 for (const auto& ms : temp1) {
312 for (const auto& m : ms.first) {
313 manifests.push_back(m);
314 }
315 }
316 }
317
318 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=946b92641d2b87bf4f5913930be20e3789ff5fb5d72739614f93f677d90fbd9d",
319 filePath, face);
320 manager.Initialize();
321
322 // Test download torrent file segments
323 uint32_t counter = 0;
spirosmastorakis50642f82016-04-08 12:11:18 -0700324 manager.downloadTorrentFile(filePath + "torrent_files", [&counter, &torrentSegments]
325 (const std::vector<ndn::Name>& vec) {
326 uint32_t manifestNum = 0;
327 for (auto i = vec.begin(); i != vec.end(); i++) {
328 Name n = torrentSegments[counter].getCatalog()[manifestNum];
329 BOOST_CHECK_EQUAL(n, *i);
330 manifestNum++;
331 }
332 counter++;
333 },
334 bind([] {
335 BOOST_FAIL("Unexpected failure");
336 }));
spirosmastorakisa46eee42016-04-05 14:24:45 -0700337
338 for (auto i = torrentSegments.begin(); i != torrentSegments.end(); i++) {
339 advanceClocks(time::milliseconds(1), 40);
340 face.receive(dynamic_cast<Data&>(*i));
341 }
342
343 fs::remove_all(filePath);
spirosmastorakis50642f82016-04-08 12:11:18 -0700344 fs::remove_all(".appdata");
spirosmastorakisa46eee42016-04-05 14:24:45 -0700345}
346
347BOOST_AUTO_TEST_CASE(TestDownloadingFileManifests)
348{
349 vector<FileManifest> manifests;
350 vector<TorrentFile> torrentSegments;
351 std::string filePath = ".appdata/foo/";
352 // get torrent files and manifests
353 {
354 auto temp = TorrentFile::generate("tests/testdata/foo", 1, 10, 10, false);
355
356 torrentSegments = temp.first;
357 auto temp1 = temp.second;
358 temp1.pop_back(); // remove the manifests for the last file
359 for (const auto& ms : temp1) {
360 for (const auto& m : ms.first) {
361 manifests.push_back(m);
362 }
363 }
364 }
365
366 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=946b92641d2b87bf4f5913930be20e3789ff5fb5d72739614f93f677d90fbd9d",
367 filePath, face);
368 manager.Initialize();
369
370 // Test download manifest segments -- 2 files (the first one segment, the second multiple)
371 int counter = 0;
372 manager.download_file_manifest(manifests[0].getFullName(), filePath + "manifests",
373 [&counter, &manifests]
374 (const std::vector<ndn::Name>& vec) {
375 uint32_t packetIndex = 0;
376 for (auto j = vec.begin(); j != vec.end(); j++) {
377 BOOST_CHECK_EQUAL(manifests[counter].catalog()[packetIndex],
378 *j);
379 packetIndex++;
380 }
381 counter++;
382 },
383 [](const ndn::Name& name, const std::string& reason) {
384 BOOST_FAIL("Unexpected failure");
385 });
386
387 advanceClocks(time::milliseconds(1), 40);
388 face.receive(dynamic_cast<Data&>(manifests[0]));
389
390 manager.download_file_manifest(manifests[1].getFullName(), filePath + "manifests",
391 [&counter, &manifests]
392 (const std::vector<ndn::Name>& vec) {
393 uint32_t packetIndex = 0;
394 for (auto j = vec.begin(); j != vec.end(); j++) {
395 BOOST_CHECK_EQUAL(manifests[counter].catalog()[packetIndex],
396 *j);
397 // if we have read all the packet names from a
398 // segment, move to the next one
399 if (packetIndex == manifests[counter].catalog().size() - 1) {
400 packetIndex = 0;
401 counter++;
402 }
403 else {
404 packetIndex++;
405 }
406 }
407 },
408 [](const ndn::Name& name, const std::string& reason) {
409 BOOST_FAIL("Unexpected failure");
410 });
411
412 for (auto i = manifests.begin() + 1; i != manifests.end(); i++) {
413 advanceClocks(time::milliseconds(1), 40);
414 face.receive(dynamic_cast<Data&>(*i));
415 }
416
417 fs::remove_all(filePath);
spirosmastorakis50642f82016-04-08 12:11:18 -0700418 fs::remove_all(".appdata");
spirosmastorakisa46eee42016-04-05 14:24:45 -0700419}
420
421BOOST_AUTO_TEST_CASE(TestDownloadingDataPackets)
422{
423 std::string filePath = ".appdata/foo/";
424 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=946b92641d2b87bf4f5913930be20e3789ff5fb5d72739614f93f677d90fbd9d",
425 filePath, face);
426 manager.Initialize();
427
428 Name dataName("/test/ucla");
429
430 // Download data successfully
431 manager.download_data_packet(dataName,
432 [&dataName] (const ndn::Name& name) {
433 BOOST_CHECK_EQUAL(name, dataName);
434 },
435 [](const ndn::Name& name, const std::string& reason) {
436 BOOST_FAIL("Unexpected failure");
437 });
438
439 auto data = make_shared<Data>(dataName);
440 SignatureSha256WithRsa fakeSignature;
441 fakeSignature.setValue(encoding::makeEmptyBlock(tlv::SignatureValue));
442 data->setSignature(fakeSignature);
443 data->wireEncode();
444
445 advanceClocks(time::milliseconds(1), 40);
446 face.receive(*data);
447
448 // Fail to download data
449 manager.download_data_packet(dataName,
spirosmastorakis50642f82016-04-08 12:11:18 -0700450 [](const ndn::Name& name) {
spirosmastorakisa46eee42016-04-05 14:24:45 -0700451 BOOST_FAIL("Unexpected failure");
452 },
453 [&dataName](const ndn::Name& name, const std::string& reason) {
454 BOOST_CHECK_EQUAL(name, dataName);
455 });
456
457 advanceClocks(time::milliseconds(1), 2100);
458
459 fs::remove_all(filePath);
spirosmastorakis50642f82016-04-08 12:11:18 -0700460 fs::remove_all(".appdata");
461}
462
463// we already have downloaded the torrent file
464BOOST_AUTO_TEST_CASE(TestFindTorrentFileSegmentToDownload1)
465{
466 std::string filePath = ".appdata/foo/";
467 TestTorrentManager manager("NTORRENT/test/torrent-file/sha256digest",
468 filePath, face);
469 manager.Initialize();
470
471 TorrentFile t1(Name("NTORRENT/test/torrent-file/sha256digest"),
472 Name("NTORRENT/test/torrent-file/1/sha256digest"), Name("/test"),
473 { Name("/manifest1") });
474 manager.pushTorrentSegment(t1);
475
476 TorrentFile t2(Name("NTORRENT/test/torrent-file/1/sha256digest"),
477 Name("NTORRENT/test/torrent-file/2/sha256digest"), Name("/test"),
478 { Name("/manifest2"), Name("/manifest3") });
479 manager.pushTorrentSegment(t2);
480
481 TorrentFile t3(Name("NTORRENT/test/torrent-file/3/sha256digest"),
482 Name("NTORRENT/test/torrent-file/4/sha256digest"), Name("/test"),
483 { Name("/manifest4"), Name("/manifest5") });
484 manager.pushTorrentSegment(t3);
485
486 TorrentFile t4(Name("NTORRENT/test/torrent-file/4/sha256digest"), Name("/test"), {});
487 manager.pushTorrentSegment(t4);
488
489 BOOST_CHECK(!(manager.findTorrentFileSegmentToDownload()));
490
491 std::vector<Name> manifests;
492 manifests = manager.downloadTorrentFile("/test");
493
494 BOOST_CHECK_EQUAL(manifests[0].toUri(), "/manifest1");
495 BOOST_CHECK_EQUAL(manifests[1].toUri(), "/manifest2");
496 BOOST_CHECK_EQUAL(manifests[2].toUri(), "/manifest3");
497 BOOST_CHECK_EQUAL(manifests[3].toUri(), "/manifest4");
498 BOOST_CHECK_EQUAL(manifests[4].toUri(), "/manifest5");
499
500 fs::remove_all(filePath);
501 fs::remove_all(".appdata");
502}
503
504// we do not have the torrent file
505BOOST_AUTO_TEST_CASE(TestFindTorrentFileSegmentToDownload2)
506{
507 std::string filePath = ".appdata/foo/";
508 TestTorrentManager manager("/test/0/sha256digest",
509 filePath, face);
510 manager.Initialize();
511
512 BOOST_CHECK_EQUAL(manager.findTorrentFileSegmentToDownload()->toUri(), "/test/0/sha256digest");
513
514 fs::remove_all(filePath);
515 fs::remove_all(".appdata");
516}
517
518// we have the torrent file and the manifests
519BOOST_AUTO_TEST_CASE(TestFindTorrentFileSegmentToDownload3)
520{
521 vector<FileManifest> manifests;
522 vector<TorrentFile> torrentSegments;
523 // for each file, the data packets
524 std::vector<vector<Data>> fileData;
525 std::string filePath = "tests/testdata/temp";
526 // get torrent files and manifests
527 {
528 auto temp = TorrentFile::generate("tests/testdata/foo",
529 1024,
530 2048,
531 8192,
532 true);
533 torrentSegments = temp.first;
534 auto temp1 = temp.second;
535 for (const auto& ms : temp1) {
536 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
537 fileData.push_back(ms.second);
538 }
539 }
540 // write the torrent segments and manifests to disk
541 std::string dirPath = ".appdata/foo/";
542 boost::filesystem::create_directories(dirPath);
543 std::string torrentPath = dirPath + "torrent_files/";
544 boost::filesystem::create_directories(torrentPath);
545 auto fileNum = 0;
546 for (const auto& t : torrentSegments) {
547 fileNum++;
548 auto filename = torrentPath + to_string(fileNum);
549 io::save(t, filename);
550 }
551
552 auto manifestPath = dirPath + "manifests/";
553 boost::filesystem::create_directory(manifestPath);
554 for (const auto& m : manifests) {
555 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
556 boost::filesystem::create_directory(filename.parent_path());
557 io::save(m, filename.string());
558 }
559 // Initialize manager
560 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=a8a2e98cd943d895b8c4b12a208343bcf9344ce85a6376dc6f5754fe8f4a573e",
561 filePath);
562 manager.Initialize();
563
564 // Set the file state
565 std::vector<bool> v1 = {true};
566 manager.setFileState(manifests[0].getFullName(), make_shared<fs::fstream>(), v1);
567
568 std::vector<bool> v2 = {false, true, true, false, false, false};
569 manager.setFileState(manifests[1].getFullName(), make_shared<fs::fstream>(), v2);
570
571 std::vector<bool> v3 = {true, false, false, false, false, false};
572 manager.setFileState(manifests[2].getFullName(), make_shared<fs::fstream>(), v3);
573
574 manager.downloadTorrentFile(filePath + "torrent_files/",
575 [&manifests](const std::vector<ndn::Name>& vec) {
576 BOOST_CHECK_EQUAL(vec[0].toUri(),
577 manifests[1].catalog()[0].toUri());
578 BOOST_CHECK_EQUAL(vec[1].toUri(),
579 manifests[1].catalog()[3].toUri());
580 BOOST_CHECK_EQUAL(vec[2].toUri(),
581 manifests[1].catalog()[4].toUri());
582 BOOST_CHECK_EQUAL(vec[3].toUri(),
583 manifests[1].catalog()[5].toUri());
584 BOOST_CHECK_EQUAL(vec[4].toUri(),
585 manifests[2].catalog()[1].toUri());
586 BOOST_CHECK_EQUAL(vec[5].toUri(),
587 manifests[2].catalog()[2].toUri());
588 BOOST_CHECK_EQUAL(vec[6].toUri(),
589 manifests[2].catalog()[3].toUri());
590 BOOST_CHECK_EQUAL(vec[7].toUri(),
591 manifests[2].catalog()[4].toUri());
592 BOOST_CHECK_EQUAL(vec[8].toUri(),
593 manifests[2].catalog()[5].toUri());
594 },
595 [](const ndn::Name& name, const std::string& reason) {
596 BOOST_FAIL("Unexpected failure");
597 });
598
599 fs::remove_all(filePath);
600 fs::remove_all(".appdata");
601}
602
603
604BOOST_AUTO_TEST_CASE(TestFindManifestSegmentToDownload1)
605{
606 std::string filePath = ".appdata/foo/";
607 TestTorrentManager manager("NTORRENT/test/sha256digest",
608 filePath, face);
609 manager.Initialize();
610
611 Name n1(Name("NTORRENT/test/file0"));
612 n1.appendSequenceNumber(0);
613
614 Name n2(Name("NTORRENT/test/file0"));
615 n2.appendSequenceNumber(1);
616
617 Name n3(Name("NTORRENT/test/file0"));
618 n3.appendSequenceNumber(2);
619
620 Name n4(Name("NTORRENT/test/file0"));
621 n4.appendSequenceNumber(3);
622
623 Name n5(Name("NTORRENT/test/file0"));
624 n5.appendSequenceNumber(4);
625
626 Name n6(Name("NTORRENT/test1/file0"));
627 n6.appendSequenceNumber(0);
628
629 Name n7(Name("NTORRENT/test1/file0"));
630 n7.appendSequenceNumber(1);
631
632 // In theory, this may not be correct, but here let's suck it up for the sake
633 // of testing the function correctness
634 Name n8(Name("NTORRENT/test1/file2"));
635 n8.appendSequenceNumber(0);
636
637 Name n9(Name("NTORRENT/test1/file2"));
638 n9.appendSequenceNumber(1);
639
640 FileManifest f1(n1, 50, Name("NTORRENT/test"), {}, make_shared<Name>(n2));
641 manager.pushFileManifestSegment(f1);
642
643 FileManifest f2(n2, 50, Name("NTORRENT/test"), {}, make_shared<Name>(n3));
644 manager.pushFileManifestSegment(f2);
645
646 FileManifest f3(n3, 50, Name("NTORRENT/test"), {}, make_shared<Name>(n4));
647 manager.pushFileManifestSegment(f3);
648
649 FileManifest f4(n4, 50, Name("NTORRENT/test"), {}, make_shared<Name>(n5));
650 manager.pushFileManifestSegment(f4);
651
652 FileManifest f5(n6, 50, Name("NTORRENT/test2"), {}, make_shared<Name>(n7));
653 manager.pushFileManifestSegment(f5);
654
655 FileManifest f6(n7, 50, Name("NTORRENT/test2"), {}, {});
656 manager.pushFileManifestSegment(f6);
657
658 FileManifest f7(n8, 50, Name("NTORRENT/test3"), {}, make_shared<Name>(n9));
659 manager.pushFileManifestSegment(f7);
660
661 BOOST_CHECK_EQUAL(manager.findManifestSegmentToDownload(Name(n2.toUri() + "/sha256digest"))->toUri(), n5.toUri());
662 BOOST_CHECK_EQUAL(manager.findManifestSegmentToDownload(Name(n8.toUri() + "/sha256digest"))->toUri(), n9.toUri());
663 BOOST_CHECK_EQUAL(manager.findManifestSegmentToDownload(Name(n5.toUri() + "/sha256digest"))->toUri(),
664 Name(n5.toUri() + "/sha256digest").toUri());
665 BOOST_CHECK(!(manager.findManifestSegmentToDownload(Name(n7.toUri() + "/sha256digest"))));
666
667 Name n10(Name("NTORRENT/test1/file1"));
668 n10.appendSequenceNumber(1);
669 n10 = Name(n10.toUri() + "/sha256digest");
670
671 BOOST_CHECK_EQUAL(manager.findManifestSegmentToDownload(n10)->toUri(), n10.toUri());
672
673 fs::remove_all(filePath);
674 fs::remove_all(".appdata");
675}
676
677BOOST_AUTO_TEST_CASE(TestFindManifestSegmentToDownload2)
678{
679 vector<FileManifest> manifests;
680 vector<TorrentFile> torrentSegments;
681 // for each file, the data packets
682 std::vector<vector<Data>> fileData;
683 std::string filePath = "tests/testdata/temp";
684 // get torrent files and manifests
685 {
686 auto temp = TorrentFile::generate("tests/testdata/foo",
687 1024,
688 2048,
689 8192,
690 true);
691 torrentSegments = temp.first;
692 auto temp1 = temp.second;
693 for (const auto& ms : temp1) {
694 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
695 fileData.push_back(ms.second);
696 }
697 }
698 // write the torrent segments and manifests to disk
699 std::string dirPath = ".appdata/foo/";
700 boost::filesystem::create_directories(dirPath);
701 std::string torrentPath = dirPath + "torrent_files/";
702 boost::filesystem::create_directories(torrentPath);
703 auto fileNum = 0;
704 for (const auto& t : torrentSegments) {
705 fileNum++;
706 auto filename = torrentPath + to_string(fileNum);
707 io::save(t, filename);
708 }
709
710 auto manifestPath = dirPath + "manifests/";
711 boost::filesystem::create_directory(manifestPath);
712 for (const auto& m : manifests) {
713 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
714 boost::filesystem::create_directory(filename.parent_path());
715 io::save(m, filename.string());
716 }
717 // Initialize manager
718 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=a8a2e98cd943d895b8c4b12a208343bcf9344ce85a6376dc6f5754fe8f4a573e",
719 filePath);
720 manager.Initialize();
721
722 // Set the file state
723 std::vector<bool> v1 = {true};
724 manager.setFileState(manifests[0].getFullName(), make_shared<fs::fstream>(), v1);
725
726 std::vector<bool> v2 = {false, true, true, false, false, false};
727 manager.setFileState(manifests[1].getFullName(), make_shared<fs::fstream>(), v2);
728
729 std::vector<bool> v3 = {true, false, false, false, false, false};
730 manager.setFileState(manifests[2].getFullName(), make_shared<fs::fstream>(), v3);
731
732 manager.download_file_manifest(manifests[0].getFullName(), filePath + "manifests",
733 [&manifests](const std::vector<ndn::Name>& vec) {
734 BOOST_CHECK_EQUAL(vec.size(), 0);
735 },
736 [](const ndn::Name& name, const std::string& reason) {
737 BOOST_FAIL("Unexpected failure");
738 });
739
740 manager.download_file_manifest(manifests[1].getFullName(), filePath + "manifests",
741 [&manifests](const std::vector<ndn::Name>& vec) {
742 BOOST_CHECK_EQUAL(vec[0].toUri(),
743 manifests[1].catalog()[0].toUri());
744 BOOST_CHECK_EQUAL(vec[1].toUri(),
745 manifests[1].catalog()[3].toUri());
746 BOOST_CHECK_EQUAL(vec[2].toUri(),
747 manifests[1].catalog()[4].toUri());
748 BOOST_CHECK_EQUAL(vec[3].toUri(),
749 manifests[1].catalog()[5].toUri());
750 },
751 [](const ndn::Name& name, const std::string& reason) {
752 BOOST_FAIL("Unexpected failure");
753 });
754
755 manager.download_file_manifest(manifests[2].getFullName(), filePath + "manifests",
756 [&manifests](const std::vector<ndn::Name>& vec) {
757 BOOST_CHECK_EQUAL(vec[0].toUri(),
758 manifests[2].catalog()[1].toUri());
759 BOOST_CHECK_EQUAL(vec[1].toUri(),
760 manifests[2].catalog()[2].toUri());
761 BOOST_CHECK_EQUAL(vec[2].toUri(),
762 manifests[2].catalog()[3].toUri());
763 BOOST_CHECK_EQUAL(vec[3].toUri(),
764 manifests[2].catalog()[4].toUri());
765 BOOST_CHECK_EQUAL(vec[4].toUri(),
766 manifests[2].catalog()[5].toUri());
767 },
768 [](const ndn::Name& name, const std::string& reason) {
769 BOOST_FAIL("Unexpected failure");
770 });
771 fs::remove_all(filePath);
772 fs::remove_all(".appdata");
773}
774
775BOOST_AUTO_TEST_CASE(TestDataAlreadyDownloaded)
776{
777 vector<FileManifest> manifests;
778 vector<TorrentFile> torrentSegments;
779 // for each file, the data packets
780 std::vector<vector<Data>> fileData;
781 std::string filePath = "tests/testdata/temp";
782 // get torrent files and manifests
783 {
784 auto temp = TorrentFile::generate("tests/testdata/foo",
785 1024,
786 2048,
787 8192,
788 true);
789 torrentSegments = temp.first;
790 auto temp1 = temp.second;
791 for (const auto& ms : temp1) {
792 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
793 fileData.push_back(ms.second);
794 }
795 }
796 // write the torrent segments and manifests to disk
797 std::string dirPath = ".appdata/foo/";
798 boost::filesystem::create_directories(dirPath);
799 std::string torrentPath = dirPath + "torrent_files/";
800 boost::filesystem::create_directories(torrentPath);
801 auto fileNum = 0;
802 for (const auto& t : torrentSegments) {
803 fileNum++;
804 auto filename = torrentPath + to_string(fileNum);
805 io::save(t, filename);
806 }
807
808 auto manifestPath = dirPath + "manifests/";
809 boost::filesystem::create_directory(manifestPath);
810 for (const auto& m : manifests) {
811 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
812 boost::filesystem::create_directory(filename.parent_path());
813 io::save(m, filename.string());
814 }
815 // Initialize manager
816 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=a8a2e98cd943d895b8c4b12a208343bcf9344ce85a6376dc6f5754fe8f4a573e",
817 filePath);
818 manager.Initialize();
819
820 // Set the file state
821 std::vector<bool> v1 = {true};
822 manager.setFileState(manifests[0].getFullName(), make_shared<fs::fstream>(), v1);
823
824 std::vector<bool> v2 = {false, true, true, false, false, false};
825 manager.setFileState(manifests[1].getFullName(), make_shared<fs::fstream>(), v2);
826
827 std::vector<bool> v3 = {true, false, false, false, false, false};
828 manager.setFileState(manifests[2].getFullName(), make_shared<fs::fstream>(), v3);
829
830 Name p1("NTORRENT/foo/bar1.txt");
831 p1.appendSequenceNumber(0);
832 p1.appendSequenceNumber(0);
833 p1 = Name(p1.toUri() + "/sha256digest");
834
835 BOOST_CHECK(!(manager.dataAlreadyDownloaded(p1)));
836
837 Name p2("NTORRENT/foo/bar.txt");
838 p2.appendSequenceNumber(0);
839 p2.appendSequenceNumber(0);
840 p2 = Name(p2.toUri() + "/sha256digest");
841
842 BOOST_CHECK(manager.dataAlreadyDownloaded(p2));
spirosmastorakisa46eee42016-04-05 14:24:45 -0700843}
844
Mickey Sweatt527b0492016-03-02 11:07:48 -0800845BOOST_AUTO_TEST_SUITE_END()
846
Mickey Sweattafda1f12016-04-04 17:15:11 -0700847BOOST_AUTO_TEST_SUITE(CheckTorrentManagerUtilities)
848
849BOOST_AUTO_TEST_CASE(CheckWriteDataComplete)
850{
851 vector<FileManifest> manifests;
852 vector<TorrentFile> torrentSegments;
853 // for each file, the data packets
854 std::vector<vector<Data>> fileData;
855 std::string filePath = "tests/testdata/temp";
856 // get torrent files and manifests
857 {
858 auto temp = TorrentFile::generate("tests/testdata/foo",
859 1024,
860 1024,
861 1024,
862 true);
863 torrentSegments = temp.first;
864 auto temp1 = temp.second;
865 for (const auto& ms : temp1) {
866 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
867 fileData.push_back(ms.second);
868 }
869 }
870 // write the torrent segments and manifests to disk
871 std::string dirPath = ".appdata/foo/";
872 boost::filesystem::create_directories(dirPath);
873 std::string torrentPath = dirPath + "torrent_files/";
874 boost::filesystem::create_directories(torrentPath);
875 auto fileNum = 0;
876 for (const auto& t : torrentSegments) {
877 fileNum++;
878 auto filename = torrentPath + to_string(fileNum);
879 io::save(t, filename);
880 }
Mickey Sweatt599bfef2016-04-05 19:11:20 -0700881 //fileNum = 0;
Mickey Sweattafda1f12016-04-04 17:15:11 -0700882 auto manifestPath = dirPath + "manifests/";
883 boost::filesystem::create_directory(manifestPath);
884 for (const auto& m : manifests) {
Mickey Sweatt599bfef2016-04-05 19:11:20 -0700885 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
886 boost::filesystem::create_directory(filename.parent_path());
887 io::save(m, filename.string());
Mickey Sweattafda1f12016-04-04 17:15:11 -0700888 }
889 // Initialize manager
890 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253",
891 filePath);
892 manager.Initialize();
893 // check that initially there is no data on disk
894 for (auto m : manager.fileManifests()) {
895 auto fileState = manager.fileState(m.getFullName());
896 BOOST_CHECK(fileState.empty());
897 }
898 // write all data to disk (for each file manifest)
899 auto manifest_it = manifests.begin();
900 for (auto& data : fileData) {
901 for (auto& d : data) {
902 BOOST_CHECK(manager.writeData(d));
903 }
spirosmastorakis50642f82016-04-08 12:11:18 -0700904 // check that the state is updated appropriately
Mickey Sweattafda1f12016-04-04 17:15:11 -0700905 auto fileState = manager.fileState(manifest_it->getFullName());
906 for (auto s : fileState) {
907 BOOST_CHECK(s);
908 }
909 ++manifest_it;
910 }
911 // get the file names (ascending)
912 std::set<std::string> fileNames;
913 for (auto i = fs::recursive_directory_iterator(filePath + "/foo");
914 i != fs::recursive_directory_iterator();
915 ++i) {
916 fileNames.insert(i->path().string());
917 }
918 // verify file by file that the data packets are written correctly
919 auto f_it = fileData.begin();
920 for (auto f : fileNames) {
921 // read file from disk
922 std::vector<uint8_t> file_bytes;
923 fs::ifstream is(f, fs::ifstream::binary | fs::ifstream::in);
924 is >> std::noskipws;
925 std::istream_iterator<uint8_t> start(is), end;
926 file_bytes.insert(file_bytes.end(), start, end);
927 std::vector<uint8_t> data_bytes;
928 // get content from data packets
929 for (const auto& d : *f_it) {
930 auto content = d.getContent();
931 data_bytes.insert(data_bytes.end(), content.value_begin(), content.value_end());
932 }
933 BOOST_CHECK(data_bytes == file_bytes);
934 ++f_it;
935 }
936 fs::remove_all(filePath);
937 fs::remove_all(".appdata");
938}
939
Mickey Sweatt599bfef2016-04-05 19:11:20 -0700940BOOST_AUTO_TEST_CASE(CheckWriteTorrentComplete)
941{
942 const struct {
943 const char *d_directoryPath;
944 const char *d_initialSegmentName;
945 size_t d_namesPerSegment;
946 size_t d_subManifestSize;
947 size_t d_dataPacketSize;
948 } DATA [] = {
949 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
950 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=96d900d6788465f9a7b00191581b004c910d74b3762d141ec0e82173731bc9f4", 1, 1, 1024},
951 };
952 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
953 for (int i = 0; i < NUM_DATA; ++i) {
954 auto directoryPath = DATA[i].d_directoryPath;
955 Name initialSegmentName = DATA[i].d_initialSegmentName;
956 auto namesPerSegment = DATA[i].d_namesPerSegment;
957 auto dataPacketSize = DATA[i].d_dataPacketSize;
958 auto subManifestSize = DATA[i].d_subManifestSize;
959
960 vector<TorrentFile> torrentSegments;
961 std::string filePath = "tests/testdata/temp";
962 // get torrent files
963 {
964 auto temp = TorrentFile::generate(directoryPath,
965 namesPerSegment,
966 subManifestSize,
967 dataPacketSize,
968 false);
969 torrentSegments = temp.first;
970 }
971 // Initialize manager
972 TestTorrentManager manager(initialSegmentName,
973 filePath);
974 manager.Initialize();
975 std::string dirPath = ".appdata/foo/";
976 std::string torrentPath = dirPath + "torrent_files/";
977 BOOST_CHECK(manager.torrentSegments().empty());
978 for (const auto& t : torrentSegments) {
979 BOOST_CHECK(manager.writeTorrentSegment(t, torrentPath));
980 }
981 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
982 // check that initializing a new manager also gets all the torrent torrentSegments
983 TestTorrentManager manager2(initialSegmentName,
984 filePath);
985 manager2.Initialize();
986 BOOST_CHECK(manager2.torrentSegments() == torrentSegments);
987
988 // start anew
989 fs::remove_all(torrentPath);
990 fs::create_directories(torrentPath);
991 manager.Initialize();
992 BOOST_CHECK(manager.torrentSegments().empty());
993
994 // check that there is no dependence on the order of torrent segments
995 // randomize the order of the torrent segments
996 auto torrentSegmentsRandom = torrentSegments;
997 std::random_shuffle(torrentSegmentsRandom.begin(), torrentSegmentsRandom.end());
998 for (const auto& t : torrentSegmentsRandom) {
999 BOOST_CHECK(manager.writeTorrentSegment(t, torrentPath));
1000 }
1001 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
1002 fs::remove_all(".appdata");
1003 }
1004}
1005
1006BOOST_AUTO_TEST_CASE(CheckWriteManifestComplete)
1007{
1008 std::string dirPath = ".appdata/foo/";
1009 std::string torrentPath = dirPath + "torrent_files/";
1010 std::string manifestPath = dirPath + "manifests/";
1011
1012 const struct {
1013 const char *d_directoryPath;
1014 const char *d_initialSegmentName;
1015 size_t d_namesPerSegment;
1016 size_t d_subManifestSize;
1017 size_t d_dataPacketSize;
1018 } DATA [] = {
1019 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
1020 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 128, 128, 1024},
1021 };
1022 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
1023 for (int i = 0; i < NUM_DATA; ++i) {
1024 auto directoryPath = DATA[i].d_directoryPath;
1025 Name initialSegmentName = DATA[i].d_initialSegmentName;
1026 auto namesPerSegment = DATA[i].d_namesPerSegment;
1027 auto dataPacketSize = DATA[i].d_dataPacketSize;
1028 auto subManifestSize = DATA[i].d_subManifestSize;
1029
1030 vector<FileManifest> manifests;
1031 vector<TorrentFile> torrentSegments;
1032
1033 std::string filePath = "tests/testdata/temp";
1034 // get torrent files and manifests
1035 {
1036 auto temp = TorrentFile::generate(directoryPath,
1037 namesPerSegment,
1038 subManifestSize,
1039 dataPacketSize,
1040 false);
1041 torrentSegments = temp.first;
1042 auto temp1 = temp.second;
1043 for (const auto& ms : temp1) {
1044 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
1045 }
1046 }
1047 TestTorrentManager manager(initialSegmentName,
1048 filePath);
1049 manager.Initialize();
1050 for (const auto& t : torrentSegments) {
1051 manager.writeTorrentSegment(t, torrentPath);
1052 }
1053
1054 BOOST_CHECK(manager.fileManifests().empty());
1055 for (const auto& m : manifests) {
1056 BOOST_CHECK(manager.writeFileManifest(m, manifestPath));
1057 }
1058 BOOST_CHECK(manager.fileManifests() == manifests);
1059
1060 TestTorrentManager manager2(initialSegmentName,
1061 filePath);
1062
1063 manager2.Initialize();
1064 BOOST_CHECK(manager2.fileManifests() == manifests);
1065
1066 // start anew
1067 fs::remove_all(manifestPath);
1068 fs::create_directories(manifestPath);
1069 manager.Initialize();
1070 BOOST_CHECK(manager.fileManifests().empty());
1071
1072 // check that there is no dependence on the order of torrent segments
1073 // randomize the order of the torrent segments
1074 auto fileManifestsRandom = manifests;
1075 std::random_shuffle(fileManifestsRandom.begin(), fileManifestsRandom.end());
1076 for (const auto& m : fileManifestsRandom) {
1077 BOOST_CHECK(manager.writeFileManifest(m, manifestPath));
1078 }
1079 BOOST_CHECK(manager2.fileManifests() == manifests);
1080 fs::remove_all(".appdata");
1081 }
1082}
1083
spirosmastorakisa46eee42016-04-05 14:24:45 -07001084BOOST_AUTO_TEST_SUITE_END()
Mickey Sweattafda1f12016-04-04 17:15:11 -07001085
1086BOOST_AUTO_TEST_SUITE_END()
1087
Mickey Sweatt527b0492016-03-02 11:07:48 -08001088} // namespace tests
1089} // namespace nTorrent
spirosmastorakisa46eee42016-04-05 14:24:45 -07001090} // namespace ndn