blob: eba4ae41008fcbe6be75874e58ca80d5b685727e [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
Mickey Sweatte908a5c2016-04-08 14:10:45 -070053 TestTorrentManager(const ndn::Name& torrentFileName,
54 const std::string& filePath,
55 std::shared_ptr<DummyClientFace> face)
spirosmastorakisa46eee42016-04-05 14:24:45 -070056 : 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)
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700121 : face(new DummyClientFace(io, { true, enableRegistrationReply }))
spirosmastorakisa46eee42016-04-05 14:24:45 -0700122 {
123 }
124
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700125 ~FaceFixture()
126 {
127 fs::remove_all(".appdata");
128 }
129
spirosmastorakisa46eee42016-04-05 14:24:45 -0700130public:
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700131 std::shared_ptr<DummyClientFace> face;
spirosmastorakisa46eee42016-04-05 14:24:45 -0700132};
133
134class FacesNoRegistrationReplyFixture : public FaceFixture
135{
136public:
137 FacesNoRegistrationReplyFixture()
138 : FaceFixture(false)
139 {
140 }
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700141
spirosmastorakisa46eee42016-04-05 14:24:45 -0700142};
143
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700144BOOST_FIXTURE_TEST_SUITE(TestTorrentManagerInitialize, FaceFixture)
Mickey Sweatt527b0492016-03-02 11:07:48 -0800145
146BOOST_AUTO_TEST_CASE(CheckInitializeComplete)
147{
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700148 const struct {
149 const char *d_directoryPath;
150 const char *d_initialSegmentName;
151 size_t d_namesPerSegment;
152 size_t d_subManifestSize;
153 size_t d_dataPacketSize;
154 } DATA [] = {
155 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
156 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=b88c054e87bcbb744726f7eaf79f95459b4fddce2caeb952f263a5ccbbfc9a7c", 128, 128, 128},
157 // {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=76df604f23bdf257d16de588f2941df261951552a5f4435a315f59c3b018a851", 1, 1, 128},
158 };
159 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
160 for (int i = 0; i < NUM_DATA; ++i) {
161 auto directoryPath = DATA[i].d_directoryPath;
162 Name initialSegmentName = DATA[i].d_initialSegmentName;
163 auto namesPerSegment = DATA[i].d_namesPerSegment;
164 auto dataPacketSize = DATA[i].d_dataPacketSize;
165 auto subManifestSize = DATA[i].d_subManifestSize;
Mickey Sweatt527b0492016-03-02 11:07:48 -0800166
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700167 vector<FileManifest> manifests;
168 vector<TorrentFile> torrentSegments;
169 std::string filePath = "tests/testdata/";
170 // get torrent files and manifests
171 {
172 auto temp = TorrentFile::generate(directoryPath,
173 namesPerSegment,
174 subManifestSize,
175 dataPacketSize,
176 false);
177 torrentSegments = temp.first;
178 auto temp1 = temp.second;
179 for (const auto& ms : temp1) {
180 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
181 }
Mickey Sweatt527b0492016-03-02 11:07:48 -0800182 }
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700183 // write the torrent segments and manifests to disk
184 std::string dirPath = ".appdata/foo/";
185 boost::filesystem::create_directories(dirPath);
186 std::string torrentPath = dirPath + "torrent_files/";
187 boost::filesystem::create_directory(torrentPath);
188 auto fileNum = 0;
189 for (const auto& t : torrentSegments) {
190 fileNum++;
191 auto filename = torrentPath + to_string(fileNum);
192 io::save(t, filename);
193 }
194 auto manifestPath = dirPath + "manifests/";
195 boost::filesystem::create_directory(manifestPath);
196 for (const auto& m : manifests) {
197 fs::path filename = manifestPath + m.file_name() + "/" + to_string(m.submanifest_number());
198 boost::filesystem::create_directories(filename.parent_path());
199 io::save(m, filename.string());
200 }
201 // Initialize and verify
202 TestTorrentManager manager(initialSegmentName,
203 filePath,
204 face);
205 manager.Initialize();
206
207 // Check that the torrent segments and file manifests match (content and order)
208 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
209 BOOST_CHECK(manager.fileManifests() == manifests);
210 // next check the data packet state vectors
211 for (auto m : manager.fileManifests()) {
212 auto fileState = manager.fileState(m.getFullName());
213 BOOST_CHECK(fileState.size() == m.catalog().size());
214 for (auto s : fileState) {
215 BOOST_CHECK(s);
216 }
217 }
218 fs::remove_all(dirPath);
Mickey Sweatt527b0492016-03-02 11:07:48 -0800219 }
Mickey Sweatt527b0492016-03-02 11:07:48 -0800220}
221
222BOOST_AUTO_TEST_CASE(CheckInitializeEmpty)
223{
224 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253",
225 "tests/testdata/");
226 manager.Initialize();
227 BOOST_CHECK(manager.torrentSegments() == vector<TorrentFile>());
228 BOOST_CHECK(manager.fileManifests() == vector<FileManifest>());
229}
230
231BOOST_AUTO_TEST_CASE(CheckInitializeNoManifests)
232{
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700233 const struct {
234 const char *d_directoryPath;
235 const char *d_initialSegmentName;
236 size_t d_namesPerSegment;
237 size_t d_subManifestSize;
238 size_t d_dataPacketSize;
239 } DATA [] = {
240 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
241 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=b88c054e87bcbb744726f7eaf79f95459b4fddce2caeb952f263a5ccbbfc9a7c", 128, 128, 128},
242 // {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=76df604f23bdf257d16de588f2941df261951552a5f4435a315f59c3b018a851", 1, 1, 128},
243 };
244 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
245 for (int i = 0; i < NUM_DATA; ++i) {
246 auto directoryPath = DATA[i].d_directoryPath;
247 Name initialSegmentName = DATA[i].d_initialSegmentName;
248 auto namesPerSegment = DATA[i].d_namesPerSegment;
249 auto dataPacketSize = DATA[i].d_dataPacketSize;
250 auto subManifestSize = DATA[i].d_subManifestSize;
Mickey Sweatt527b0492016-03-02 11:07:48 -0800251
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700252 vector<FileManifest> manifests;
253 vector<TorrentFile> torrentSegments;
254 std::string filePath = "tests/testdata/";
255 // get torrent files and manifests
256 {
257 auto temp = TorrentFile::generate(directoryPath,
258 namesPerSegment,
259 subManifestSize,
260 dataPacketSize,
261 false);
262 torrentSegments = temp.first;
263 }
264 // write the torrent segments and manifests to disk
265 std::string dirPath = ".appdata/foo/";
266 boost::filesystem::create_directories(dirPath);
267 std::string torrentPath = dirPath + "torrent_files/";
268 boost::filesystem::create_directory(torrentPath);
269 auto fileNum = 0;
270 for (const auto& t : torrentSegments) {
271 fileNum++;
272 auto filename = torrentPath + to_string(fileNum);
273 io::save(t, filename);
274 }
275 // Initialize and verify
276 TestTorrentManager manager(initialSegmentName,
277 filePath,
278 face);
279 manager.Initialize();
Mickey Sweatt527b0492016-03-02 11:07:48 -0800280
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700281 // Check that the torrent segments and file manifests match (content and order)
282 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
283 BOOST_CHECK(manager.fileManifests() == vector<FileManifest>());
284
285 fs::remove_all(".appdata");
286 }
Mickey Sweatt527b0492016-03-02 11:07:48 -0800287}
288
289BOOST_AUTO_TEST_CASE(CheckInitializeMissingManifests)
290{
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700291 const struct {
292 const char *d_directoryPath;
293 const char *d_initialSegmentName;
294 size_t d_namesPerSegment;
295 size_t d_subManifestSize;
296 size_t d_dataPacketSize;
297 } DATA [] = {
298 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
299 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=b88c054e87bcbb744726f7eaf79f95459b4fddce2caeb952f263a5ccbbfc9a7c", 128, 128, 128},
300 // {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=76df604f23bdf257d16de588f2941df261951552a5f4435a315f59c3b018a851", 1, 1, 128},
301 };
302 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
303 for (int i = 0; i < NUM_DATA; ++i) {
304 auto directoryPath = DATA[i].d_directoryPath;
305 Name initialSegmentName = DATA[i].d_initialSegmentName;
306 auto namesPerSegment = DATA[i].d_namesPerSegment;
307 auto dataPacketSize = DATA[i].d_dataPacketSize;
308 auto subManifestSize = DATA[i].d_subManifestSize;
Mickey Sweatt527b0492016-03-02 11:07:48 -0800309
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700310 vector<FileManifest> manifests;
311 vector<TorrentFile> torrentSegments;
312 std::string filePath = "tests/testdata/";
313 // get torrent files and manifests
314 {
315 auto temp = TorrentFile::generate(directoryPath,
316 namesPerSegment,
317 subManifestSize,
318 dataPacketSize,
319 false);
320 torrentSegments = temp.first;
321 auto temp1 = temp.second;
322 temp1.pop_back(); // remove the manifests for the last file
323 for (const auto& ms : temp1) {
324 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
325 }
Mickey Sweatt527b0492016-03-02 11:07:48 -0800326 }
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700327 // write the torrent segments and manifests to disk
328 std::string dirPath = ".appdata/foo/";
329 boost::filesystem::create_directories(dirPath);
330 std::string torrentPath = dirPath + "torrent_files/";
331 boost::filesystem::create_directories(torrentPath);
332 auto fileNum = 0;
333 for (const auto& t : torrentSegments) {
334 fileNum++;
335 auto filename = torrentPath + to_string(fileNum);
336 io::save(t, filename);
337 }
338 auto manifestPath = dirPath + "manifests/";
339 boost::filesystem::create_directory(manifestPath);
340 for (const auto& m : manifests) {
341 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
342 boost::filesystem::create_directory(filename.parent_path());
343 io::save(m, filename.string());
344 }
345 // Initialize and verify
346 TestTorrentManager manager(initialSegmentName,
347 filePath,
348 face);
349 manager.Initialize();
350
351 // Check that the torrent segments and file manifests match (content and order)
352 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
353 BOOST_CHECK(manager.fileManifests() == manifests);
354 // next check the data packet state vectors
355 for (auto m : manager.fileManifests()) {
356 auto fileState = manager.fileState(m.getFullName());
357 BOOST_CHECK(fileState.size() == m.catalog().size());
358 for (auto s : fileState) {
359 BOOST_CHECK(s);
360 }
361 }
362 fs::remove_all(".appdata");
Mickey Sweatt527b0492016-03-02 11:07:48 -0800363 }
Mickey Sweatt527b0492016-03-02 11:07:48 -0800364}
365
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700366BOOST_AUTO_TEST_SUITE_END()
367
spirosmastorakisa46eee42016-04-05 14:24:45 -0700368BOOST_FIXTURE_TEST_SUITE(TestTorrentManagerNetworkingStuff, FaceFixture)
369
370BOOST_AUTO_TEST_CASE(TestDownloadingTorrentFile)
371{
372 vector<FileManifest> manifests;
373 vector<TorrentFile> torrentSegments;
374 std::string filePath = ".appdata/foo/";
375 // get torrent files and manifests
376 {
377 auto temp = TorrentFile::generate("tests/testdata/foo", 1, 10, 10, false);
378
379 torrentSegments = temp.first;
380 auto temp1 = temp.second;
381 temp1.pop_back(); // remove the manifests for the last file
382 for (const auto& ms : temp1) {
383 for (const auto& m : ms.first) {
384 manifests.push_back(m);
385 }
386 }
387 }
388
389 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=946b92641d2b87bf4f5913930be20e3789ff5fb5d72739614f93f677d90fbd9d",
390 filePath, face);
391 manager.Initialize();
392
393 // Test download torrent file segments
394 uint32_t counter = 0;
spirosmastorakis50642f82016-04-08 12:11:18 -0700395 manager.downloadTorrentFile(filePath + "torrent_files", [&counter, &torrentSegments]
396 (const std::vector<ndn::Name>& vec) {
397 uint32_t manifestNum = 0;
398 for (auto i = vec.begin(); i != vec.end(); i++) {
399 Name n = torrentSegments[counter].getCatalog()[manifestNum];
400 BOOST_CHECK_EQUAL(n, *i);
401 manifestNum++;
402 }
403 counter++;
404 },
405 bind([] {
406 BOOST_FAIL("Unexpected failure");
407 }));
spirosmastorakisa46eee42016-04-05 14:24:45 -0700408
409 for (auto i = torrentSegments.begin(); i != torrentSegments.end(); i++) {
410 advanceClocks(time::milliseconds(1), 40);
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700411 face->receive(dynamic_cast<Data&>(*i));
spirosmastorakisa46eee42016-04-05 14:24:45 -0700412 }
413
414 fs::remove_all(filePath);
spirosmastorakis50642f82016-04-08 12:11:18 -0700415 fs::remove_all(".appdata");
spirosmastorakisa46eee42016-04-05 14:24:45 -0700416}
417
418BOOST_AUTO_TEST_CASE(TestDownloadingFileManifests)
419{
420 vector<FileManifest> manifests;
421 vector<TorrentFile> torrentSegments;
422 std::string filePath = ".appdata/foo/";
423 // get torrent files and manifests
424 {
425 auto temp = TorrentFile::generate("tests/testdata/foo", 1, 10, 10, false);
426
427 torrentSegments = temp.first;
428 auto temp1 = temp.second;
429 temp1.pop_back(); // remove the manifests for the last file
430 for (const auto& ms : temp1) {
431 for (const auto& m : ms.first) {
432 manifests.push_back(m);
433 }
434 }
435 }
436
437 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=946b92641d2b87bf4f5913930be20e3789ff5fb5d72739614f93f677d90fbd9d",
438 filePath, face);
439 manager.Initialize();
440
441 // Test download manifest segments -- 2 files (the first one segment, the second multiple)
442 int counter = 0;
443 manager.download_file_manifest(manifests[0].getFullName(), filePath + "manifests",
444 [&counter, &manifests]
445 (const std::vector<ndn::Name>& vec) {
446 uint32_t packetIndex = 0;
447 for (auto j = vec.begin(); j != vec.end(); j++) {
448 BOOST_CHECK_EQUAL(manifests[counter].catalog()[packetIndex],
449 *j);
450 packetIndex++;
451 }
452 counter++;
453 },
454 [](const ndn::Name& name, const std::string& reason) {
455 BOOST_FAIL("Unexpected failure");
456 });
457
458 advanceClocks(time::milliseconds(1), 40);
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700459 face->receive(dynamic_cast<Data&>(manifests[0]));
spirosmastorakisa46eee42016-04-05 14:24:45 -0700460
461 manager.download_file_manifest(manifests[1].getFullName(), filePath + "manifests",
462 [&counter, &manifests]
463 (const std::vector<ndn::Name>& vec) {
464 uint32_t packetIndex = 0;
465 for (auto j = vec.begin(); j != vec.end(); j++) {
466 BOOST_CHECK_EQUAL(manifests[counter].catalog()[packetIndex],
467 *j);
468 // if we have read all the packet names from a
469 // segment, move to the next one
470 if (packetIndex == manifests[counter].catalog().size() - 1) {
471 packetIndex = 0;
472 counter++;
473 }
474 else {
475 packetIndex++;
476 }
477 }
478 },
479 [](const ndn::Name& name, const std::string& reason) {
480 BOOST_FAIL("Unexpected failure");
481 });
482
483 for (auto i = manifests.begin() + 1; i != manifests.end(); i++) {
484 advanceClocks(time::milliseconds(1), 40);
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700485 face->receive(dynamic_cast<Data&>(*i));
spirosmastorakisa46eee42016-04-05 14:24:45 -0700486 }
487
488 fs::remove_all(filePath);
spirosmastorakis50642f82016-04-08 12:11:18 -0700489 fs::remove_all(".appdata");
spirosmastorakisa46eee42016-04-05 14:24:45 -0700490}
491
492BOOST_AUTO_TEST_CASE(TestDownloadingDataPackets)
493{
494 std::string filePath = ".appdata/foo/";
495 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=946b92641d2b87bf4f5913930be20e3789ff5fb5d72739614f93f677d90fbd9d",
496 filePath, face);
497 manager.Initialize();
498
499 Name dataName("/test/ucla");
500
501 // Download data successfully
502 manager.download_data_packet(dataName,
503 [&dataName] (const ndn::Name& name) {
504 BOOST_CHECK_EQUAL(name, dataName);
505 },
506 [](const ndn::Name& name, const std::string& reason) {
507 BOOST_FAIL("Unexpected failure");
508 });
509
510 auto data = make_shared<Data>(dataName);
511 SignatureSha256WithRsa fakeSignature;
512 fakeSignature.setValue(encoding::makeEmptyBlock(tlv::SignatureValue));
513 data->setSignature(fakeSignature);
514 data->wireEncode();
515
516 advanceClocks(time::milliseconds(1), 40);
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700517 face->receive(*data);
spirosmastorakisa46eee42016-04-05 14:24:45 -0700518
519 // Fail to download data
520 manager.download_data_packet(dataName,
spirosmastorakis50642f82016-04-08 12:11:18 -0700521 [](const ndn::Name& name) {
spirosmastorakisa46eee42016-04-05 14:24:45 -0700522 BOOST_FAIL("Unexpected failure");
523 },
524 [&dataName](const ndn::Name& name, const std::string& reason) {
525 BOOST_CHECK_EQUAL(name, dataName);
526 });
527
528 advanceClocks(time::milliseconds(1), 2100);
529
530 fs::remove_all(filePath);
spirosmastorakis50642f82016-04-08 12:11:18 -0700531 fs::remove_all(".appdata");
532}
533
534// we already have downloaded the torrent file
535BOOST_AUTO_TEST_CASE(TestFindTorrentFileSegmentToDownload1)
536{
537 std::string filePath = ".appdata/foo/";
538 TestTorrentManager manager("NTORRENT/test/torrent-file/sha256digest",
539 filePath, face);
540 manager.Initialize();
541
542 TorrentFile t1(Name("NTORRENT/test/torrent-file/sha256digest"),
543 Name("NTORRENT/test/torrent-file/1/sha256digest"), Name("/test"),
544 { Name("/manifest1") });
545 manager.pushTorrentSegment(t1);
546
547 TorrentFile t2(Name("NTORRENT/test/torrent-file/1/sha256digest"),
548 Name("NTORRENT/test/torrent-file/2/sha256digest"), Name("/test"),
549 { Name("/manifest2"), Name("/manifest3") });
550 manager.pushTorrentSegment(t2);
551
552 TorrentFile t3(Name("NTORRENT/test/torrent-file/3/sha256digest"),
553 Name("NTORRENT/test/torrent-file/4/sha256digest"), Name("/test"),
554 { Name("/manifest4"), Name("/manifest5") });
555 manager.pushTorrentSegment(t3);
556
557 TorrentFile t4(Name("NTORRENT/test/torrent-file/4/sha256digest"), Name("/test"), {});
558 manager.pushTorrentSegment(t4);
559
560 BOOST_CHECK(!(manager.findTorrentFileSegmentToDownload()));
561
562 std::vector<Name> manifests;
563 manifests = manager.downloadTorrentFile("/test");
564
565 BOOST_CHECK_EQUAL(manifests[0].toUri(), "/manifest1");
566 BOOST_CHECK_EQUAL(manifests[1].toUri(), "/manifest2");
567 BOOST_CHECK_EQUAL(manifests[2].toUri(), "/manifest3");
568 BOOST_CHECK_EQUAL(manifests[3].toUri(), "/manifest4");
569 BOOST_CHECK_EQUAL(manifests[4].toUri(), "/manifest5");
570
571 fs::remove_all(filePath);
572 fs::remove_all(".appdata");
573}
574
575// we do not have the torrent file
576BOOST_AUTO_TEST_CASE(TestFindTorrentFileSegmentToDownload2)
577{
578 std::string filePath = ".appdata/foo/";
579 TestTorrentManager manager("/test/0/sha256digest",
580 filePath, face);
581 manager.Initialize();
582
583 BOOST_CHECK_EQUAL(manager.findTorrentFileSegmentToDownload()->toUri(), "/test/0/sha256digest");
584
585 fs::remove_all(filePath);
586 fs::remove_all(".appdata");
587}
588
589// we have the torrent file and the manifests
590BOOST_AUTO_TEST_CASE(TestFindTorrentFileSegmentToDownload3)
591{
592 vector<FileManifest> manifests;
593 vector<TorrentFile> torrentSegments;
594 // for each file, the data packets
595 std::vector<vector<Data>> fileData;
596 std::string filePath = "tests/testdata/temp";
597 // get torrent files and manifests
598 {
599 auto temp = TorrentFile::generate("tests/testdata/foo",
600 1024,
601 2048,
602 8192,
603 true);
604 torrentSegments = temp.first;
605 auto temp1 = temp.second;
606 for (const auto& ms : temp1) {
607 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
608 fileData.push_back(ms.second);
609 }
610 }
611 // write the torrent segments and manifests to disk
612 std::string dirPath = ".appdata/foo/";
613 boost::filesystem::create_directories(dirPath);
614 std::string torrentPath = dirPath + "torrent_files/";
615 boost::filesystem::create_directories(torrentPath);
616 auto fileNum = 0;
617 for (const auto& t : torrentSegments) {
618 fileNum++;
619 auto filename = torrentPath + to_string(fileNum);
620 io::save(t, filename);
621 }
622
623 auto manifestPath = dirPath + "manifests/";
624 boost::filesystem::create_directory(manifestPath);
625 for (const auto& m : manifests) {
626 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
627 boost::filesystem::create_directory(filename.parent_path());
628 io::save(m, filename.string());
629 }
630 // Initialize manager
631 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=a8a2e98cd943d895b8c4b12a208343bcf9344ce85a6376dc6f5754fe8f4a573e",
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700632 filePath,
633 face);
spirosmastorakis50642f82016-04-08 12:11:18 -0700634 manager.Initialize();
635
636 // Set the file state
637 std::vector<bool> v1 = {true};
638 manager.setFileState(manifests[0].getFullName(), make_shared<fs::fstream>(), v1);
639
640 std::vector<bool> v2 = {false, true, true, false, false, false};
641 manager.setFileState(manifests[1].getFullName(), make_shared<fs::fstream>(), v2);
642
643 std::vector<bool> v3 = {true, false, false, false, false, false};
644 manager.setFileState(manifests[2].getFullName(), make_shared<fs::fstream>(), v3);
645
646 manager.downloadTorrentFile(filePath + "torrent_files/",
647 [&manifests](const std::vector<ndn::Name>& vec) {
648 BOOST_CHECK_EQUAL(vec[0].toUri(),
649 manifests[1].catalog()[0].toUri());
650 BOOST_CHECK_EQUAL(vec[1].toUri(),
651 manifests[1].catalog()[3].toUri());
652 BOOST_CHECK_EQUAL(vec[2].toUri(),
653 manifests[1].catalog()[4].toUri());
654 BOOST_CHECK_EQUAL(vec[3].toUri(),
655 manifests[1].catalog()[5].toUri());
656 BOOST_CHECK_EQUAL(vec[4].toUri(),
657 manifests[2].catalog()[1].toUri());
658 BOOST_CHECK_EQUAL(vec[5].toUri(),
659 manifests[2].catalog()[2].toUri());
660 BOOST_CHECK_EQUAL(vec[6].toUri(),
661 manifests[2].catalog()[3].toUri());
662 BOOST_CHECK_EQUAL(vec[7].toUri(),
663 manifests[2].catalog()[4].toUri());
664 BOOST_CHECK_EQUAL(vec[8].toUri(),
665 manifests[2].catalog()[5].toUri());
666 },
667 [](const ndn::Name& name, const std::string& reason) {
668 BOOST_FAIL("Unexpected failure");
669 });
670
671 fs::remove_all(filePath);
672 fs::remove_all(".appdata");
673}
674
spirosmastorakis50642f82016-04-08 12:11:18 -0700675BOOST_AUTO_TEST_CASE(TestFindManifestSegmentToDownload1)
676{
677 std::string filePath = ".appdata/foo/";
678 TestTorrentManager manager("NTORRENT/test/sha256digest",
679 filePath, face);
680 manager.Initialize();
681
682 Name n1(Name("NTORRENT/test/file0"));
683 n1.appendSequenceNumber(0);
684
685 Name n2(Name("NTORRENT/test/file0"));
686 n2.appendSequenceNumber(1);
687
688 Name n3(Name("NTORRENT/test/file0"));
689 n3.appendSequenceNumber(2);
690
691 Name n4(Name("NTORRENT/test/file0"));
692 n4.appendSequenceNumber(3);
693
694 Name n5(Name("NTORRENT/test/file0"));
695 n5.appendSequenceNumber(4);
696
697 Name n6(Name("NTORRENT/test1/file0"));
698 n6.appendSequenceNumber(0);
699
700 Name n7(Name("NTORRENT/test1/file0"));
701 n7.appendSequenceNumber(1);
702
703 // In theory, this may not be correct, but here let's suck it up for the sake
704 // of testing the function correctness
705 Name n8(Name("NTORRENT/test1/file2"));
706 n8.appendSequenceNumber(0);
707
708 Name n9(Name("NTORRENT/test1/file2"));
709 n9.appendSequenceNumber(1);
710
711 FileManifest f1(n1, 50, Name("NTORRENT/test"), {}, make_shared<Name>(n2));
712 manager.pushFileManifestSegment(f1);
713
714 FileManifest f2(n2, 50, Name("NTORRENT/test"), {}, make_shared<Name>(n3));
715 manager.pushFileManifestSegment(f2);
716
717 FileManifest f3(n3, 50, Name("NTORRENT/test"), {}, make_shared<Name>(n4));
718 manager.pushFileManifestSegment(f3);
719
720 FileManifest f4(n4, 50, Name("NTORRENT/test"), {}, make_shared<Name>(n5));
721 manager.pushFileManifestSegment(f4);
722
723 FileManifest f5(n6, 50, Name("NTORRENT/test2"), {}, make_shared<Name>(n7));
724 manager.pushFileManifestSegment(f5);
725
726 FileManifest f6(n7, 50, Name("NTORRENT/test2"), {}, {});
727 manager.pushFileManifestSegment(f6);
728
729 FileManifest f7(n8, 50, Name("NTORRENT/test3"), {}, make_shared<Name>(n9));
730 manager.pushFileManifestSegment(f7);
731
732 BOOST_CHECK_EQUAL(manager.findManifestSegmentToDownload(Name(n2.toUri() + "/sha256digest"))->toUri(), n5.toUri());
733 BOOST_CHECK_EQUAL(manager.findManifestSegmentToDownload(Name(n8.toUri() + "/sha256digest"))->toUri(), n9.toUri());
734 BOOST_CHECK_EQUAL(manager.findManifestSegmentToDownload(Name(n5.toUri() + "/sha256digest"))->toUri(),
735 Name(n5.toUri() + "/sha256digest").toUri());
736 BOOST_CHECK(!(manager.findManifestSegmentToDownload(Name(n7.toUri() + "/sha256digest"))));
737
738 Name n10(Name("NTORRENT/test1/file1"));
739 n10.appendSequenceNumber(1);
740 n10 = Name(n10.toUri() + "/sha256digest");
741
742 BOOST_CHECK_EQUAL(manager.findManifestSegmentToDownload(n10)->toUri(), n10.toUri());
spirosmastorakis50642f82016-04-08 12:11:18 -0700743}
744
745BOOST_AUTO_TEST_CASE(TestFindManifestSegmentToDownload2)
746{
747 vector<FileManifest> manifests;
748 vector<TorrentFile> torrentSegments;
749 // for each file, the data packets
750 std::vector<vector<Data>> fileData;
751 std::string filePath = "tests/testdata/temp";
752 // get torrent files and manifests
753 {
754 auto temp = TorrentFile::generate("tests/testdata/foo",
755 1024,
756 2048,
757 8192,
758 true);
759 torrentSegments = temp.first;
760 auto temp1 = temp.second;
761 for (const auto& ms : temp1) {
762 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
763 fileData.push_back(ms.second);
764 }
765 }
766 // write the torrent segments and manifests to disk
767 std::string dirPath = ".appdata/foo/";
768 boost::filesystem::create_directories(dirPath);
769 std::string torrentPath = dirPath + "torrent_files/";
770 boost::filesystem::create_directories(torrentPath);
771 auto fileNum = 0;
772 for (const auto& t : torrentSegments) {
773 fileNum++;
774 auto filename = torrentPath + to_string(fileNum);
775 io::save(t, filename);
776 }
777
778 auto manifestPath = dirPath + "manifests/";
779 boost::filesystem::create_directory(manifestPath);
780 for (const auto& m : manifests) {
781 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
782 boost::filesystem::create_directory(filename.parent_path());
783 io::save(m, filename.string());
784 }
785 // Initialize manager
786 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=a8a2e98cd943d895b8c4b12a208343bcf9344ce85a6376dc6f5754fe8f4a573e",
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700787 filePath,
788 face);
spirosmastorakis50642f82016-04-08 12:11:18 -0700789 manager.Initialize();
790
791 // Set the file state
792 std::vector<bool> v1 = {true};
793 manager.setFileState(manifests[0].getFullName(), make_shared<fs::fstream>(), v1);
794
795 std::vector<bool> v2 = {false, true, true, false, false, false};
796 manager.setFileState(manifests[1].getFullName(), make_shared<fs::fstream>(), v2);
797
798 std::vector<bool> v3 = {true, false, false, false, false, false};
799 manager.setFileState(manifests[2].getFullName(), make_shared<fs::fstream>(), v3);
800
801 manager.download_file_manifest(manifests[0].getFullName(), filePath + "manifests",
802 [&manifests](const std::vector<ndn::Name>& vec) {
803 BOOST_CHECK_EQUAL(vec.size(), 0);
804 },
805 [](const ndn::Name& name, const std::string& reason) {
806 BOOST_FAIL("Unexpected failure");
807 });
808
809 manager.download_file_manifest(manifests[1].getFullName(), filePath + "manifests",
810 [&manifests](const std::vector<ndn::Name>& vec) {
811 BOOST_CHECK_EQUAL(vec[0].toUri(),
812 manifests[1].catalog()[0].toUri());
813 BOOST_CHECK_EQUAL(vec[1].toUri(),
814 manifests[1].catalog()[3].toUri());
815 BOOST_CHECK_EQUAL(vec[2].toUri(),
816 manifests[1].catalog()[4].toUri());
817 BOOST_CHECK_EQUAL(vec[3].toUri(),
818 manifests[1].catalog()[5].toUri());
819 },
820 [](const ndn::Name& name, const std::string& reason) {
821 BOOST_FAIL("Unexpected failure");
822 });
823
824 manager.download_file_manifest(manifests[2].getFullName(), filePath + "manifests",
825 [&manifests](const std::vector<ndn::Name>& vec) {
826 BOOST_CHECK_EQUAL(vec[0].toUri(),
827 manifests[2].catalog()[1].toUri());
828 BOOST_CHECK_EQUAL(vec[1].toUri(),
829 manifests[2].catalog()[2].toUri());
830 BOOST_CHECK_EQUAL(vec[2].toUri(),
831 manifests[2].catalog()[3].toUri());
832 BOOST_CHECK_EQUAL(vec[3].toUri(),
833 manifests[2].catalog()[4].toUri());
834 BOOST_CHECK_EQUAL(vec[4].toUri(),
835 manifests[2].catalog()[5].toUri());
836 },
837 [](const ndn::Name& name, const std::string& reason) {
838 BOOST_FAIL("Unexpected failure");
839 });
840 fs::remove_all(filePath);
841 fs::remove_all(".appdata");
842}
843
844BOOST_AUTO_TEST_CASE(TestDataAlreadyDownloaded)
845{
846 vector<FileManifest> manifests;
847 vector<TorrentFile> torrentSegments;
848 // for each file, the data packets
849 std::vector<vector<Data>> fileData;
850 std::string filePath = "tests/testdata/temp";
851 // get torrent files and manifests
852 {
853 auto temp = TorrentFile::generate("tests/testdata/foo",
854 1024,
855 2048,
856 8192,
857 true);
858 torrentSegments = temp.first;
859 auto temp1 = temp.second;
860 for (const auto& ms : temp1) {
861 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
862 fileData.push_back(ms.second);
863 }
864 }
865 // write the torrent segments and manifests to disk
866 std::string dirPath = ".appdata/foo/";
867 boost::filesystem::create_directories(dirPath);
868 std::string torrentPath = dirPath + "torrent_files/";
869 boost::filesystem::create_directories(torrentPath);
870 auto fileNum = 0;
871 for (const auto& t : torrentSegments) {
872 fileNum++;
873 auto filename = torrentPath + to_string(fileNum);
874 io::save(t, filename);
875 }
876
877 auto manifestPath = dirPath + "manifests/";
878 boost::filesystem::create_directory(manifestPath);
879 for (const auto& m : manifests) {
880 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
881 boost::filesystem::create_directory(filename.parent_path());
882 io::save(m, filename.string());
883 }
884 // Initialize manager
885 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=a8a2e98cd943d895b8c4b12a208343bcf9344ce85a6376dc6f5754fe8f4a573e",
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700886 filePath,
887 face);
spirosmastorakis50642f82016-04-08 12:11:18 -0700888 manager.Initialize();
889
890 // Set the file state
891 std::vector<bool> v1 = {true};
892 manager.setFileState(manifests[0].getFullName(), make_shared<fs::fstream>(), v1);
893
894 std::vector<bool> v2 = {false, true, true, false, false, false};
895 manager.setFileState(manifests[1].getFullName(), make_shared<fs::fstream>(), v2);
896
897 std::vector<bool> v3 = {true, false, false, false, false, false};
898 manager.setFileState(manifests[2].getFullName(), make_shared<fs::fstream>(), v3);
899
900 Name p1("NTORRENT/foo/bar1.txt");
901 p1.appendSequenceNumber(0);
902 p1.appendSequenceNumber(0);
903 p1 = Name(p1.toUri() + "/sha256digest");
904
905 BOOST_CHECK(!(manager.dataAlreadyDownloaded(p1)));
906
907 Name p2("NTORRENT/foo/bar.txt");
908 p2.appendSequenceNumber(0);
909 p2.appendSequenceNumber(0);
910 p2 = Name(p2.toUri() + "/sha256digest");
911
912 BOOST_CHECK(manager.dataAlreadyDownloaded(p2));
spirosmastorakisa46eee42016-04-05 14:24:45 -0700913}
914
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700915BOOST_AUTO_TEST_CASE(CheckSeedComplete)
916{
917 const struct {
918 const char *d_directoryPath;
919 const char *d_initialSegmentName;
920 size_t d_namesPerSegment;
921 size_t d_subManifestSize;
922 size_t d_dataPacketSize;
923 } DATA [] = {
924 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
925 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=b88c054e87bcbb744726f7eaf79f95459b4fddce2caeb952f263a5ccbbfc9a7c", 128, 128, 128},
926 // {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=76df604f23bdf257d16de588f2941df261951552a5f4435a315f59c3b018a851", 1, 1, 128},
927 };
928 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
929 for (int i = 0; i < NUM_DATA; ++i) {
930 auto directoryPath = DATA[i].d_directoryPath;
931 Name initialSegmentName = DATA[i].d_initialSegmentName;
932 auto namesPerSegment = DATA[i].d_namesPerSegment;
933 auto dataPacketSize = DATA[i].d_dataPacketSize;
934 auto subManifestSize = DATA[i].d_subManifestSize;
Mickey Sweatt527b0492016-03-02 11:07:48 -0800935
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700936 vector<FileManifest> manifests;
937 vector<TorrentFile> torrentSegments;
938 std::string filePath = "tests/testdata/";
939 std::vector<vector<Data>> fileData;
940 // get torrent files and manifests
941 {
942 auto temp = TorrentFile::generate(directoryPath,
943 namesPerSegment,
944 subManifestSize,
945 dataPacketSize,
946 false);
947 torrentSegments = temp.first;
948 auto temp1 = temp.second;
949 for (const auto& ms : temp1) {
950 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
951 fileData.push_back(ms.second);
952 }
953 }
954 // write the torrent segments and manifests to disk
955 std::string dirPath = ".appdata/foo/";
956 boost::filesystem::create_directories(dirPath);
957 std::string torrentPath = dirPath + "torrent_files/";
958 boost::filesystem::create_directory(torrentPath);
959 auto fileNum = 0;
960 for (const auto& t : torrentSegments) {
961 fileNum++;
962 auto filename = torrentPath + to_string(fileNum);
963 io::save(t, filename);
964 }
965 auto manifestPath = dirPath + "manifests/";
966 boost::filesystem::create_directory(manifestPath);
967 for (const auto& m : manifests) {
968 fs::path filename = manifestPath + m.file_name() + "/" + to_string(m.submanifest_number());
969 boost::filesystem::create_directories(filename.parent_path());
970 io::save(m, filename.string());
971 }
972 // Initialize and verify
973 TestTorrentManager manager(initialSegmentName,
974 filePath,
975 face);
976 manager.Initialize();
977 size_t nData = 0;
978 BOOST_CHECK_EQUAL(0, face->sentData.size());
979 // request all the torrent segments
980 for (const auto& t : torrentSegments) {
981 Interest interest(t.getFullName(), time::milliseconds(50));
982 face->expressInterest(interest,
983 [&t](const Interest& i, const Data& d) {
984 TorrentFile t1(d.wireEncode());
985 BOOST_CHECK(t == d);
986 BOOST_CHECK(t1 == t);
987 },
988 bind([] {
989 BOOST_FAIL("Unexpected Nack");
990 }),
991 bind([] {
992 BOOST_FAIL("Unexpected timeout");
993 }));
994 advanceClocks(time::milliseconds(1), 40);
995 face->receive(interest);
996 face->processEvents(time::milliseconds(-1));
997 // check that one piece of data is sent, and it is what was expected
998 BOOST_CHECK_EQUAL(++nData, face->sentData.size());
999 face->receive(face->sentData[nData - 1]);
1000 }
1001 // request all the file manifests
1002 for (const auto& m : manifests) {
1003 Interest interest(m.getFullName(), time::milliseconds(50));
1004 face->expressInterest(interest,
1005 [&m](const Interest& i, const Data& d) {
1006 FileManifest m1(d.wireEncode());
1007 BOOST_CHECK(m == d);
1008 BOOST_CHECK(m1 == m);
1009 },
1010 bind([] {
1011 BOOST_FAIL("Unexpected Nack");
1012 }),
1013 bind([] {
1014 BOOST_FAIL("Unexpected timeout");
1015 }));
1016 advanceClocks(time::milliseconds(1), 40);
1017 face->receive(interest);
1018 face->processEvents(time::milliseconds(-1));
1019 // check that one piece of data is sent, and it is what was expected
1020 BOOST_CHECK_EQUAL(++nData, face->sentData.size());
1021 face->receive(face->sentData[nData - 1]);
1022 }
1023 // request all the data packets
1024 for (const auto& file : fileData) {
1025 for (const auto& data : file) {
1026 Interest interest(data. getFullName(), time::milliseconds(50));
1027 face->expressInterest(interest,
1028 [&data](const Interest& i, const Data& d) {
1029 BOOST_CHECK(data == d);
1030 },
1031 bind([] {
1032 BOOST_FAIL("Unexpected Nack");
1033 }),
1034 bind([] {
1035 BOOST_FAIL("Unexpected timeout");
1036 }));
1037 advanceClocks(time::milliseconds(1), 40);
1038 face->receive(interest);
1039 face->processEvents(time::milliseconds(-1));
1040 // check that one piece of data is sent, and it is what was expected
1041 BOOST_CHECK_EQUAL(++nData, face->sentData.size());
1042 face->receive(face->sentData[nData - 1]);
1043 }
1044 }
1045 // clean up tests
1046 face->sentData.clear();
1047 fs::remove_all(".appdata/");
1048 }
1049}
Mickey Sweattafda1f12016-04-04 17:15:11 -07001050
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001051BOOST_AUTO_TEST_CASE(CheckSeedRandom)
Mickey Sweattafda1f12016-04-04 17:15:11 -07001052{
1053 vector<FileManifest> manifests;
1054 vector<TorrentFile> torrentSegments;
1055 // for each file, the data packets
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001056 std::vector<Data> data;
1057 std::string filePath = "tests/testdata/";
1058 std::string dirPath = ".appdata/foo/";
1059 Name initialSegmentName = "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253";
Mickey Sweattafda1f12016-04-04 17:15:11 -07001060 // get torrent files and manifests
1061 {
1062 auto temp = TorrentFile::generate("tests/testdata/foo",
1063 1024,
1064 1024,
1065 1024,
1066 true);
1067 torrentSegments = temp.first;
1068 auto temp1 = temp.second;
1069 for (const auto& ms : temp1) {
1070 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001071 data.insert(data.end(), ms.second.begin(), ms.second.end());
Mickey Sweattafda1f12016-04-04 17:15:11 -07001072 }
1073 }
1074 // write the torrent segments and manifests to disk
Mickey Sweattafda1f12016-04-04 17:15:11 -07001075 boost::filesystem::create_directories(dirPath);
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001076 auto torrentPath = dirPath + "torrent_files/";
Mickey Sweattafda1f12016-04-04 17:15:11 -07001077 boost::filesystem::create_directories(torrentPath);
1078 auto fileNum = 0;
1079 for (const auto& t : torrentSegments) {
1080 fileNum++;
1081 auto filename = torrentPath + to_string(fileNum);
1082 io::save(t, filename);
1083 }
Mickey Sweattafda1f12016-04-04 17:15:11 -07001084 auto manifestPath = dirPath + "manifests/";
1085 boost::filesystem::create_directory(manifestPath);
1086 for (const auto& m : manifests) {
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001087 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
1088 boost::filesystem::create_directory(filename.parent_path());
1089 io::save(m, filename.string());
Mickey Sweattafda1f12016-04-04 17:15:11 -07001090 }
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001091
Mickey Sweattafda1f12016-04-04 17:15:11 -07001092 // Initialize manager
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001093 TestTorrentManager manager(initialSegmentName,
1094 filePath,
1095 face);
Mickey Sweattafda1f12016-04-04 17:15:11 -07001096 manager.Initialize();
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001097
1098 // insert the other entities
1099 data.insert(data.end(), torrentSegments.begin(), torrentSegments.end());
1100 data.insert(data.end(), manifests.begin(), manifests.end());
1101
1102 std::random_shuffle(data.begin(), data.end());
1103 // request all the data packets
1104 auto nData = 0;
1105 for(const auto& d : data) {
1106 Interest interest(d.getFullName(), time::milliseconds(50));
1107 face->expressInterest(interest,
1108 [&d](const Interest& i, const Data& data) {
1109 BOOST_CHECK(data == d);
1110 },
1111 bind([] {
1112 BOOST_FAIL("Unexpected Nack");
1113 }),
1114 bind([] {
1115 BOOST_FAIL("Unexpected timeout");
1116 }));
1117 advanceClocks(time::milliseconds(1), 40);
1118 face->receive(interest);
1119 face->processEvents(time::milliseconds(-1));
1120 // check that one piece of data is sent, and it is what was expected
1121 BOOST_CHECK_EQUAL(++nData, face->sentData.size());
1122 face->receive(face->sentData[nData - 1]);
Mickey Sweattafda1f12016-04-04 17:15:11 -07001123 }
Mickey Sweattafda1f12016-04-04 17:15:11 -07001124 fs::remove_all(".appdata");
1125}
1126
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001127BOOST_AUTO_TEST_SUITE_END()
1128
1129BOOST_FIXTURE_TEST_SUITE(CheckTorrentManagerUtilities, FaceFixture)
1130
1131BOOST_AUTO_TEST_CASE(CheckWriteDataComplete)
1132{
1133 const struct {
1134 const char *d_directoryPath;
1135 const char *d_initialSegmentName;
1136 size_t d_namesPerSegment;
1137 size_t d_subManifestSize;
1138 size_t d_dataPacketSize;
1139 } DATA [] = {
1140 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
1141 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=b88c054e87bcbb744726f7eaf79f95459b4fddce2caeb952f263a5ccbbfc9a7c", 128, 128, 128},
1142 };
1143 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
1144 for (int i = 0; i < NUM_DATA; ++i) {
1145 auto directoryPath = DATA[i].d_directoryPath;
1146 Name initialSegmentName = DATA[i].d_initialSegmentName;
1147 auto namesPerSegment = DATA[i].d_namesPerSegment;
1148 auto dataPacketSize = DATA[i].d_dataPacketSize;
1149 auto subManifestSize = DATA[i].d_subManifestSize;
1150
1151 vector<TorrentFile> torrentSegments;
1152 vector<FileManifest> manifests;
1153 // for each file, the data packets
1154 std::vector<vector<Data>> fileData;
1155 std::string filePath = "tests/testdata/temp";
1156 // get torrent files and manifests
1157 {
1158 auto temp = TorrentFile::generate(directoryPath,
1159 namesPerSegment,
1160 subManifestSize,
1161 dataPacketSize,
1162 false);
1163 torrentSegments = temp.first;
1164 auto temp1 = temp.second;
1165 for (const auto& ms : temp1) {
1166 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
1167 fileData.push_back(ms.second);
1168 }
1169 }
1170 // write the torrent segments and manifests to disk
1171 std::string dirPath = ".appdata/foo/";
1172 boost::filesystem::create_directories(dirPath);
1173 std::string torrentPath = dirPath + "torrent_files/";
1174 boost::filesystem::create_directories(torrentPath);
1175 auto fileNum = 0;
1176 for (const auto& t : torrentSegments) {
1177 fileNum++;
1178 auto filename = torrentPath + to_string(fileNum);
1179 io::save(t, filename);
1180 }
1181 auto manifestPath = dirPath + "manifests/";
1182 boost::filesystem::create_directory(manifestPath);
1183 for (const auto& m : manifests) {
1184 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
1185 boost::filesystem::create_directory(filename.parent_path());
1186 io::save(m, filename.string());
1187 }
1188 // Initialize manager
1189 TestTorrentManager manager(initialSegmentName,
1190 filePath,
1191 face);
1192 manager.Initialize();
1193 // check that initially there is no data on disk
1194 for (auto m : manager.fileManifests()) {
1195 auto fileState = manager.fileState(m.getFullName());
1196 BOOST_CHECK(fileState.empty());
1197 }
1198 // write all data to disk (for each file manifest)
1199 auto manifest_it = manifests.begin();
1200 for (auto& data : fileData) {
1201 for (auto& d : data) {
1202 BOOST_CHECK(manager.writeData(d));
1203 }
1204 // check that the state is updated appropriately
1205 auto fileState = manager.fileState(manifest_it->getFullName());
1206 for (auto s : fileState) {
1207 BOOST_CHECK(s);
1208 }
1209 ++manifest_it;
1210 }
1211 // get the file names (ascending)
1212 std::set<std::string> fileNames;
1213 for (auto i = fs::recursive_directory_iterator(filePath + "/foo");
1214 i != fs::recursive_directory_iterator();
1215 ++i) {
1216 fileNames.insert(i->path().string());
1217 }
1218 // verify file by file that the data packets are written correctly
1219 auto f_it = fileData.begin();
1220 for (auto f : fileNames) {
1221 // read file from disk
1222 std::vector<uint8_t> file_bytes;
1223 fs::ifstream is(f, fs::ifstream::binary | fs::ifstream::in);
1224 is >> std::noskipws;
1225 std::istream_iterator<uint8_t> start(is), end;
1226 file_bytes.insert(file_bytes.end(), start, end);
1227 std::vector<uint8_t> data_bytes;
1228 // get content from data packets
1229 for (const auto& d : *f_it) {
1230 auto content = d.getContent();
1231 data_bytes.insert(data_bytes.end(), content.value_begin(), content.value_end());
1232 }
1233 BOOST_CHECK(data_bytes == file_bytes);
1234 ++f_it;
1235 }
1236 fs::remove_all(filePath);
1237 fs::remove_all(".appdata");
1238 }
1239}
1240
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001241BOOST_AUTO_TEST_CASE(CheckWriteTorrentComplete)
1242{
1243 const struct {
1244 const char *d_directoryPath;
1245 const char *d_initialSegmentName;
1246 size_t d_namesPerSegment;
1247 size_t d_subManifestSize;
1248 size_t d_dataPacketSize;
1249 } DATA [] = {
1250 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
1251 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=96d900d6788465f9a7b00191581b004c910d74b3762d141ec0e82173731bc9f4", 1, 1, 1024},
1252 };
1253 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
1254 for (int i = 0; i < NUM_DATA; ++i) {
1255 auto directoryPath = DATA[i].d_directoryPath;
1256 Name initialSegmentName = DATA[i].d_initialSegmentName;
1257 auto namesPerSegment = DATA[i].d_namesPerSegment;
1258 auto dataPacketSize = DATA[i].d_dataPacketSize;
1259 auto subManifestSize = DATA[i].d_subManifestSize;
1260
1261 vector<TorrentFile> torrentSegments;
1262 std::string filePath = "tests/testdata/temp";
1263 // get torrent files
1264 {
1265 auto temp = TorrentFile::generate(directoryPath,
1266 namesPerSegment,
1267 subManifestSize,
1268 dataPacketSize,
1269 false);
1270 torrentSegments = temp.first;
1271 }
1272 // Initialize manager
1273 TestTorrentManager manager(initialSegmentName,
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001274 filePath,
1275 face);
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001276 manager.Initialize();
1277 std::string dirPath = ".appdata/foo/";
1278 std::string torrentPath = dirPath + "torrent_files/";
1279 BOOST_CHECK(manager.torrentSegments().empty());
1280 for (const auto& t : torrentSegments) {
1281 BOOST_CHECK(manager.writeTorrentSegment(t, torrentPath));
1282 }
1283 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
1284 // check that initializing a new manager also gets all the torrent torrentSegments
1285 TestTorrentManager manager2(initialSegmentName,
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001286 filePath,
1287 face);
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001288 manager2.Initialize();
1289 BOOST_CHECK(manager2.torrentSegments() == torrentSegments);
1290
1291 // start anew
1292 fs::remove_all(torrentPath);
1293 fs::create_directories(torrentPath);
1294 manager.Initialize();
1295 BOOST_CHECK(manager.torrentSegments().empty());
1296
1297 // check that there is no dependence on the order of torrent segments
1298 // randomize the order of the torrent segments
1299 auto torrentSegmentsRandom = torrentSegments;
1300 std::random_shuffle(torrentSegmentsRandom.begin(), torrentSegmentsRandom.end());
1301 for (const auto& t : torrentSegmentsRandom) {
1302 BOOST_CHECK(manager.writeTorrentSegment(t, torrentPath));
1303 }
1304 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
1305 fs::remove_all(".appdata");
1306 }
1307}
1308
1309BOOST_AUTO_TEST_CASE(CheckWriteManifestComplete)
1310{
1311 std::string dirPath = ".appdata/foo/";
1312 std::string torrentPath = dirPath + "torrent_files/";
1313 std::string manifestPath = dirPath + "manifests/";
1314
1315 const struct {
1316 const char *d_directoryPath;
1317 const char *d_initialSegmentName;
1318 size_t d_namesPerSegment;
1319 size_t d_subManifestSize;
1320 size_t d_dataPacketSize;
1321 } DATA [] = {
1322 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
1323 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 128, 128, 1024},
1324 };
1325 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
1326 for (int i = 0; i < NUM_DATA; ++i) {
1327 auto directoryPath = DATA[i].d_directoryPath;
1328 Name initialSegmentName = DATA[i].d_initialSegmentName;
1329 auto namesPerSegment = DATA[i].d_namesPerSegment;
1330 auto dataPacketSize = DATA[i].d_dataPacketSize;
1331 auto subManifestSize = DATA[i].d_subManifestSize;
1332
1333 vector<FileManifest> manifests;
1334 vector<TorrentFile> torrentSegments;
1335
1336 std::string filePath = "tests/testdata/temp";
1337 // get torrent files and manifests
1338 {
1339 auto temp = TorrentFile::generate(directoryPath,
1340 namesPerSegment,
1341 subManifestSize,
1342 dataPacketSize,
1343 false);
1344 torrentSegments = temp.first;
1345 auto temp1 = temp.second;
1346 for (const auto& ms : temp1) {
1347 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
1348 }
1349 }
1350 TestTorrentManager manager(initialSegmentName,
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001351 filePath,
1352 face);
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001353 manager.Initialize();
1354 for (const auto& t : torrentSegments) {
1355 manager.writeTorrentSegment(t, torrentPath);
1356 }
1357
1358 BOOST_CHECK(manager.fileManifests().empty());
1359 for (const auto& m : manifests) {
1360 BOOST_CHECK(manager.writeFileManifest(m, manifestPath));
1361 }
1362 BOOST_CHECK(manager.fileManifests() == manifests);
1363
1364 TestTorrentManager manager2(initialSegmentName,
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001365 filePath,
1366 face);
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001367
1368 manager2.Initialize();
1369 BOOST_CHECK(manager2.fileManifests() == manifests);
1370
1371 // start anew
1372 fs::remove_all(manifestPath);
1373 fs::create_directories(manifestPath);
1374 manager.Initialize();
1375 BOOST_CHECK(manager.fileManifests().empty());
1376
1377 // check that there is no dependence on the order of torrent segments
1378 // randomize the order of the torrent segments
1379 auto fileManifestsRandom = manifests;
1380 std::random_shuffle(fileManifestsRandom.begin(), fileManifestsRandom.end());
1381 for (const auto& m : fileManifestsRandom) {
1382 BOOST_CHECK(manager.writeFileManifest(m, manifestPath));
1383 }
1384 BOOST_CHECK(manager2.fileManifests() == manifests);
1385 fs::remove_all(".appdata");
1386 }
1387}
1388
spirosmastorakisa46eee42016-04-05 14:24:45 -07001389BOOST_AUTO_TEST_SUITE_END()
Mickey Sweattafda1f12016-04-04 17:15:11 -07001390
Mickey Sweatt527b0492016-03-02 11:07:48 -08001391} // namespace tests
1392} // namespace nTorrent
spirosmastorakisa46eee42016-04-05 14:24:45 -07001393} // namespace ndn