blob: 32304fb7fbe6d71d722132c4211e09f42432d794 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2017, Regents of the University of California.
*
* This file is part of ChronoShare, a decentralized file sharing application over NDN.
*
* ChronoShare is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* ChronoShare is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received copies of the GNU General Public License along with
* ChronoShare, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ChronoShare authors and contributors.
*/
#include "fetch-manager.hpp"
#include "test-common.hpp"
#include <ndn-cxx/util/dummy-client-face.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/range/adaptor/transformed.hpp>
namespace ndn {
namespace chronoshare {
namespace tests {
_LOG_INIT(Test.FetchManager);
BOOST_AUTO_TEST_SUITE(TestFetchManager)
class FetcherTestData : public IdentityManagementTimeFixture
{
public:
FetcherTestData()
: face(m_io, m_keyChain, {true, true})
, m_done(false)
, m_failed(false)
, m_hasMissing(true)
{
}
void
onData(const ndn::Name& deviceName, const ndn::Name& basename, uint64_t seqno,
ndn::shared_ptr<ndn::Data> data)
{
_LOG_TRACE("onData: " << seqno << data->getName());
recvData.insert(seqno);
differentNames.insert(basename);
Name name = basename;
name.appendNumber(seqno);
segmentNames.insert(name);
Block block = data->getContent();
std::string recvNo(reinterpret_cast<const char*>(block.value()), block.value_size());
recvContent.insert(boost::lexical_cast<uint32_t>(recvNo));
}
void
finish(const ndn::Name& deviceName, const ndn::Name& baseName)
{
}
void
onComplete(Fetcher& fetcher)
{
m_done = true;
}
void
onFail(Fetcher& fetcher)
{
m_failed = true;
}
public:
util::DummyClientFace face;
std::set<uint32_t> recvData;
std::set<uint32_t> recvContent;
std::set<Name> differentNames;
std::set<Name> segmentNames;
bool m_done;
bool m_failed;
bool m_hasMissing;
};
BOOST_FIXTURE_TEST_CASE(TestFetcher, FetcherTestData)
{
Name baseName("/fetchtest");
Name deviceName("/device");
// publish seqnos: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, <gap 5>, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, <gap 1>, 26
// this will allow us to test our pipeline of 6
std::set<uint32_t> seqs = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /*<gap 10-14>,*/
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /*<gap 25>,*/ 26};
face.onSendInterest.connect([&, this] (const Interest& interest) {
uint32_t requestedSeqNo = interest.getName().at(-1).toNumber();
if (seqs.count(requestedSeqNo) > 0) {
auto data = make_shared<Data>();
Name name(baseName);
name.appendNumber(requestedSeqNo);
data->setName(name);
data->setFreshnessPeriod(time::seconds(300));
std::string content = to_string(requestedSeqNo);
data->setContent(reinterpret_cast<const uint8_t*>(content.data()), content.size());
m_keyChain.sign(*data);
m_io.post([data, this] { face.receive(*data); });
}
});
Fetcher fetcher(face, bind(&FetcherTestData::onData, this, _1, _2, _3, _4),
bind(&FetcherTestData::finish, this, _1, _2),
bind(&FetcherTestData::onComplete, this, _1),
bind(&FetcherTestData::onFail, this, _1), deviceName, Name("/fetchtest"), 0, 26,
time::seconds(5), Name());
BOOST_CHECK_EQUAL(fetcher.IsActive(), false);
fetcher.RestartPipeline();
BOOST_CHECK_EQUAL(fetcher.IsActive(), true);
this->advanceClocks(time::milliseconds(50), 1000);
BOOST_CHECK_EQUAL(m_failed, true);
BOOST_CHECK_EQUAL(differentNames.size(), 1);
BOOST_CHECK_EQUAL(segmentNames.size(), 20);
BOOST_CHECK_EQUAL(recvData.size(), 20);
BOOST_CHECK_EQUAL(recvContent.size(), 20);
BOOST_CHECK_EQUAL("0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24",
join(recvData | boost::adaptors::transformed([] (int i) { return std::to_string(i); }), ", "));
BOOST_CHECK_EQUAL_COLLECTIONS(recvData.begin(), recvData.end(), recvContent.begin(), recvContent.end());
BOOST_CHECK_EQUAL(fetcher.IsActive(), false);
fetcher.RestartPipeline();
BOOST_CHECK_EQUAL(fetcher.IsActive(), true);
this->advanceClocks(time::milliseconds(100), 100);
BOOST_CHECK_EQUAL(m_done, false);
BOOST_CHECK_EQUAL(m_failed, true);
BOOST_CHECK_EQUAL(fetcher.IsActive(), false);
std::set<uint32_t> missing = {10, 11, 12, 13, 14, 25};
seqs.insert(missing.begin(), missing.end());
m_failed = false;
fetcher.RestartPipeline();
BOOST_CHECK_EQUAL(fetcher.IsActive(), true);
this->advanceClocks(time::milliseconds(100), 100);
BOOST_CHECK_EQUAL(m_done, true);
BOOST_CHECK_EQUAL(m_failed, false);
BOOST_CHECK_EQUAL(segmentNames.size(), 27);
BOOST_CHECK_EQUAL(recvData.size(), 27);
BOOST_CHECK_EQUAL(recvContent.size(), 27);
BOOST_CHECK_EQUAL("0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26",
join(recvData | boost::adaptors::transformed([] (int i) { return std::to_string(i); }), ", "));
BOOST_CHECK_EQUAL_COLLECTIONS(recvData.begin(), recvData.end(), recvContent.begin(), recvContent.end());
// TODO add tests that other callbacks got called
}
BOOST_AUTO_TEST_SUITE_END()
} // namespace tests
} // namespace chronoshare
} // namespace ndn