util: augment SegmentFetcher with congestion control
refs #4364
Change-Id: Ibfebc1f173382d1faf88e0d3d707b8ab2dae5e43
diff --git a/tests/unit-tests/util/segment-fetcher.t.cpp b/tests/unit-tests/util/segment-fetcher.t.cpp
index d8f2bf5..c804f70 100644
--- a/tests/unit-tests/util/segment-fetcher.t.cpp
+++ b/tests/unit-tests/util/segment-fetcher.t.cpp
@@ -30,15 +30,14 @@
#include "make-interest-data.hpp"
#include "../identity-management-time-fixture.hpp"
+#include <set>
+
namespace ndn {
namespace util {
namespace tests {
using namespace ndn::tests;
-BOOST_AUTO_TEST_SUITE(Util)
-BOOST_AUTO_TEST_SUITE(TestSegmentFetcher)
-
class Fixture : public IdentityManagementTimeFixture
{
public:
@@ -69,11 +68,11 @@
}
void
- onComplete(const ConstBufferPtr& data)
+ onComplete(ConstBufferPtr data)
{
++nCompletions;
dataSize = data->size();
- dataString = std::string(data->get<char>());
+ dataBuf = data;
}
void
@@ -92,22 +91,88 @@
fetcher->onError.connect(bind(&Fixture::onError, this, _1));
}
+ void
+ onInterest(const Interest& interest)
+ {
+ if (interest.getName().get(-1).isSegment()) {
+ if (segmentsToDropOrNack.size() > 0 &&
+ interest.getName().get(-1).toSegment() == segmentsToDropOrNack.front()) {
+ segmentsToDropOrNack.pop();
+ if (sendNackInsteadOfDropping) {
+ lp::Nack nack = makeNack(interest, nackReason);
+ face.receive(nack);
+ }
+ return;
+ }
+
+ auto data = makeDataSegment("/hello/world/version0",
+ interest.getName().get(-1).toSegment(),
+ interest.getName().get(-1).toSegment() == nSegments - 1);
+ face.receive(*data);
+
+ uniqSegmentsSent.insert(interest.getName().get(-1).toSegment());
+ if (uniqSegmentsSent.size() == nSegments) {
+ io.stop();
+ }
+ }
+ else {
+ if (segmentsToDropOrNack.size() > 0 &&
+ segmentsToDropOrNack.front() == 0) {
+ segmentsToDropOrNack.pop();
+ if (sendNackInsteadOfDropping) {
+ lp::Nack nack = makeNack(interest, nackReason);
+ face.receive(nack);
+ }
+ return;
+ }
+
+ auto data = makeDataSegment("/hello/world/version0", defaultSegmentToSend, nSegments == 1);
+ face.receive(*data);
+ uniqSegmentsSent.insert(defaultSegmentToSend);
+ }
+ }
+
public:
DummyClientFace face;
+ std::set<uint64_t> uniqSegmentsSent;
int nErrors = 0;
uint32_t lastError = 0;
int nCompletions = 0;
size_t dataSize = 0;
- std::string dataString;
+ ConstBufferPtr dataBuf;
+
+ // number of segments in fetched object
+ uint64_t nSegments = 0;
+ std::queue<uint64_t> segmentsToDropOrNack;
+ bool sendNackInsteadOfDropping = false;
+ lp::NackReason nackReason = lp::NackReason::NONE;
+ // segment that is sent in response to an Interest w/o a segment component in its name
+ uint64_t defaultSegmentToSend = 0;
};
-BOOST_FIXTURE_TEST_CASE(Timeout, Fixture)
+BOOST_AUTO_TEST_SUITE(Util)
+BOOST_FIXTURE_TEST_SUITE(TestSegmentFetcher, Fixture)
+
+BOOST_AUTO_TEST_CASE(InvalidOptions)
+{
+ SegmentFetcher::Options options;
+ options.mdCoef = 1.5;
+ DummyValidator acceptValidator;
+ BOOST_CHECK_THROW(SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options),
+ std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_CASE(ExceedMaxTimeout)
{
DummyValidator acceptValidator;
- shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world", 100_ms),
- acceptValidator);
+ size_t nAfterSegmentTimedOut = 0;
+ SegmentFetcher::Options options;
+ options.maxTimeout = 100_ms;
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
+ acceptValidator, options);
connectSignals(fetcher);
+ fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
advanceClocks(1_ms);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
@@ -121,46 +186,338 @@
BOOST_CHECK_EQUAL(nErrors, 0);
BOOST_CHECK_EQUAL(nCompletions, 0);
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
+ BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
advanceClocks(1_ms, 2);
BOOST_CHECK_EQUAL(nErrors, 1);
BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::INTEREST_TIMEOUT));
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
+ BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 1);
}
-BOOST_FIXTURE_TEST_CASE(Basic, Fixture)
+BOOST_AUTO_TEST_CASE(BasicSingleSegment)
{
DummyValidator acceptValidator;
size_t nAfterSegmentReceived = 0;
size_t nAfterSegmentValidated = 0;
- shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world", 1000_s),
+ size_t nAfterSegmentNacked = 0;
+ size_t nAfterSegmentTimedOut = 0;
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
acceptValidator);
connectSignals(fetcher);
fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
+ fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
+ fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
advanceClocks(10_ms);
- for (uint64_t i = 0; i < 400; i++) {
- advanceClocks(10_ms);
- face.receive(*makeDataSegment("/hello/world/version0", i, false));
- }
- advanceClocks(10_ms);
- face.receive(*makeDataSegment("/hello/world/version0", 400, true));
+ face.receive(*makeDataSegment("/hello/world/version0", 0, true));
advanceClocks(10_ms);
BOOST_CHECK_EQUAL(nErrors, 0);
BOOST_CHECK_EQUAL(nCompletions, 1);
- BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
- BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
+ BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
+ BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
+ BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
+ BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
}
-BOOST_FIXTURE_TEST_CASE(MissingSegmentNum, Fixture)
+BOOST_AUTO_TEST_CASE(ConstantCwnd)
+{
+ SegmentFetcher::Options options;
+ options.useConstantCwnd = true;
+ DummyValidator acceptValidator;
+ size_t nAfterSegmentReceived = 0;
+ size_t nAfterSegmentValidated = 0;
+ size_t nAfterSegmentNacked = 0;
+ size_t nAfterSegmentTimedOut = 0;
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
+ acceptValidator, options);
+ connectSignals(fetcher);
+ fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
+ fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
+ fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
+ fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
+
+ advanceClocks(10_ms);
+
+ BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
+
+ face.receive(*makeDataSegment("/hello/world/version0", 0, false));
+
+ advanceClocks(10_ms);
+
+ BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
+ BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 2);
+ BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 1);
+ face.receive(*makeDataSegment("/hello/world/version0", 1, false));
+
+ advanceClocks(10_ms);
+
+ BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
+ BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 2);
+ face.receive(*makeDataSegment("/hello/world/version0", 2, false));
+
+ advanceClocks(10_ms);
+
+ BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 4);
+ BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 3);
+ face.receive(*makeDataSegment("/hello/world/version0", 3, false));
+
+ advanceClocks(10_ms);
+
+ BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
+ BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 4);
+ nackLastInterest(lp::NackReason::CONGESTION);
+
+ advanceClocks(10_ms);
+
+ BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
+ BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 4);
+ face.receive(*makeDataSegment("/hello/world/version0", 4, true));
+
+ advanceClocks(10_ms);
+
+ BOOST_CHECK_EQUAL(nErrors, 0);
+ BOOST_CHECK_EQUAL(nCompletions, 1);
+ BOOST_CHECK_EQUAL(nAfterSegmentReceived, 5);
+ BOOST_CHECK_EQUAL(nAfterSegmentValidated, 5);
+ BOOST_CHECK_EQUAL(nAfterSegmentNacked, 1);
+ BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
+}
+
+BOOST_AUTO_TEST_CASE(BasicMultipleSegments)
{
DummyValidator acceptValidator;
- shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world", 1000_s),
+ size_t nAfterSegmentReceived = 0;
+ size_t nAfterSegmentValidated = 0;
+ size_t nAfterSegmentNacked = 0;
+ size_t nAfterSegmentTimedOut = 0;
+ nSegments = 401;
+ sendNackInsteadOfDropping = false;
+ face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
+
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
+ acceptValidator);
+ connectSignals(fetcher);
+ fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
+ fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
+ fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
+ fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
+
+ face.processEvents(1_s);
+
+ BOOST_CHECK_EQUAL(nErrors, 0);
+ BOOST_CHECK_EQUAL(nCompletions, 1);
+ BOOST_CHECK_EQUAL(dataSize, 14 * 401);
+ BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
+ BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
+ BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
+ BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
+}
+
+BOOST_AUTO_TEST_CASE(FirstSegmentNotZero)
+{
+ DummyValidator acceptValidator;
+ size_t nAfterSegmentReceived = 0;
+ size_t nAfterSegmentValidated = 0;
+ size_t nAfterSegmentNacked = 0;
+ size_t nAfterSegmentTimedOut = 0;
+ nSegments = 401;
+ sendNackInsteadOfDropping = false;
+ defaultSegmentToSend = 47;
+ face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
+
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
+ acceptValidator);
+ connectSignals(fetcher);
+ fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
+ fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
+ fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
+ fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
+
+ face.processEvents(1_s);
+
+ BOOST_CHECK_EQUAL(nErrors, 0);
+ BOOST_CHECK_EQUAL(nCompletions, 1);
+ BOOST_CHECK_EQUAL(dataSize, 14 * 401);
+ BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
+ BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
+ BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
+ BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
+}
+
+BOOST_AUTO_TEST_CASE(WindowSize)
+{
+ DummyValidator acceptValidator;
+ size_t nAfterSegmentReceived = 0;
+ size_t nAfterSegmentValidated = 0;
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
+ acceptValidator);
+ connectSignals(fetcher);
+ fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
+ fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
+
+ advanceClocks(10_ms); // T+10ms
+
+ BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
+ BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
+ BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
+ BOOST_CHECK_EQUAL(fetcher->m_ssthresh, std::numeric_limits<double>::max());
+ BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_highInterest, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_nReceived, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 0);
+ BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), 1);
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
+
+ double oldCwnd = fetcher->m_cwnd;
+ double oldSsthresh = fetcher->m_ssthresh;
+ uint64_t oldNextSegmentNum = fetcher->m_nextSegmentNum;
+
+ face.receive(*makeDataSegment("/hello/world/version0", 0, false));
+
+ advanceClocks(10_ms); //T+20ms
+
+ BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
+ BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
+ BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
+ // +2 below because m_nextSegmentNum will be incremented in the receive callback if segment 0 is
+ // the first received
+ BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 2);
+ BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
+ BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd + fetcher->m_options.aiStep);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 14);
+ BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
+ BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 1);
+ BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 1 + fetcher->m_cwnd);
+
+ oldCwnd = fetcher->m_cwnd;
+ oldNextSegmentNum = fetcher->m_nextSegmentNum;
+
+ face.receive(*makeDataSegment("/hello/world/version0", 2, false));
+
+ advanceClocks(10_ms); //T+30ms
+
+ BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
+ BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
+ BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
+ BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
+ BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
+ BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 28);
+ BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
+ BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
+ BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 2);
+ BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 2 + fetcher->m_cwnd);
+
+ oldCwnd = fetcher->m_cwnd;
+ oldNextSegmentNum = fetcher->m_nextSegmentNum;
+
+ face.receive(*makeDataSegment("/hello/world/version0", 1, false));
+
+ advanceClocks(10_ms); //T+40ms
+
+ BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
+ BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
+ BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
+ BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
+ BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
+ BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
+ BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
+ BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
+ BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
+ BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 3 + fetcher->m_cwnd);
+
+ oldCwnd = fetcher->m_cwnd;
+ oldSsthresh = fetcher->m_ssthresh;
+ oldNextSegmentNum = fetcher->m_nextSegmentNum;
+ size_t oldSentInterestsSize = face.sentInterests.size();
+
+ nackLastInterest(lp::NackReason::CONGESTION); //T+50ms
+
+ BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 20_ms);
+ BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
+ BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
+ BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
+ BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
+ BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
+ BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
+ BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
+ BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
+ BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
+ // The Nacked segment will remain in pendingSegments, so the size of the structure doesn't change
+ BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
+
+ advanceClocks(10_ms); //T+60ms
+
+ BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 30_ms);
+ BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
+ BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
+ BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
+ BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
+ BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
+ BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
+ BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
+ BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
+ BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
+ BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
+ BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
+ BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
+
+ // Properly end test case
+ lp::Nack nack = makeNack(face.sentInterests[face.sentInterests.size() - 2], lp::NackReason::NO_ROUTE);
+ face.receive(nack);
+ advanceClocks(10_ms); //T+70ms
+
+ BOOST_CHECK_EQUAL(nErrors, 1);
+ BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::NACK_ERROR));
+ BOOST_CHECK_EQUAL(nCompletions, 0);
+}
+
+BOOST_AUTO_TEST_CASE(MissingSegmentNum)
+{
+ DummyValidator acceptValidator;
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
acceptValidator);
connectSignals(fetcher);
@@ -178,107 +535,165 @@
BOOST_CHECK_EQUAL(nCompletions, 0);
}
-BOOST_FIXTURE_TEST_CASE(DuplicateNack, Fixture)
+BOOST_AUTO_TEST_CASE(MoreSegmentsThanNSegments)
{
DummyValidator acceptValidator;
- shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world", 1000_s),
+ size_t nAfterSegmentReceived = 0;
+ size_t nAfterSegmentValidated = 0;
+ size_t nAfterSegmentNacked = 0;
+ size_t nAfterSegmentTimedOut = 0;
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
acceptValidator);
connectSignals(fetcher);
+ fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
+ fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
+ fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
+ fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
+
advanceClocks(10_ms);
- // receive nack for the original interest
- nackLastInterest(lp::NackReason::DUPLICATE);
-
- // receive nack due to Duplication for the reexpressed interests
- for (uint32_t i = 1; i <= SegmentFetcher::MAX_INTEREST_REEXPRESS; ++i) {
- nackLastInterest(lp::NackReason::DUPLICATE);
- }
-
- BOOST_CHECK_EQUAL(face.sentInterests.size(), (SegmentFetcher::MAX_INTEREST_REEXPRESS + 1));
- BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::NACK_ERROR));
-}
-
-BOOST_FIXTURE_TEST_CASE(CongestionNack, Fixture)
-{
- DummyValidator acceptValidator;
- shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world", 1000_s),
- acceptValidator);
- connectSignals(fetcher);
+ face.receive(*makeDataSegment("/hello/world/version0", 0, false));
advanceClocks(10_ms);
- // receive nack for the original interest
- nackLastInterest(lp::NackReason::CONGESTION);
+ BOOST_CHECK_EQUAL(nErrors, 0);
+ BOOST_CHECK_EQUAL(nCompletions, 0);
- // receive nack due to Congestion for the reexpressed interests
- for (uint32_t i = 1; i <= SegmentFetcher::MAX_INTEREST_REEXPRESS; ++i) {
- nackLastInterest(lp::NackReason::CONGESTION);
- }
-
- BOOST_CHECK_EQUAL(face.sentInterests.size(), (SegmentFetcher::MAX_INTEREST_REEXPRESS + 1));
- BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::NACK_ERROR));
-}
-
-BOOST_FIXTURE_TEST_CASE(SegmentZero, Fixture)
-{
- int nNacks = 2;
-
- ndn::Name interestName("ndn:/A");
- DummyValidator acceptValidator;
- shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest(interestName),
- acceptValidator);
- connectSignals(fetcher);
-
- advanceClocks(1000_ms);
-
- for (uint64_t segmentNo = 0; segmentNo <= 3; segmentNo++) {
- if (segmentNo == 1) {
- while (nNacks--) {
- nackLastInterest(lp::NackReason::CONGESTION);
- advanceClocks(10_ms);
- }
- }
-
- auto data = makeDataSegment(interestName, segmentNo, segmentNo == 3);
- face.receive(*data);
- advanceClocks(10_ms);
- }
-
- // Total number of sent interests should be 6: one interest for segment zero and segment one each,
- // two re-expressed interests for segment one after getting nack twice, and two interests for
- // segment two and three
- BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 6);
-
- BOOST_CHECK_EQUAL(face.sentInterests[0].getName(), ndn::Name("ndn:/A"));
- BOOST_CHECK_EQUAL(face.sentInterests[1].getName(), ndn::Name("ndn:/A/%00%01"));
- BOOST_CHECK_EQUAL(face.sentInterests[2].getName(), ndn::Name("ndn:/A/%00%01"));
- BOOST_CHECK_EQUAL(face.sentInterests[3].getName(), ndn::Name("ndn:/A/%00%01"));
- BOOST_CHECK_EQUAL(face.sentInterests[4].getName(), ndn::Name("ndn:/A/%00%02"));
- BOOST_CHECK_EQUAL(face.sentInterests[5].getName(), ndn::Name("ndn:/A/%00%03"));
-}
-
-BOOST_FIXTURE_TEST_CASE(SingleSegment, Fixture)
-{
- DummyValidator acceptValidator;
- shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("ndn:/", 1000_s),
- acceptValidator);
- connectSignals(fetcher);
+ face.receive(*makeDataSegment("/hello/world/version0", 1, false));
advanceClocks(10_ms);
- nackLastInterest(lp::NackReason::DUPLICATE);
- face.receive(*makeDataSegment("/hello/world", 0, true));
- BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 2);
- BOOST_CHECK_EQUAL(face.sentInterests[0].getName(), ndn::Name("ndn:/"));
- BOOST_CHECK_EQUAL(face.sentInterests[1].getName(), ndn::Name("ndn:/"));
- BOOST_REQUIRE_EQUAL(nCompletions, 1);
+ BOOST_CHECK_EQUAL(nErrors, 0);
+ BOOST_CHECK_EQUAL(nCompletions, 0);
+
+ face.receive(*makeDataSegment("/hello/world/version0", 2, false));
+ advanceClocks(10_ms);
+
+ BOOST_CHECK_EQUAL(nErrors, 0);
+ BOOST_CHECK_EQUAL(nCompletions, 0);
+
+ face.receive(*makeDataSegment("/hello/world/version0", 3, false));
+ advanceClocks(10_ms);
+
+ BOOST_CHECK_EQUAL(nErrors, 0);
+ BOOST_CHECK_EQUAL(nCompletions, 0);
+
+ auto data4 = makeDataSegment("/hello/world/version0", 4, false);
+ data4->setFinalBlock(name::Component::fromSegment(2));
+ face.receive(*data4);
+ advanceClocks(10_ms);
+
+ BOOST_CHECK_EQUAL(nErrors, 0);
+ BOOST_CHECK_EQUAL(nCompletions, 1);
+ BOOST_CHECK_EQUAL(dataSize, 14 * 3);
+ BOOST_CHECK_EQUAL(nAfterSegmentReceived, 5);
+ BOOST_CHECK_EQUAL(nAfterSegmentValidated, 5);
+ BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
+ BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
}
-BOOST_FIXTURE_TEST_CASE(ValidationFailure, Fixture)
+BOOST_AUTO_TEST_CASE(DuplicateNack)
+{
+ DummyValidator acceptValidator;
+ size_t nAfterSegmentReceived = 0;
+ size_t nAfterSegmentValidated = 0;
+ size_t nAfterSegmentNacked = 0;
+ size_t nAfterSegmentTimedOut = 0;
+ nSegments = 401;
+ segmentsToDropOrNack.push(0);
+ segmentsToDropOrNack.push(200);
+ sendNackInsteadOfDropping = true;
+ nackReason = lp::NackReason::DUPLICATE;
+ face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
+
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
+ acceptValidator);
+ connectSignals(fetcher);
+ fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
+ fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
+ fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
+ fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
+
+ face.processEvents(1_s);
+
+ BOOST_CHECK_EQUAL(nErrors, 0);
+ BOOST_CHECK_EQUAL(nCompletions, 1);
+ BOOST_CHECK_EQUAL(dataSize, 14 * 401);
+ BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
+ BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
+ BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
+ BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
+}
+
+BOOST_AUTO_TEST_CASE(CongestionNack)
+{
+ DummyValidator acceptValidator;
+ size_t nAfterSegmentReceived = 0;
+ size_t nAfterSegmentValidated = 0;
+ size_t nAfterSegmentNacked = 0;
+ size_t nAfterSegmentTimedOut = 0;
+ nSegments = 401;
+ segmentsToDropOrNack.push(0);
+ segmentsToDropOrNack.push(200);
+ sendNackInsteadOfDropping = true;
+ nackReason = lp::NackReason::CONGESTION;
+ face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
+
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
+ acceptValidator);
+ connectSignals(fetcher);
+ fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
+ fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
+ fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
+ fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
+
+ face.processEvents(1_s);
+
+ BOOST_CHECK_EQUAL(nErrors, 0);
+ BOOST_CHECK_EQUAL(nCompletions, 1);
+ BOOST_CHECK_EQUAL(dataSize, 14 * 401);
+ BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
+ BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
+ BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
+ BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
+}
+
+BOOST_AUTO_TEST_CASE(OtherNackReason)
+{
+ DummyValidator acceptValidator;
+ size_t nAfterSegmentReceived = 0;
+ size_t nAfterSegmentValidated = 0;
+ size_t nAfterSegmentNacked = 0;
+ size_t nAfterSegmentTimedOut = 0;
+ segmentsToDropOrNack.push(0);
+ sendNackInsteadOfDropping = true;
+ nackReason = lp::NackReason::NO_ROUTE;
+ face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
+
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
+ acceptValidator);
+ connectSignals(fetcher);
+ fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
+ fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
+ fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
+ fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
+
+ face.processEvents(1_s);
+
+ BOOST_CHECK_EQUAL(nErrors, 1);
+ BOOST_CHECK_EQUAL(nCompletions, 0);
+ BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
+ BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
+ BOOST_CHECK_EQUAL(nAfterSegmentNacked, 1);
+ BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
+}
+
+BOOST_AUTO_TEST_CASE(ValidationFailure)
{
DummyValidator validator;
validator.getPolicy().setResultCallback([] (const Name& name) {
return name.at(-1).toSegment() % 2 == 0;
});
- shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world", 1000_s),
+ shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
validator);
connectSignals(fetcher);
@@ -297,14 +712,19 @@
advanceClocks(10_ms, 10);
+ BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
+
face.receive(*data1);
advanceClocks(10_ms, 10);
+ BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
+
face.receive(*data2);
advanceClocks(10_ms, 10);
+ BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 200_ms);
BOOST_CHECK_EQUAL(nRecvSegments, 2);
BOOST_CHECK_EQUAL(nValidatedSegments, 1);
BOOST_CHECK_EQUAL(nErrors, 1);
@@ -312,7 +732,7 @@
// Tests deprecated `fetch` API that uses callbacks instead of signals. This test case will be
// removed when this API is removed.
-BOOST_FIXTURE_TEST_CASE(DeprecatedFetch, Fixture)
+BOOST_AUTO_TEST_CASE(DeprecatedFetch)
{
DummyValidator acceptValidator;
SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
@@ -330,11 +750,11 @@
BOOST_CHECK_EQUAL(dataSize, 14);
- const uint8_t buffer[] = "Hello, world!";
- std::string bufferString(reinterpret_cast<const char*>(buffer));
+ const uint8_t buffer[] = "Hello, world!\0";
+ BOOST_REQUIRE_EQUAL(dataBuf->size(), 14);
+ BOOST_CHECK_EQUAL_COLLECTIONS(dataBuf->begin(), dataBuf->end(), buffer, buffer + 14);
- BOOST_CHECK_EQUAL(dataString, bufferString);
-
+ BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
@@ -342,11 +762,65 @@
BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
BOOST_CHECK_EQUAL(interest.getChildSelector(), 1);
+ BOOST_CHECK_EQUAL(interest.getInterestLifetime(), 1000_s);
+}
+
+// Tests deprecated `fetch` API that uses callbacks instead of signals. This test case will be
+// removed when this API is removed.
+BOOST_AUTO_TEST_CASE(DeprecatedFetchMultipleSegments)
+{
+ DummyValidator acceptValidator;
+ SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
+ acceptValidator,
+ bind(&Fixture::onComplete, this, _1),
+ bind(&Fixture::onError, this, _1));
+
+ advanceClocks(10_ms);
+
+ face.receive(*makeDataSegment("/hello/world/version0", 0, false));
+ advanceClocks(10_ms);
+
+ face.receive(*makeDataSegment("/hello/world/version0", 1, false));
+ advanceClocks(10_ms);
+
+ face.receive(*makeDataSegment("/hello/world/version0", 2, true));
+ advanceClocks(10_ms);
+
+ BOOST_CHECK_EQUAL(nErrors, 0);
+ BOOST_CHECK_EQUAL(nCompletions, 1);
+
+ BOOST_CHECK_EQUAL(dataSize, 14 * 3);
+
+ const uint8_t buffer[] = "Hello, world!\0Hello, world!\0Hello, world!\0";
+ BOOST_REQUIRE_EQUAL(dataBuf->size(), 14 * 3);
+ BOOST_CHECK_EQUAL_COLLECTIONS(dataBuf->begin(), dataBuf->end(), buffer, buffer + (14 * 3));
+
+ BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
+ BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 3);
+ BOOST_CHECK_EQUAL(face.sentData.size(), 0);
+
+ const Interest& interest0 = face.sentInterests[0];
+ BOOST_CHECK_EQUAL(interest0.getName(), "/hello/world");
+ BOOST_CHECK_EQUAL(interest0.getMustBeFresh(), true);
+ BOOST_CHECK_EQUAL(interest0.getChildSelector(), 1);
+ BOOST_CHECK_EQUAL(interest0.getInterestLifetime(), 1000_s);
+
+ const Interest& interest1 = face.sentInterests[1];
+ BOOST_CHECK_EQUAL(interest1.getName(), "/hello/world/version0/%00%01");
+ BOOST_CHECK_EQUAL(interest1.getMustBeFresh(), false);
+ BOOST_CHECK_EQUAL(interest1.getChildSelector(), 0);
+ BOOST_CHECK_EQUAL(interest1.getInterestLifetime(), 1000_s);
+
+ const Interest& interest2 = face.sentInterests[2];
+ BOOST_CHECK_EQUAL(interest2.getName(), "/hello/world/version0/%00%02");
+ BOOST_CHECK_EQUAL(interest2.getMustBeFresh(), false);
+ BOOST_CHECK_EQUAL(interest2.getChildSelector(), 0);
+ BOOST_CHECK_EQUAL(interest2.getInterestLifetime(), 1000_s);
}
// Tests deprecated `fetch` API that uses callbacks instead of signals (with an accepting shared_ptr
// Validator). This test case will be removed when this API is removed.
-BOOST_FIXTURE_TEST_CASE(DeprecatedFetchSharedPtrComplete, Fixture)
+BOOST_AUTO_TEST_CASE(DeprecatedFetchSharedPtrComplete)
{
auto acceptValidator = make_shared<DummyValidator>(true);
SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
@@ -372,11 +846,11 @@
BOOST_CHECK_EQUAL(dataSize, 14);
- const uint8_t buffer[] = "Hello, world!";
- std::string bufferString(reinterpret_cast<const char*>(buffer));
+ const uint8_t buffer[] = "Hello, world!\0";
+ BOOST_REQUIRE_EQUAL(dataBuf->size(), 14);
+ BOOST_CHECK_EQUAL_COLLECTIONS(dataBuf->begin(), dataBuf->end(), buffer, buffer + 14);
- BOOST_CHECK_EQUAL(dataString, bufferString);
-
+ BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
@@ -384,11 +858,12 @@
BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
BOOST_CHECK_EQUAL(interest.getChildSelector(), 1);
+ BOOST_CHECK_EQUAL(interest.getInterestLifetime(), 1000_s);
}
// Tests deprecated `fetch` API that uses callbacks instead of signals (with a rejecting shared_ptr
// Validator). This test case will be removed when this API is removed.
-BOOST_FIXTURE_TEST_CASE(DeprecatedFetchSharedPtrError, Fixture)
+BOOST_AUTO_TEST_CASE(DeprecatedFetchSharedPtrError)
{
auto acceptValidator = make_shared<DummyValidator>(false);
SegmentFetcher::fetch(face, Interest("/hello/world", 1000_s),
@@ -412,6 +887,7 @@
BOOST_CHECK_EQUAL(nErrors, 1);
BOOST_CHECK_EQUAL(nCompletions, 0);
+ BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
@@ -419,6 +895,7 @@
BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
BOOST_CHECK_EQUAL(interest.getChildSelector(), 1);
+ BOOST_CHECK_EQUAL(interest.getInterestLifetime(), 1000_s);
}
BOOST_AUTO_TEST_SUITE_END() // TestSegmentFetcher