blob: 11a55eed5e777ac86d9c5e79a925885f38d7e983 [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
Mickey Sweattb7ee19c2016-04-21 12:18:15 -070016* General Public License along with nTorrent, e.g., in COPYING.md file. SoIf not, see
Mickey Sweatt527b0492016-03-02 11:07:48 -080017* <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
spirosmastorakis4ff8c872016-04-14 09:51:38 -070024#include "dummy-parser-fixture.hpp"
Mickey Sweatt527b0492016-03-02 11:07:48 -080025#include "torrent-manager.hpp"
26#include "torrent-file.hpp"
spirosmastorakisa46eee42016-04-05 14:24:45 -070027#include "unit-test-time-fixture.hpp"
Mickey Sweatt527b0492016-03-02 11:07:48 -080028
Mickey Sweattafda1f12016-04-04 17:15:11 -070029#include <set>
30
Mickey Sweatt527b0492016-03-02 11:07:48 -080031#include <boost/filesystem.hpp>
32
spirosmastorakisa46eee42016-04-05 14:24:45 -070033#include <ndn-cxx/util/dummy-client-face.hpp>
Mickey Sweatt527b0492016-03-02 11:07:48 -080034#include <ndn-cxx/util/io.hpp>
35
36namespace ndn {
37namespace ntorrent {
38namespace tests {
39
40using std::vector;
41using ndn::Name;
spirosmastorakisa46eee42016-04-05 14:24:45 -070042using ndn::util::DummyClientFace;
Mickey Sweatt527b0492016-03-02 11:07:48 -080043
44namespace fs = boost::filesystem;
45
46class TestTorrentManager : public TorrentManager {
spirosmastorakis4ff8c872016-04-14 09:51:38 -070047public:
Mickey Sweatte908a5c2016-04-08 14:10:45 -070048 TestTorrentManager(const ndn::Name& torrentFileName,
49 const std::string& filePath,
50 std::shared_ptr<DummyClientFace> face)
Mickey Sweatt44e4fd92016-05-02 15:43:11 -070051 : TorrentManager(torrentFileName, filePath, false, face)
spirosmastorakis4ff8c872016-04-14 09:51:38 -070052 , m_face(face)
spirosmastorakisa46eee42016-04-05 14:24:45 -070053 {
spirosmastorakis4ff8c872016-04-14 09:51:38 -070054 m_keyChain = make_shared<KeyChain>();
spirosmastorakisa46eee42016-04-05 14:24:45 -070055 }
Mickey Sweatt527b0492016-03-02 11:07:48 -080056
57 std::vector<TorrentFile> torrentSegments() const {
58 return m_torrentSegments;
59 }
60
61 std::vector<FileManifest> fileManifests() const {
62 return m_fileManifests;
63 }
64
spirosmastorakis50642f82016-04-08 12:11:18 -070065 void pushTorrentSegment(const TorrentFile& t) {
66 m_torrentSegments.push_back(t);
67 }
68
69 void pushFileManifestSegment(const FileManifest& m) {
70 m_fileManifests.push_back(m);
71 }
72
73 shared_ptr<Name> findTorrentFileSegmentToDownload() {
74 return TorrentManager::findTorrentFileSegmentToDownload();
75 }
76
77 shared_ptr<Name> findManifestSegmentToDownload(const Name& manifestName) {
78 return TorrentManager::findManifestSegmentToDownload(manifestName);
79 }
80
Mickey Sweatt527b0492016-03-02 11:07:48 -080081 std::vector<bool> fileState(const ndn::Name& manifestName) {
Mickey Sweattafda1f12016-04-04 17:15:11 -070082 auto fout = m_fileStates[manifestName].first;
83 if (nullptr != fout) {
84 fout->flush();
85 }
Mickey Sweatt527b0492016-03-02 11:07:48 -080086 return m_fileStates[manifestName].second;
87 }
Mickey Sweattafda1f12016-04-04 17:15:11 -070088
spirosmastorakis50642f82016-04-08 12:11:18 -070089 void setFileState(const ndn::Name manifestName,
90 std::shared_ptr<fs::fstream> f,
91 const std::vector<bool>& stateVec) {
92
93 m_fileStates.insert({ manifestName, std::make_pair(f, stateVec) });
94 }
95
Mickey Sweattafda1f12016-04-04 17:15:11 -070096 bool writeData(const Data& data) {
97 return TorrentManager::writeData(data);
98 }
Mickey Sweatt599bfef2016-04-05 19:11:20 -070099
100 bool writeTorrentSegment(const TorrentFile& segment, const std::string& path) {
101 return TorrentManager::writeTorrentSegment(segment, path);
102 }
spirosmastorakis50642f82016-04-08 12:11:18 -0700103
Mickey Sweatt599bfef2016-04-05 19:11:20 -0700104 bool writeFileManifest(const FileManifest& manifest, const std::string& path) {
105 return TorrentManager::writeFileManifest(manifest, path);
106 }
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700107
108 void sendRoutablePrefixResponse() {
109 // Create a data packet containing one name as content
110 shared_ptr<Data> d = DummyParser::createDataPacket(Name("/localhop/nfd/rib/routable-prefixes"),
111 { Name("ucla") });
112 m_keyChain->sign(*d);
113 m_face->receive(*d);
114 }
115
116private:
117 shared_ptr<KeyChain> m_keyChain;
118 shared_ptr<DummyClientFace> m_face;
Mickey Sweatt527b0492016-03-02 11:07:48 -0800119};
120
spirosmastorakisa46eee42016-04-05 14:24:45 -0700121class FaceFixture : public UnitTestTimeFixture
122{
123public:
124 explicit
125 FaceFixture(bool enableRegistrationReply = true)
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700126 : face(new DummyClientFace(io, { true, enableRegistrationReply }))
spirosmastorakisa46eee42016-04-05 14:24:45 -0700127 {
128 }
129
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700130 ~FaceFixture()
131 {
132 fs::remove_all(".appdata");
133 }
134
spirosmastorakisa46eee42016-04-05 14:24:45 -0700135public:
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700136 std::shared_ptr<DummyClientFace> face;
spirosmastorakisa46eee42016-04-05 14:24:45 -0700137};
138
139class FacesNoRegistrationReplyFixture : public FaceFixture
140{
141public:
142 FacesNoRegistrationReplyFixture()
143 : FaceFixture(false)
144 {
145 }
146};
147
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700148BOOST_FIXTURE_TEST_SUITE(TestTorrentManagerInitialize, FaceFixture)
Mickey Sweatt527b0492016-03-02 11:07:48 -0800149
150BOOST_AUTO_TEST_CASE(CheckInitializeComplete)
151{
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700152 const struct {
153 const char *d_directoryPath;
154 const char *d_initialSegmentName;
155 size_t d_namesPerSegment;
156 size_t d_subManifestSize;
157 size_t d_dataPacketSize;
158 } DATA [] = {
159 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
160 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=b88c054e87bcbb744726f7eaf79f95459b4fddce2caeb952f263a5ccbbfc9a7c", 128, 128, 128},
161 // {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=76df604f23bdf257d16de588f2941df261951552a5f4435a315f59c3b018a851", 1, 1, 128},
162 };
163 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
164 for (int i = 0; i < NUM_DATA; ++i) {
165 auto directoryPath = DATA[i].d_directoryPath;
166 Name initialSegmentName = DATA[i].d_initialSegmentName;
167 auto namesPerSegment = DATA[i].d_namesPerSegment;
168 auto dataPacketSize = DATA[i].d_dataPacketSize;
169 auto subManifestSize = DATA[i].d_subManifestSize;
Mickey Sweatt527b0492016-03-02 11:07:48 -0800170
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700171 vector<FileManifest> manifests;
172 vector<TorrentFile> torrentSegments;
173 std::string filePath = "tests/testdata/";
174 // get torrent files and manifests
175 {
176 auto temp = TorrentFile::generate(directoryPath,
177 namesPerSegment,
178 subManifestSize,
179 dataPacketSize,
180 false);
181 torrentSegments = temp.first;
182 auto temp1 = temp.second;
183 for (const auto& ms : temp1) {
184 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
185 }
Mickey Sweatt527b0492016-03-02 11:07:48 -0800186 }
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700187 // write the torrent segments and manifests to disk
188 std::string dirPath = ".appdata/foo/";
189 boost::filesystem::create_directories(dirPath);
190 std::string torrentPath = dirPath + "torrent_files/";
191 boost::filesystem::create_directory(torrentPath);
192 auto fileNum = 0;
193 for (const auto& t : torrentSegments) {
194 fileNum++;
195 auto filename = torrentPath + to_string(fileNum);
196 io::save(t, filename);
197 }
198 auto manifestPath = dirPath + "manifests/";
199 boost::filesystem::create_directory(manifestPath);
200 for (const auto& m : manifests) {
201 fs::path filename = manifestPath + m.file_name() + "/" + to_string(m.submanifest_number());
202 boost::filesystem::create_directories(filename.parent_path());
203 io::save(m, filename.string());
204 }
205 // Initialize and verify
206 TestTorrentManager manager(initialSegmentName,
207 filePath,
208 face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700209
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700210 manager.Initialize();
Mickey Sweatt15dde2d2016-04-28 23:42:45 -0700211 BOOST_CHECK(manager.hasAllTorrentSegments());
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700212
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700213 advanceClocks(time::milliseconds(1), 10);
214 manager.sendRoutablePrefixResponse();
215
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700216 // Check that the torrent segments and file manifests match (content and order)
217 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
218 BOOST_CHECK(manager.fileManifests() == manifests);
219 // next check the data packet state vectors
220 for (auto m : manager.fileManifests()) {
221 auto fileState = manager.fileState(m.getFullName());
222 BOOST_CHECK(fileState.size() == m.catalog().size());
223 for (auto s : fileState) {
224 BOOST_CHECK(s);
225 }
226 }
227 fs::remove_all(dirPath);
Mickey Sweatt527b0492016-03-02 11:07:48 -0800228 }
Mickey Sweatt527b0492016-03-02 11:07:48 -0800229}
230
231BOOST_AUTO_TEST_CASE(CheckInitializeEmpty)
232{
233 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253",
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700234 "tests/testdata/", face);
235
Mickey Sweatt527b0492016-03-02 11:07:48 -0800236 manager.Initialize();
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700237
238 advanceClocks(time::milliseconds(1), 10);
239 manager.sendRoutablePrefixResponse();
240
Mickey Sweatt15dde2d2016-04-28 23:42:45 -0700241 BOOST_CHECK(!manager.hasAllTorrentSegments());
242
Mickey Sweatt527b0492016-03-02 11:07:48 -0800243 BOOST_CHECK(manager.torrentSegments() == vector<TorrentFile>());
244 BOOST_CHECK(manager.fileManifests() == vector<FileManifest>());
245}
246
247BOOST_AUTO_TEST_CASE(CheckInitializeNoManifests)
248{
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700249 const struct {
250 const char *d_directoryPath;
251 const char *d_initialSegmentName;
252 size_t d_namesPerSegment;
253 size_t d_subManifestSize;
254 size_t d_dataPacketSize;
255 } DATA [] = {
256 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
257 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=b88c054e87bcbb744726f7eaf79f95459b4fddce2caeb952f263a5ccbbfc9a7c", 128, 128, 128},
258 // {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=76df604f23bdf257d16de588f2941df261951552a5f4435a315f59c3b018a851", 1, 1, 128},
259 };
260 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
261 for (int i = 0; i < NUM_DATA; ++i) {
262 auto directoryPath = DATA[i].d_directoryPath;
263 Name initialSegmentName = DATA[i].d_initialSegmentName;
264 auto namesPerSegment = DATA[i].d_namesPerSegment;
265 auto dataPacketSize = DATA[i].d_dataPacketSize;
266 auto subManifestSize = DATA[i].d_subManifestSize;
Mickey Sweatt527b0492016-03-02 11:07:48 -0800267
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700268 vector<FileManifest> manifests;
269 vector<TorrentFile> torrentSegments;
270 std::string filePath = "tests/testdata/";
271 // get torrent files and manifests
272 {
273 auto temp = TorrentFile::generate(directoryPath,
274 namesPerSegment,
275 subManifestSize,
276 dataPacketSize,
277 false);
278 torrentSegments = temp.first;
279 }
280 // write the torrent segments and manifests to disk
281 std::string dirPath = ".appdata/foo/";
282 boost::filesystem::create_directories(dirPath);
283 std::string torrentPath = dirPath + "torrent_files/";
284 boost::filesystem::create_directory(torrentPath);
285 auto fileNum = 0;
286 for (const auto& t : torrentSegments) {
287 fileNum++;
288 auto filename = torrentPath + to_string(fileNum);
289 io::save(t, filename);
290 }
291 // Initialize and verify
292 TestTorrentManager manager(initialSegmentName,
293 filePath,
294 face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700295
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700296 manager.Initialize();
Mickey Sweatt15dde2d2016-04-28 23:42:45 -0700297 BOOST_CHECK(manager.hasAllTorrentSegments());
Mickey Sweatt527b0492016-03-02 11:07:48 -0800298
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700299 advanceClocks(time::milliseconds(1), 10);
300 manager.sendRoutablePrefixResponse();
301
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700302 // Check that the torrent segments and file manifests match (content and order)
303 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
304 BOOST_CHECK(manager.fileManifests() == vector<FileManifest>());
305
306 fs::remove_all(".appdata");
307 }
Mickey Sweatt527b0492016-03-02 11:07:48 -0800308}
309
310BOOST_AUTO_TEST_CASE(CheckInitializeMissingManifests)
311{
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700312 const struct {
313 const char *d_directoryPath;
314 const char *d_initialSegmentName;
315 size_t d_namesPerSegment;
316 size_t d_subManifestSize;
317 size_t d_dataPacketSize;
318 } DATA [] = {
319 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
320 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=b88c054e87bcbb744726f7eaf79f95459b4fddce2caeb952f263a5ccbbfc9a7c", 128, 128, 128},
321 // {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=76df604f23bdf257d16de588f2941df261951552a5f4435a315f59c3b018a851", 1, 1, 128},
322 };
323 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
324 for (int i = 0; i < NUM_DATA; ++i) {
325 auto directoryPath = DATA[i].d_directoryPath;
326 Name initialSegmentName = DATA[i].d_initialSegmentName;
327 auto namesPerSegment = DATA[i].d_namesPerSegment;
328 auto dataPacketSize = DATA[i].d_dataPacketSize;
329 auto subManifestSize = DATA[i].d_subManifestSize;
Mickey Sweatt527b0492016-03-02 11:07:48 -0800330
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700331 vector<FileManifest> manifests;
332 vector<TorrentFile> torrentSegments;
333 std::string filePath = "tests/testdata/";
334 // get torrent files and manifests
335 {
336 auto temp = TorrentFile::generate(directoryPath,
337 namesPerSegment,
338 subManifestSize,
339 dataPacketSize,
340 false);
341 torrentSegments = temp.first;
342 auto temp1 = temp.second;
343 temp1.pop_back(); // remove the manifests for the last file
344 for (const auto& ms : temp1) {
345 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
346 }
Mickey Sweatt527b0492016-03-02 11:07:48 -0800347 }
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700348 // write the torrent segments and manifests to disk
349 std::string dirPath = ".appdata/foo/";
350 boost::filesystem::create_directories(dirPath);
351 std::string torrentPath = dirPath + "torrent_files/";
352 boost::filesystem::create_directories(torrentPath);
353 auto fileNum = 0;
354 for (const auto& t : torrentSegments) {
355 fileNum++;
356 auto filename = torrentPath + to_string(fileNum);
357 io::save(t, filename);
358 }
359 auto manifestPath = dirPath + "manifests/";
360 boost::filesystem::create_directory(manifestPath);
361 for (const auto& m : manifests) {
362 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
363 boost::filesystem::create_directory(filename.parent_path());
364 io::save(m, filename.string());
365 }
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700366
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700367 // Initialize and verify
368 TestTorrentManager manager(initialSegmentName,
369 filePath,
370 face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700371
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700372 manager.Initialize();
Mickey Sweatt15dde2d2016-04-28 23:42:45 -0700373 BOOST_CHECK(manager.hasAllTorrentSegments());
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700374
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700375 advanceClocks(time::milliseconds(1), 10);
376 manager.sendRoutablePrefixResponse();
377
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700378 // Check that the torrent segments and file manifests match (content and order)
379 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
380 BOOST_CHECK(manager.fileManifests() == manifests);
381 // next check the data packet state vectors
382 for (auto m : manager.fileManifests()) {
383 auto fileState = manager.fileState(m.getFullName());
384 BOOST_CHECK(fileState.size() == m.catalog().size());
385 for (auto s : fileState) {
386 BOOST_CHECK(s);
387 }
388 }
389 fs::remove_all(".appdata");
Mickey Sweatt527b0492016-03-02 11:07:48 -0800390 }
Mickey Sweatt527b0492016-03-02 11:07:48 -0800391}
392
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700393BOOST_AUTO_TEST_SUITE_END()
394
spirosmastorakisa46eee42016-04-05 14:24:45 -0700395BOOST_FIXTURE_TEST_SUITE(TestTorrentManagerNetworkingStuff, FaceFixture)
396
397BOOST_AUTO_TEST_CASE(TestDownloadingTorrentFile)
398{
399 vector<FileManifest> manifests;
400 vector<TorrentFile> torrentSegments;
401 std::string filePath = ".appdata/foo/";
402 // get torrent files and manifests
403 {
404 auto temp = TorrentFile::generate("tests/testdata/foo", 1, 10, 10, false);
405
406 torrentSegments = temp.first;
407 auto temp1 = temp.second;
408 temp1.pop_back(); // remove the manifests for the last file
409 for (const auto& ms : temp1) {
410 for (const auto& m : ms.first) {
411 manifests.push_back(m);
412 }
413 }
414 }
415
416 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=946b92641d2b87bf4f5913930be20e3789ff5fb5d72739614f93f677d90fbd9d",
417 filePath, face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700418
spirosmastorakisa46eee42016-04-05 14:24:45 -0700419 manager.Initialize();
Mickey Sweatt15dde2d2016-04-28 23:42:45 -0700420 BOOST_CHECK(!manager.hasAllTorrentSegments());
spirosmastorakisa46eee42016-04-05 14:24:45 -0700421
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700422 advanceClocks(time::milliseconds(1), 10);
423 manager.sendRoutablePrefixResponse();
424
spirosmastorakisa46eee42016-04-05 14:24:45 -0700425 // Test download torrent file segments
426 uint32_t counter = 0;
spirosmastorakis50642f82016-04-08 12:11:18 -0700427 manager.downloadTorrentFile(filePath + "torrent_files", [&counter, &torrentSegments]
428 (const std::vector<ndn::Name>& vec) {
429 uint32_t manifestNum = 0;
430 for (auto i = vec.begin(); i != vec.end(); i++) {
431 Name n = torrentSegments[counter].getCatalog()[manifestNum];
432 BOOST_CHECK_EQUAL(n, *i);
433 manifestNum++;
434 }
435 counter++;
436 },
437 bind([] {
438 BOOST_FAIL("Unexpected failure");
439 }));
spirosmastorakisa46eee42016-04-05 14:24:45 -0700440
441 for (auto i = torrentSegments.begin(); i != torrentSegments.end(); i++) {
442 advanceClocks(time::milliseconds(1), 40);
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700443 face->receive(dynamic_cast<Data&>(*i));
spirosmastorakisa46eee42016-04-05 14:24:45 -0700444 }
Mickey Sweatt15dde2d2016-04-28 23:42:45 -0700445 BOOST_CHECK(manager.hasAllTorrentSegments());
spirosmastorakisa46eee42016-04-05 14:24:45 -0700446 fs::remove_all(filePath);
spirosmastorakis50642f82016-04-08 12:11:18 -0700447 fs::remove_all(".appdata");
spirosmastorakisa46eee42016-04-05 14:24:45 -0700448}
449
450BOOST_AUTO_TEST_CASE(TestDownloadingFileManifests)
451{
452 vector<FileManifest> manifests;
453 vector<TorrentFile> torrentSegments;
454 std::string filePath = ".appdata/foo/";
455 // get torrent files and manifests
456 {
457 auto temp = TorrentFile::generate("tests/testdata/foo", 1, 10, 10, false);
458
459 torrentSegments = temp.first;
460 auto temp1 = temp.second;
461 temp1.pop_back(); // remove the manifests for the last file
462 for (const auto& ms : temp1) {
463 for (const auto& m : ms.first) {
464 manifests.push_back(m);
465 }
466 }
467 }
468
469 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=946b92641d2b87bf4f5913930be20e3789ff5fb5d72739614f93f677d90fbd9d",
470 filePath, face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700471
spirosmastorakisa46eee42016-04-05 14:24:45 -0700472 manager.Initialize();
473
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700474 advanceClocks(time::milliseconds(1), 10);
475 manager.sendRoutablePrefixResponse();
476
spirosmastorakisa46eee42016-04-05 14:24:45 -0700477 // Test download manifest segments -- 2 files (the first one segment, the second multiple)
478 int counter = 0;
479 manager.download_file_manifest(manifests[0].getFullName(), filePath + "manifests",
480 [&counter, &manifests]
481 (const std::vector<ndn::Name>& vec) {
482 uint32_t packetIndex = 0;
483 for (auto j = vec.begin(); j != vec.end(); j++) {
484 BOOST_CHECK_EQUAL(manifests[counter].catalog()[packetIndex],
485 *j);
486 packetIndex++;
487 }
488 counter++;
489 },
490 [](const ndn::Name& name, const std::string& reason) {
491 BOOST_FAIL("Unexpected failure");
492 });
493
494 advanceClocks(time::milliseconds(1), 40);
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700495 face->receive(dynamic_cast<Data&>(manifests[0]));
spirosmastorakisa46eee42016-04-05 14:24:45 -0700496
497 manager.download_file_manifest(manifests[1].getFullName(), filePath + "manifests",
498 [&counter, &manifests]
499 (const std::vector<ndn::Name>& vec) {
500 uint32_t packetIndex = 0;
501 for (auto j = vec.begin(); j != vec.end(); j++) {
502 BOOST_CHECK_EQUAL(manifests[counter].catalog()[packetIndex],
503 *j);
504 // if we have read all the packet names from a
505 // segment, move to the next one
506 if (packetIndex == manifests[counter].catalog().size() - 1) {
507 packetIndex = 0;
508 counter++;
509 }
510 else {
511 packetIndex++;
512 }
513 }
514 },
515 [](const ndn::Name& name, const std::string& reason) {
516 BOOST_FAIL("Unexpected failure");
517 });
518
519 for (auto i = manifests.begin() + 1; i != manifests.end(); i++) {
520 advanceClocks(time::milliseconds(1), 40);
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700521 face->receive(dynamic_cast<Data&>(*i));
spirosmastorakisa46eee42016-04-05 14:24:45 -0700522 }
523
524 fs::remove_all(filePath);
spirosmastorakis50642f82016-04-08 12:11:18 -0700525 fs::remove_all(".appdata");
spirosmastorakisa46eee42016-04-05 14:24:45 -0700526}
527
528BOOST_AUTO_TEST_CASE(TestDownloadingDataPackets)
529{
530 std::string filePath = ".appdata/foo/";
531 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=946b92641d2b87bf4f5913930be20e3789ff5fb5d72739614f93f677d90fbd9d",
532 filePath, face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700533
spirosmastorakisa46eee42016-04-05 14:24:45 -0700534 manager.Initialize();
535
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700536 advanceClocks(time::milliseconds(1), 10);
537 manager.sendRoutablePrefixResponse();
538
spirosmastorakisa46eee42016-04-05 14:24:45 -0700539 Name dataName("/test/ucla");
540
541 // Download data successfully
542 manager.download_data_packet(dataName,
543 [&dataName] (const ndn::Name& name) {
544 BOOST_CHECK_EQUAL(name, dataName);
545 },
546 [](const ndn::Name& name, const std::string& reason) {
547 BOOST_FAIL("Unexpected failure");
548 });
549
550 auto data = make_shared<Data>(dataName);
551 SignatureSha256WithRsa fakeSignature;
552 fakeSignature.setValue(encoding::makeEmptyBlock(tlv::SignatureValue));
553 data->setSignature(fakeSignature);
554 data->wireEncode();
555
556 advanceClocks(time::milliseconds(1), 40);
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700557 face->receive(*data);
spirosmastorakisa46eee42016-04-05 14:24:45 -0700558
559 // Fail to download data
560 manager.download_data_packet(dataName,
spirosmastorakis50642f82016-04-08 12:11:18 -0700561 [](const ndn::Name& name) {
spirosmastorakisa46eee42016-04-05 14:24:45 -0700562 BOOST_FAIL("Unexpected failure");
563 },
564 [&dataName](const ndn::Name& name, const std::string& reason) {
565 BOOST_CHECK_EQUAL(name, dataName);
566 });
567
568 advanceClocks(time::milliseconds(1), 2100);
569
570 fs::remove_all(filePath);
spirosmastorakis50642f82016-04-08 12:11:18 -0700571 fs::remove_all(".appdata");
572}
573
574// we already have downloaded the torrent file
575BOOST_AUTO_TEST_CASE(TestFindTorrentFileSegmentToDownload1)
576{
577 std::string filePath = ".appdata/foo/";
578 TestTorrentManager manager("NTORRENT/test/torrent-file/sha256digest",
579 filePath, face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700580
spirosmastorakis50642f82016-04-08 12:11:18 -0700581 manager.Initialize();
582
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700583 advanceClocks(time::milliseconds(1), 10);
584 manager.sendRoutablePrefixResponse();
585
spirosmastorakis50642f82016-04-08 12:11:18 -0700586 TorrentFile t1(Name("NTORRENT/test/torrent-file/sha256digest"),
587 Name("NTORRENT/test/torrent-file/1/sha256digest"), Name("/test"),
588 { Name("/manifest1") });
589 manager.pushTorrentSegment(t1);
590
591 TorrentFile t2(Name("NTORRENT/test/torrent-file/1/sha256digest"),
592 Name("NTORRENT/test/torrent-file/2/sha256digest"), Name("/test"),
593 { Name("/manifest2"), Name("/manifest3") });
594 manager.pushTorrentSegment(t2);
595
596 TorrentFile t3(Name("NTORRENT/test/torrent-file/3/sha256digest"),
597 Name("NTORRENT/test/torrent-file/4/sha256digest"), Name("/test"),
598 { Name("/manifest4"), Name("/manifest5") });
599 manager.pushTorrentSegment(t3);
600
601 TorrentFile t4(Name("NTORRENT/test/torrent-file/4/sha256digest"), Name("/test"), {});
602 manager.pushTorrentSegment(t4);
603
604 BOOST_CHECK(!(manager.findTorrentFileSegmentToDownload()));
605
606 std::vector<Name> manifests;
Mickey Sweatt15dde2d2016-04-28 23:42:45 -0700607 manager.downloadTorrentFile("/test");
608 manager.findFileManifestsToDownload(manifests);
spirosmastorakis50642f82016-04-08 12:11:18 -0700609
610 BOOST_CHECK_EQUAL(manifests[0].toUri(), "/manifest1");
611 BOOST_CHECK_EQUAL(manifests[1].toUri(), "/manifest2");
612 BOOST_CHECK_EQUAL(manifests[2].toUri(), "/manifest3");
613 BOOST_CHECK_EQUAL(manifests[3].toUri(), "/manifest4");
614 BOOST_CHECK_EQUAL(manifests[4].toUri(), "/manifest5");
615
616 fs::remove_all(filePath);
617 fs::remove_all(".appdata");
618}
619
620// we do not have the torrent file
621BOOST_AUTO_TEST_CASE(TestFindTorrentFileSegmentToDownload2)
622{
623 std::string filePath = ".appdata/foo/";
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700624 TestTorrentManager manager("NTORRENT/test/torrent-file/0/sha256digest",
spirosmastorakis50642f82016-04-08 12:11:18 -0700625 filePath, face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700626
spirosmastorakis50642f82016-04-08 12:11:18 -0700627 manager.Initialize();
628
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700629 advanceClocks(time::milliseconds(1), 10);
630 manager.sendRoutablePrefixResponse();
631
632 BOOST_CHECK_EQUAL(manager.findTorrentFileSegmentToDownload()->toUri(),
633 "/NTORRENT/test/torrent-file/0/sha256digest");
spirosmastorakis50642f82016-04-08 12:11:18 -0700634
635 fs::remove_all(filePath);
636 fs::remove_all(".appdata");
637}
638
spirosmastorakis50642f82016-04-08 12:11:18 -0700639BOOST_AUTO_TEST_CASE(TestFindManifestSegmentToDownload1)
640{
641 std::string filePath = ".appdata/foo/";
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700642 TestTorrentManager manager("NTORRENT/test/torrent-file/sha256digest",
spirosmastorakis50642f82016-04-08 12:11:18 -0700643 filePath, face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700644
spirosmastorakis50642f82016-04-08 12:11:18 -0700645 manager.Initialize();
646
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700647 advanceClocks(time::milliseconds(1), 10);
648 manager.sendRoutablePrefixResponse();
649
spirosmastorakis50642f82016-04-08 12:11:18 -0700650 Name n1(Name("NTORRENT/test/file0"));
651 n1.appendSequenceNumber(0);
652
653 Name n2(Name("NTORRENT/test/file0"));
654 n2.appendSequenceNumber(1);
655
656 Name n3(Name("NTORRENT/test/file0"));
657 n3.appendSequenceNumber(2);
658
659 Name n4(Name("NTORRENT/test/file0"));
660 n4.appendSequenceNumber(3);
661
662 Name n5(Name("NTORRENT/test/file0"));
663 n5.appendSequenceNumber(4);
664
665 Name n6(Name("NTORRENT/test1/file0"));
666 n6.appendSequenceNumber(0);
667
668 Name n7(Name("NTORRENT/test1/file0"));
669 n7.appendSequenceNumber(1);
670
671 // In theory, this may not be correct, but here let's suck it up for the sake
672 // of testing the function correctness
673 Name n8(Name("NTORRENT/test1/file2"));
674 n8.appendSequenceNumber(0);
675
676 Name n9(Name("NTORRENT/test1/file2"));
677 n9.appendSequenceNumber(1);
678
679 FileManifest f1(n1, 50, Name("NTORRENT/test"), {}, make_shared<Name>(n2));
680 manager.pushFileManifestSegment(f1);
681
682 FileManifest f2(n2, 50, Name("NTORRENT/test"), {}, make_shared<Name>(n3));
683 manager.pushFileManifestSegment(f2);
684
685 FileManifest f3(n3, 50, Name("NTORRENT/test"), {}, make_shared<Name>(n4));
686 manager.pushFileManifestSegment(f3);
687
688 FileManifest f4(n4, 50, Name("NTORRENT/test"), {}, make_shared<Name>(n5));
689 manager.pushFileManifestSegment(f4);
690
691 FileManifest f5(n6, 50, Name("NTORRENT/test2"), {}, make_shared<Name>(n7));
692 manager.pushFileManifestSegment(f5);
693
694 FileManifest f6(n7, 50, Name("NTORRENT/test2"), {}, {});
695 manager.pushFileManifestSegment(f6);
696
697 FileManifest f7(n8, 50, Name("NTORRENT/test3"), {}, make_shared<Name>(n9));
698 manager.pushFileManifestSegment(f7);
699
700 BOOST_CHECK_EQUAL(manager.findManifestSegmentToDownload(Name(n2.toUri() + "/sha256digest"))->toUri(), n5.toUri());
701 BOOST_CHECK_EQUAL(manager.findManifestSegmentToDownload(Name(n8.toUri() + "/sha256digest"))->toUri(), n9.toUri());
702 BOOST_CHECK_EQUAL(manager.findManifestSegmentToDownload(Name(n5.toUri() + "/sha256digest"))->toUri(),
703 Name(n5.toUri() + "/sha256digest").toUri());
704 BOOST_CHECK(!(manager.findManifestSegmentToDownload(Name(n7.toUri() + "/sha256digest"))));
705
706 Name n10(Name("NTORRENT/test1/file1"));
707 n10.appendSequenceNumber(1);
708 n10 = Name(n10.toUri() + "/sha256digest");
709
710 BOOST_CHECK_EQUAL(manager.findManifestSegmentToDownload(n10)->toUri(), n10.toUri());
spirosmastorakis50642f82016-04-08 12:11:18 -0700711}
712
713BOOST_AUTO_TEST_CASE(TestFindManifestSegmentToDownload2)
714{
715 vector<FileManifest> manifests;
716 vector<TorrentFile> torrentSegments;
717 // for each file, the data packets
718 std::vector<vector<Data>> fileData;
719 std::string filePath = "tests/testdata/temp";
720 // get torrent files and manifests
721 {
722 auto temp = TorrentFile::generate("tests/testdata/foo",
723 1024,
724 2048,
725 8192,
726 true);
727 torrentSegments = temp.first;
728 auto temp1 = temp.second;
729 for (const auto& ms : temp1) {
730 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
731 fileData.push_back(ms.second);
732 }
733 }
734 // write the torrent segments and manifests to disk
735 std::string dirPath = ".appdata/foo/";
736 boost::filesystem::create_directories(dirPath);
737 std::string torrentPath = dirPath + "torrent_files/";
738 boost::filesystem::create_directories(torrentPath);
739 auto fileNum = 0;
740 for (const auto& t : torrentSegments) {
741 fileNum++;
742 auto filename = torrentPath + to_string(fileNum);
743 io::save(t, filename);
744 }
745
746 auto manifestPath = dirPath + "manifests/";
747 boost::filesystem::create_directory(manifestPath);
748 for (const auto& m : manifests) {
749 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
750 boost::filesystem::create_directory(filename.parent_path());
751 io::save(m, filename.string());
752 }
753 // Initialize manager
754 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=a8a2e98cd943d895b8c4b12a208343bcf9344ce85a6376dc6f5754fe8f4a573e",
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700755 filePath,
756 face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700757
spirosmastorakis50642f82016-04-08 12:11:18 -0700758 manager.Initialize();
759
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700760 advanceClocks(time::milliseconds(1), 10);
761 manager.sendRoutablePrefixResponse();
762
spirosmastorakis50642f82016-04-08 12:11:18 -0700763 // Set the file state
764 std::vector<bool> v1 = {true};
765 manager.setFileState(manifests[0].getFullName(), make_shared<fs::fstream>(), v1);
766
767 std::vector<bool> v2 = {false, true, true, false, false, false};
768 manager.setFileState(manifests[1].getFullName(), make_shared<fs::fstream>(), v2);
769
770 std::vector<bool> v3 = {true, false, false, false, false, false};
771 manager.setFileState(manifests[2].getFullName(), make_shared<fs::fstream>(), v3);
772
773 manager.download_file_manifest(manifests[0].getFullName(), filePath + "manifests",
774 [&manifests](const std::vector<ndn::Name>& vec) {
775 BOOST_CHECK_EQUAL(vec.size(), 0);
776 },
777 [](const ndn::Name& name, const std::string& reason) {
778 BOOST_FAIL("Unexpected failure");
779 });
780
781 manager.download_file_manifest(manifests[1].getFullName(), filePath + "manifests",
782 [&manifests](const std::vector<ndn::Name>& vec) {
783 BOOST_CHECK_EQUAL(vec[0].toUri(),
784 manifests[1].catalog()[0].toUri());
785 BOOST_CHECK_EQUAL(vec[1].toUri(),
786 manifests[1].catalog()[3].toUri());
787 BOOST_CHECK_EQUAL(vec[2].toUri(),
788 manifests[1].catalog()[4].toUri());
789 BOOST_CHECK_EQUAL(vec[3].toUri(),
790 manifests[1].catalog()[5].toUri());
791 },
792 [](const ndn::Name& name, const std::string& reason) {
793 BOOST_FAIL("Unexpected failure");
794 });
795
796 manager.download_file_manifest(manifests[2].getFullName(), filePath + "manifests",
797 [&manifests](const std::vector<ndn::Name>& vec) {
798 BOOST_CHECK_EQUAL(vec[0].toUri(),
799 manifests[2].catalog()[1].toUri());
800 BOOST_CHECK_EQUAL(vec[1].toUri(),
801 manifests[2].catalog()[2].toUri());
802 BOOST_CHECK_EQUAL(vec[2].toUri(),
803 manifests[2].catalog()[3].toUri());
804 BOOST_CHECK_EQUAL(vec[3].toUri(),
805 manifests[2].catalog()[4].toUri());
806 BOOST_CHECK_EQUAL(vec[4].toUri(),
807 manifests[2].catalog()[5].toUri());
808 },
809 [](const ndn::Name& name, const std::string& reason) {
810 BOOST_FAIL("Unexpected failure");
811 });
812 fs::remove_all(filePath);
813 fs::remove_all(".appdata");
814}
815
816BOOST_AUTO_TEST_CASE(TestDataAlreadyDownloaded)
817{
818 vector<FileManifest> manifests;
819 vector<TorrentFile> torrentSegments;
820 // for each file, the data packets
821 std::vector<vector<Data>> fileData;
822 std::string filePath = "tests/testdata/temp";
823 // get torrent files and manifests
824 {
825 auto temp = TorrentFile::generate("tests/testdata/foo",
826 1024,
827 2048,
828 8192,
829 true);
830 torrentSegments = temp.first;
831 auto temp1 = temp.second;
832 for (const auto& ms : temp1) {
833 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
834 fileData.push_back(ms.second);
835 }
836 }
837 // write the torrent segments and manifests to disk
838 std::string dirPath = ".appdata/foo/";
839 boost::filesystem::create_directories(dirPath);
840 std::string torrentPath = dirPath + "torrent_files/";
841 boost::filesystem::create_directories(torrentPath);
842 auto fileNum = 0;
843 for (const auto& t : torrentSegments) {
844 fileNum++;
845 auto filename = torrentPath + to_string(fileNum);
846 io::save(t, filename);
847 }
848
849 auto manifestPath = dirPath + "manifests/";
850 boost::filesystem::create_directory(manifestPath);
851 for (const auto& m : manifests) {
852 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
853 boost::filesystem::create_directory(filename.parent_path());
854 io::save(m, filename.string());
855 }
856 // Initialize manager
857 TestTorrentManager manager("/NTORRENT/foo/torrent-file/sha256digest=a8a2e98cd943d895b8c4b12a208343bcf9344ce85a6376dc6f5754fe8f4a573e",
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700858 filePath,
859 face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700860
spirosmastorakis50642f82016-04-08 12:11:18 -0700861 manager.Initialize();
Mickey Sweatt15dde2d2016-04-28 23:42:45 -0700862 BOOST_CHECK(manager.hasAllTorrentSegments());
spirosmastorakis50642f82016-04-08 12:11:18 -0700863
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700864 advanceClocks(time::milliseconds(1), 10);
865 manager.sendRoutablePrefixResponse();
866
spirosmastorakis50642f82016-04-08 12:11:18 -0700867 // Set the file state
868 std::vector<bool> v1 = {true};
869 manager.setFileState(manifests[0].getFullName(), make_shared<fs::fstream>(), v1);
870
871 std::vector<bool> v2 = {false, true, true, false, false, false};
872 manager.setFileState(manifests[1].getFullName(), make_shared<fs::fstream>(), v2);
873
874 std::vector<bool> v3 = {true, false, false, false, false, false};
875 manager.setFileState(manifests[2].getFullName(), make_shared<fs::fstream>(), v3);
876
877 Name p1("NTORRENT/foo/bar1.txt");
878 p1.appendSequenceNumber(0);
879 p1.appendSequenceNumber(0);
880 p1 = Name(p1.toUri() + "/sha256digest");
881
Mickey Sweatt15dde2d2016-04-28 23:42:45 -0700882 BOOST_CHECK(!(manager.hasDataPacket(p1)));
spirosmastorakis50642f82016-04-08 12:11:18 -0700883
884 Name p2("NTORRENT/foo/bar.txt");
885 p2.appendSequenceNumber(0);
886 p2.appendSequenceNumber(0);
887 p2 = Name(p2.toUri() + "/sha256digest");
888
Mickey Sweatt15dde2d2016-04-28 23:42:45 -0700889 BOOST_CHECK(manager.hasDataPacket(p2));
spirosmastorakisa46eee42016-04-05 14:24:45 -0700890}
891
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700892BOOST_AUTO_TEST_CASE(CheckSeedComplete)
893{
894 const struct {
895 const char *d_directoryPath;
896 const char *d_initialSegmentName;
897 size_t d_namesPerSegment;
898 size_t d_subManifestSize;
899 size_t d_dataPacketSize;
900 } DATA [] = {
901 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
902 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=b88c054e87bcbb744726f7eaf79f95459b4fddce2caeb952f263a5ccbbfc9a7c", 128, 128, 128},
903 // {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=76df604f23bdf257d16de588f2941df261951552a5f4435a315f59c3b018a851", 1, 1, 128},
904 };
905 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
906 for (int i = 0; i < NUM_DATA; ++i) {
907 auto directoryPath = DATA[i].d_directoryPath;
908 Name initialSegmentName = DATA[i].d_initialSegmentName;
909 auto namesPerSegment = DATA[i].d_namesPerSegment;
910 auto dataPacketSize = DATA[i].d_dataPacketSize;
911 auto subManifestSize = DATA[i].d_subManifestSize;
Mickey Sweatt527b0492016-03-02 11:07:48 -0800912
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700913 vector<FileManifest> manifests;
914 vector<TorrentFile> torrentSegments;
915 std::string filePath = "tests/testdata/";
916 std::vector<vector<Data>> fileData;
917 // get torrent files and manifests
918 {
919 auto temp = TorrentFile::generate(directoryPath,
920 namesPerSegment,
921 subManifestSize,
922 dataPacketSize,
923 false);
924 torrentSegments = temp.first;
925 auto temp1 = temp.second;
926 for (const auto& ms : temp1) {
927 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
928 fileData.push_back(ms.second);
929 }
930 }
931 // write the torrent segments and manifests to disk
932 std::string dirPath = ".appdata/foo/";
933 boost::filesystem::create_directories(dirPath);
934 std::string torrentPath = dirPath + "torrent_files/";
935 boost::filesystem::create_directory(torrentPath);
936 auto fileNum = 0;
937 for (const auto& t : torrentSegments) {
938 fileNum++;
939 auto filename = torrentPath + to_string(fileNum);
940 io::save(t, filename);
941 }
942 auto manifestPath = dirPath + "manifests/";
943 boost::filesystem::create_directory(manifestPath);
944 for (const auto& m : manifests) {
945 fs::path filename = manifestPath + m.file_name() + "/" + to_string(m.submanifest_number());
946 boost::filesystem::create_directories(filename.parent_path());
947 io::save(m, filename.string());
948 }
949 // Initialize and verify
950 TestTorrentManager manager(initialSegmentName,
951 filePath,
952 face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700953
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700954 manager.Initialize();
spirosmastorakis4ff8c872016-04-14 09:51:38 -0700955
956 advanceClocks(time::milliseconds(1), 10);
957 manager.sendRoutablePrefixResponse();
958
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700959 size_t nData = 0;
960 BOOST_CHECK_EQUAL(0, face->sentData.size());
961 // request all the torrent segments
962 for (const auto& t : torrentSegments) {
963 Interest interest(t.getFullName(), time::milliseconds(50));
964 face->expressInterest(interest,
965 [&t](const Interest& i, const Data& d) {
966 TorrentFile t1(d.wireEncode());
967 BOOST_CHECK(t == d);
968 BOOST_CHECK(t1 == t);
969 },
970 bind([] {
971 BOOST_FAIL("Unexpected Nack");
972 }),
973 bind([] {
974 BOOST_FAIL("Unexpected timeout");
975 }));
976 advanceClocks(time::milliseconds(1), 40);
977 face->receive(interest);
Mickey Sweatt15dde2d2016-04-28 23:42:45 -0700978 manager.processEvents(time::milliseconds(-1));
Mickey Sweatte908a5c2016-04-08 14:10:45 -0700979 // check that one piece of data is sent, and it is what was expected
980 BOOST_CHECK_EQUAL(++nData, face->sentData.size());
981 face->receive(face->sentData[nData - 1]);
982 }
983 // request all the file manifests
984 for (const auto& m : manifests) {
985 Interest interest(m.getFullName(), time::milliseconds(50));
986 face->expressInterest(interest,
987 [&m](const Interest& i, const Data& d) {
988 FileManifest m1(d.wireEncode());
989 BOOST_CHECK(m == d);
990 BOOST_CHECK(m1 == m);
991 },
992 bind([] {
993 BOOST_FAIL("Unexpected Nack");
994 }),
995 bind([] {
996 BOOST_FAIL("Unexpected timeout");
997 }));
998 advanceClocks(time::milliseconds(1), 40);
999 face->receive(interest);
Mickey Sweatt15dde2d2016-04-28 23:42:45 -07001000 manager.processEvents(time::milliseconds(-1));
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001001 // check that one piece of data is sent, and it is what was expected
1002 BOOST_CHECK_EQUAL(++nData, face->sentData.size());
1003 face->receive(face->sentData[nData - 1]);
1004 }
1005 // request all the data packets
1006 for (const auto& file : fileData) {
1007 for (const auto& data : file) {
Mickey Sweattb7ee19c2016-04-21 12:18:15 -07001008 Interest interest(data.getFullName(), time::milliseconds(50));
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001009 face->expressInterest(interest,
1010 [&data](const Interest& i, const Data& d) {
1011 BOOST_CHECK(data == d);
1012 },
1013 bind([] {
1014 BOOST_FAIL("Unexpected Nack");
1015 }),
1016 bind([] {
1017 BOOST_FAIL("Unexpected timeout");
1018 }));
1019 advanceClocks(time::milliseconds(1), 40);
1020 face->receive(interest);
Mickey Sweatt15dde2d2016-04-28 23:42:45 -07001021 manager.processEvents(time::milliseconds(-1));
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001022 // check that one piece of data is sent, and it is what was expected
1023 BOOST_CHECK_EQUAL(++nData, face->sentData.size());
1024 face->receive(face->sentData[nData - 1]);
1025 }
1026 }
1027 // clean up tests
1028 face->sentData.clear();
1029 fs::remove_all(".appdata/");
1030 }
1031}
Mickey Sweattafda1f12016-04-04 17:15:11 -07001032
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001033BOOST_AUTO_TEST_CASE(CheckSeedRandom)
Mickey Sweattafda1f12016-04-04 17:15:11 -07001034{
1035 vector<FileManifest> manifests;
1036 vector<TorrentFile> torrentSegments;
1037 // for each file, the data packets
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001038 std::vector<Data> data;
1039 std::string filePath = "tests/testdata/";
1040 std::string dirPath = ".appdata/foo/";
1041 Name initialSegmentName = "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253";
Mickey Sweattafda1f12016-04-04 17:15:11 -07001042 // get torrent files and manifests
1043 {
1044 auto temp = TorrentFile::generate("tests/testdata/foo",
1045 1024,
1046 1024,
1047 1024,
1048 true);
1049 torrentSegments = temp.first;
1050 auto temp1 = temp.second;
1051 for (const auto& ms : temp1) {
1052 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001053 data.insert(data.end(), ms.second.begin(), ms.second.end());
Mickey Sweattafda1f12016-04-04 17:15:11 -07001054 }
1055 }
1056 // write the torrent segments and manifests to disk
Mickey Sweattafda1f12016-04-04 17:15:11 -07001057 boost::filesystem::create_directories(dirPath);
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001058 auto torrentPath = dirPath + "torrent_files/";
Mickey Sweattafda1f12016-04-04 17:15:11 -07001059 boost::filesystem::create_directories(torrentPath);
1060 auto fileNum = 0;
1061 for (const auto& t : torrentSegments) {
1062 fileNum++;
1063 auto filename = torrentPath + to_string(fileNum);
1064 io::save(t, filename);
1065 }
Mickey Sweattafda1f12016-04-04 17:15:11 -07001066 auto manifestPath = dirPath + "manifests/";
1067 boost::filesystem::create_directory(manifestPath);
1068 for (const auto& m : manifests) {
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001069 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
1070 boost::filesystem::create_directory(filename.parent_path());
1071 io::save(m, filename.string());
Mickey Sweattafda1f12016-04-04 17:15:11 -07001072 }
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001073
Mickey Sweattafda1f12016-04-04 17:15:11 -07001074 // Initialize manager
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001075 TestTorrentManager manager(initialSegmentName,
1076 filePath,
1077 face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -07001078
Mickey Sweattafda1f12016-04-04 17:15:11 -07001079 manager.Initialize();
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001080
spirosmastorakis4ff8c872016-04-14 09:51:38 -07001081 advanceClocks(time::milliseconds(1), 10);
1082 manager.sendRoutablePrefixResponse();
1083
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001084 // insert the other entities
1085 data.insert(data.end(), torrentSegments.begin(), torrentSegments.end());
1086 data.insert(data.end(), manifests.begin(), manifests.end());
1087
1088 std::random_shuffle(data.begin(), data.end());
1089 // request all the data packets
1090 auto nData = 0;
1091 for(const auto& d : data) {
1092 Interest interest(d.getFullName(), time::milliseconds(50));
1093 face->expressInterest(interest,
1094 [&d](const Interest& i, const Data& data) {
1095 BOOST_CHECK(data == d);
1096 },
1097 bind([] {
1098 BOOST_FAIL("Unexpected Nack");
1099 }),
1100 bind([] {
1101 BOOST_FAIL("Unexpected timeout");
1102 }));
1103 advanceClocks(time::milliseconds(1), 40);
1104 face->receive(interest);
Mickey Sweatt15dde2d2016-04-28 23:42:45 -07001105 manager.processEvents(time::milliseconds(-1));
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001106 // check that one piece of data is sent, and it is what was expected
1107 BOOST_CHECK_EQUAL(++nData, face->sentData.size());
1108 face->receive(face->sentData[nData - 1]);
Mickey Sweattafda1f12016-04-04 17:15:11 -07001109 }
Mickey Sweattafda1f12016-04-04 17:15:11 -07001110 fs::remove_all(".appdata");
1111}
1112
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001113BOOST_AUTO_TEST_SUITE_END()
1114
1115BOOST_FIXTURE_TEST_SUITE(CheckTorrentManagerUtilities, FaceFixture)
1116
1117BOOST_AUTO_TEST_CASE(CheckWriteDataComplete)
1118{
1119 const struct {
1120 const char *d_directoryPath;
1121 const char *d_initialSegmentName;
1122 size_t d_namesPerSegment;
1123 size_t d_subManifestSize;
1124 size_t d_dataPacketSize;
1125 } DATA [] = {
1126 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
1127 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=b88c054e87bcbb744726f7eaf79f95459b4fddce2caeb952f263a5ccbbfc9a7c", 128, 128, 128},
1128 };
1129 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
1130 for (int i = 0; i < NUM_DATA; ++i) {
1131 auto directoryPath = DATA[i].d_directoryPath;
1132 Name initialSegmentName = DATA[i].d_initialSegmentName;
1133 auto namesPerSegment = DATA[i].d_namesPerSegment;
1134 auto dataPacketSize = DATA[i].d_dataPacketSize;
1135 auto subManifestSize = DATA[i].d_subManifestSize;
1136
1137 vector<TorrentFile> torrentSegments;
1138 vector<FileManifest> manifests;
1139 // for each file, the data packets
1140 std::vector<vector<Data>> fileData;
1141 std::string filePath = "tests/testdata/temp";
1142 // get torrent files and manifests
1143 {
1144 auto temp = TorrentFile::generate(directoryPath,
1145 namesPerSegment,
1146 subManifestSize,
1147 dataPacketSize,
1148 false);
1149 torrentSegments = temp.first;
1150 auto temp1 = temp.second;
1151 for (const auto& ms : temp1) {
1152 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
1153 fileData.push_back(ms.second);
1154 }
1155 }
1156 // write the torrent segments and manifests to disk
1157 std::string dirPath = ".appdata/foo/";
1158 boost::filesystem::create_directories(dirPath);
1159 std::string torrentPath = dirPath + "torrent_files/";
1160 boost::filesystem::create_directories(torrentPath);
1161 auto fileNum = 0;
1162 for (const auto& t : torrentSegments) {
1163 fileNum++;
1164 auto filename = torrentPath + to_string(fileNum);
1165 io::save(t, filename);
1166 }
1167 auto manifestPath = dirPath + "manifests/";
1168 boost::filesystem::create_directory(manifestPath);
1169 for (const auto& m : manifests) {
1170 fs::path filename = manifestPath + m.file_name() + to_string(m.submanifest_number());
1171 boost::filesystem::create_directory(filename.parent_path());
1172 io::save(m, filename.string());
1173 }
1174 // Initialize manager
1175 TestTorrentManager manager(initialSegmentName,
1176 filePath,
1177 face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -07001178
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001179 manager.Initialize();
spirosmastorakis4ff8c872016-04-14 09:51:38 -07001180
1181 advanceClocks(time::milliseconds(1), 10);
1182 manager.sendRoutablePrefixResponse();
1183
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001184 // check that initially there is no data on disk
1185 for (auto m : manager.fileManifests()) {
1186 auto fileState = manager.fileState(m.getFullName());
1187 BOOST_CHECK(fileState.empty());
1188 }
1189 // write all data to disk (for each file manifest)
1190 auto manifest_it = manifests.begin();
1191 for (auto& data : fileData) {
1192 for (auto& d : data) {
1193 BOOST_CHECK(manager.writeData(d));
1194 }
1195 // check that the state is updated appropriately
1196 auto fileState = manager.fileState(manifest_it->getFullName());
1197 for (auto s : fileState) {
1198 BOOST_CHECK(s);
1199 }
1200 ++manifest_it;
1201 }
1202 // get the file names (ascending)
1203 std::set<std::string> fileNames;
1204 for (auto i = fs::recursive_directory_iterator(filePath + "/foo");
1205 i != fs::recursive_directory_iterator();
1206 ++i) {
1207 fileNames.insert(i->path().string());
1208 }
1209 // verify file by file that the data packets are written correctly
1210 auto f_it = fileData.begin();
1211 for (auto f : fileNames) {
1212 // read file from disk
1213 std::vector<uint8_t> file_bytes;
1214 fs::ifstream is(f, fs::ifstream::binary | fs::ifstream::in);
1215 is >> std::noskipws;
1216 std::istream_iterator<uint8_t> start(is), end;
1217 file_bytes.insert(file_bytes.end(), start, end);
1218 std::vector<uint8_t> data_bytes;
1219 // get content from data packets
1220 for (const auto& d : *f_it) {
1221 auto content = d.getContent();
1222 data_bytes.insert(data_bytes.end(), content.value_begin(), content.value_end());
1223 }
1224 BOOST_CHECK(data_bytes == file_bytes);
1225 ++f_it;
1226 }
1227 fs::remove_all(filePath);
1228 fs::remove_all(".appdata");
1229 }
1230}
1231
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001232BOOST_AUTO_TEST_CASE(CheckWriteTorrentComplete)
1233{
1234 const struct {
1235 const char *d_directoryPath;
1236 const char *d_initialSegmentName;
1237 size_t d_namesPerSegment;
1238 size_t d_subManifestSize;
1239 size_t d_dataPacketSize;
1240 } DATA [] = {
1241 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
1242 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=96d900d6788465f9a7b00191581b004c910d74b3762d141ec0e82173731bc9f4", 1, 1, 1024},
1243 };
1244 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
1245 for (int i = 0; i < NUM_DATA; ++i) {
1246 auto directoryPath = DATA[i].d_directoryPath;
1247 Name initialSegmentName = DATA[i].d_initialSegmentName;
1248 auto namesPerSegment = DATA[i].d_namesPerSegment;
1249 auto dataPacketSize = DATA[i].d_dataPacketSize;
1250 auto subManifestSize = DATA[i].d_subManifestSize;
1251
1252 vector<TorrentFile> torrentSegments;
1253 std::string filePath = "tests/testdata/temp";
1254 // get torrent files
1255 {
1256 auto temp = TorrentFile::generate(directoryPath,
1257 namesPerSegment,
1258 subManifestSize,
1259 dataPacketSize,
1260 false);
1261 torrentSegments = temp.first;
1262 }
1263 // Initialize manager
1264 TestTorrentManager manager(initialSegmentName,
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001265 filePath,
1266 face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -07001267
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001268 manager.Initialize();
spirosmastorakis4ff8c872016-04-14 09:51:38 -07001269
1270 advanceClocks(time::milliseconds(1), 10);
1271 manager.sendRoutablePrefixResponse();
1272
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001273 std::string dirPath = ".appdata/foo/";
1274 std::string torrentPath = dirPath + "torrent_files/";
1275 BOOST_CHECK(manager.torrentSegments().empty());
1276 for (const auto& t : torrentSegments) {
1277 BOOST_CHECK(manager.writeTorrentSegment(t, torrentPath));
1278 }
1279 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
1280 // check that initializing a new manager also gets all the torrent torrentSegments
1281 TestTorrentManager manager2(initialSegmentName,
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001282 filePath,
1283 face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -07001284
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001285 manager2.Initialize();
spirosmastorakis4ff8c872016-04-14 09:51:38 -07001286
1287 advanceClocks(time::milliseconds(1), 10);
1288 manager2.sendRoutablePrefixResponse();
1289
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001290 BOOST_CHECK(manager2.torrentSegments() == torrentSegments);
1291
1292 // start anew
1293 fs::remove_all(torrentPath);
1294 fs::create_directories(torrentPath);
1295 manager.Initialize();
spirosmastorakis4ff8c872016-04-14 09:51:38 -07001296
1297 advanceClocks(time::milliseconds(1), 10);
1298 manager.sendRoutablePrefixResponse();
1299
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001300 BOOST_CHECK(manager.torrentSegments().empty());
1301
1302 // check that there is no dependence on the order of torrent segments
1303 // randomize the order of the torrent segments
1304 auto torrentSegmentsRandom = torrentSegments;
1305 std::random_shuffle(torrentSegmentsRandom.begin(), torrentSegmentsRandom.end());
1306 for (const auto& t : torrentSegmentsRandom) {
1307 BOOST_CHECK(manager.writeTorrentSegment(t, torrentPath));
1308 }
1309 BOOST_CHECK(manager.torrentSegments() == torrentSegments);
1310 fs::remove_all(".appdata");
1311 }
1312}
1313
1314BOOST_AUTO_TEST_CASE(CheckWriteManifestComplete)
1315{
1316 std::string dirPath = ".appdata/foo/";
1317 std::string torrentPath = dirPath + "torrent_files/";
1318 std::string manifestPath = dirPath + "manifests/";
1319
1320 const struct {
1321 const char *d_directoryPath;
1322 const char *d_initialSegmentName;
1323 size_t d_namesPerSegment;
1324 size_t d_subManifestSize;
1325 size_t d_dataPacketSize;
1326 } DATA [] = {
1327 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 1024, 1024, 1024},
1328 {"tests/testdata/foo", "/NTORRENT/foo/torrent-file/sha256digest=02c737fd4c6e7de4b4825b089f39700c2dfa8fd2bb2b91f09201e357c4463253", 128, 128, 1024},
1329 };
1330 enum { NUM_DATA = sizeof DATA / sizeof *DATA };
1331 for (int i = 0; i < NUM_DATA; ++i) {
1332 auto directoryPath = DATA[i].d_directoryPath;
1333 Name initialSegmentName = DATA[i].d_initialSegmentName;
1334 auto namesPerSegment = DATA[i].d_namesPerSegment;
1335 auto dataPacketSize = DATA[i].d_dataPacketSize;
1336 auto subManifestSize = DATA[i].d_subManifestSize;
1337
1338 vector<FileManifest> manifests;
1339 vector<TorrentFile> torrentSegments;
1340
1341 std::string filePath = "tests/testdata/temp";
1342 // get torrent files and manifests
1343 {
1344 auto temp = TorrentFile::generate(directoryPath,
1345 namesPerSegment,
1346 subManifestSize,
1347 dataPacketSize,
1348 false);
1349 torrentSegments = temp.first;
1350 auto temp1 = temp.second;
1351 for (const auto& ms : temp1) {
1352 manifests.insert(manifests.end(), ms.first.begin(), ms.first.end());
1353 }
1354 }
1355 TestTorrentManager manager(initialSegmentName,
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001356 filePath,
1357 face);
spirosmastorakis4ff8c872016-04-14 09:51:38 -07001358
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001359 manager.Initialize();
spirosmastorakis4ff8c872016-04-14 09:51:38 -07001360
1361 advanceClocks(time::milliseconds(1), 10);
1362 manager.sendRoutablePrefixResponse();
1363
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001364 for (const auto& t : torrentSegments) {
1365 manager.writeTorrentSegment(t, torrentPath);
1366 }
1367
1368 BOOST_CHECK(manager.fileManifests().empty());
1369 for (const auto& m : manifests) {
1370 BOOST_CHECK(manager.writeFileManifest(m, manifestPath));
1371 }
1372 BOOST_CHECK(manager.fileManifests() == manifests);
1373
1374 TestTorrentManager manager2(initialSegmentName,
Mickey Sweatte908a5c2016-04-08 14:10:45 -07001375 filePath,
1376 face);
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001377
1378 manager2.Initialize();
spirosmastorakis4ff8c872016-04-14 09:51:38 -07001379
1380 advanceClocks(time::milliseconds(1), 10);
1381 manager2.sendRoutablePrefixResponse();
1382
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001383 BOOST_CHECK(manager2.fileManifests() == manifests);
1384
1385 // start anew
1386 fs::remove_all(manifestPath);
1387 fs::create_directories(manifestPath);
1388 manager.Initialize();
spirosmastorakis4ff8c872016-04-14 09:51:38 -07001389
1390 advanceClocks(time::milliseconds(1), 10);
1391 manager.sendRoutablePrefixResponse();
1392
Mickey Sweatt599bfef2016-04-05 19:11:20 -07001393 BOOST_CHECK(manager.fileManifests().empty());
1394
1395 // check that there is no dependence on the order of torrent segments
1396 // randomize the order of the torrent segments
1397 auto fileManifestsRandom = manifests;
1398 std::random_shuffle(fileManifestsRandom.begin(), fileManifestsRandom.end());
1399 for (const auto& m : fileManifestsRandom) {
1400 BOOST_CHECK(manager.writeFileManifest(m, manifestPath));
1401 }
1402 BOOST_CHECK(manager2.fileManifests() == manifests);
1403 fs::remove_all(".appdata");
1404 }
1405}
1406
spirosmastorakisa46eee42016-04-05 14:24:45 -07001407BOOST_AUTO_TEST_SUITE_END()
Mickey Sweattafda1f12016-04-04 17:15:11 -07001408
Mickey Sweatt527b0492016-03-02 11:07:48 -08001409} // namespace tests
1410} // namespace nTorrent
spirosmastorakisa46eee42016-04-05 14:24:45 -07001411} // namespace ndn