util: SegmentFetcher don't restart from segment 0 upon Nack
Change-Id: I167186961a82a4349fab5b4431c26a3fdb904bb8
refs: #3554
diff --git a/src/util/segment-fetcher.cpp b/src/util/segment-fetcher.cpp
index a9c0418..70ad632 100644
--- a/src/util/segment-fetcher.cpp
+++ b/src/util/segment-fetcher.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2013-2015 Regents of the University of California.
+ * Copyright (c) 2013-2016 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -178,9 +178,17 @@
interest.refreshNonce();
BOOST_ASSERT(interest.hasNonce());
+ bool isSegmentZeroExpected = true;
+ if (!interest.getName().empty()) {
+ name::Component lastComponent = interest.getName().get(-1);
+ isSegmentZeroExpected = !lastComponent.isSegment();
+ }
+
m_face.expressInterest(interest,
- bind(&SegmentFetcher::afterSegmentReceived, this, _1, _2, true, self),
- bind(&SegmentFetcher::afterNackReceived, this, _1, _2, ++reExpressCount, self),
+ bind(&SegmentFetcher::afterSegmentReceived, this, _1, _2,
+ isSegmentZeroExpected, self),
+ bind(&SegmentFetcher::afterNackReceived, this, _1, _2,
+ ++reExpressCount, self),
bind(m_errorCallback, INTEREST_TIMEOUT, "Timeout"));
}
diff --git a/tests/unit-tests/util/segment-fetcher.t.cpp b/tests/unit-tests/util/segment-fetcher.t.cpp
index 4cccc80..7362439 100644
--- a/tests/unit-tests/util/segment-fetcher.t.cpp
+++ b/tests/unit-tests/util/segment-fetcher.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2013-2015 Regents of the University of California.
+ * Copyright (c) 2013-2016 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -357,7 +357,7 @@
BOOST_CHECK_EQUAL(nDatas, 1);
}
-BOOST_FIXTURE_TEST_CASE(SegmentFetcherDuplicateNack, Fixture)
+BOOST_FIXTURE_TEST_CASE(DuplicateNack, Fixture)
{
SegmentFetcher::fetch(face, Interest("/hello/world", time::seconds(1000)),
make_shared<ValidatorNull>(),
@@ -377,7 +377,7 @@
BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::NACK_ERROR));
}
-BOOST_FIXTURE_TEST_CASE(SegmentFetcherCongestionNack, Fixture)
+BOOST_FIXTURE_TEST_CASE(CongestionNack, Fixture)
{
SegmentFetcher::fetch(face, Interest("/hello/world", time::seconds(1000)),
make_shared<ValidatorNull>(),
@@ -397,6 +397,61 @@
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");
+ SegmentFetcher::fetch(face,
+ Interest(interestName),
+ make_shared<ValidatorNull>(),
+ bind(&Fixture::onComplete, this, _1),
+ bind(&Fixture::onError, this, _1));
+
+ advanceClocks(time::milliseconds(1), 1000);
+
+ for (uint64_t segmentNo = 0; segmentNo <= 3; segmentNo++) {
+ if (segmentNo == 1) {
+ while (nNacks--) {
+ nackLastInterest(lp::NackReason::CONGESTION);
+ advanceClocks(time::milliseconds(1), 10);
+ }
+ }
+
+ auto data = makeDataSegment(interestName, segmentNo, segmentNo == 3);
+ face.receive(*data);
+ advanceClocks(time::milliseconds(1), 10);
+ }
+
+ // 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(ZeroComponentName, Fixture)
+{
+ SegmentFetcher::fetch(face, Interest("ndn:/"),
+ make_shared<ValidatorNull>(),
+ bind(&Fixture::onComplete, this, _1),
+ bind(&Fixture::onError, this, _1));
+ advanceClocks(time::milliseconds(1), 10);
+ 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(nDatas, 1);
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace tests