catchunks: pass versioned name to onDiscoverySuccess signal

refs: #4556
Change-Id: I599bafcf70647bd806236f87f24d7a22f73a3505
diff --git a/tests/chunks/consumer.t.cpp b/tests/chunks/consumer.t.cpp
index ebedd61..f6d3e8a 100644
--- a/tests/chunks/consumer.t.cpp
+++ b/tests/chunks/consumer.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2016-2018, Regents of the University of California,
+ * Copyright (c) 2016-2019, Regents of the University of California,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University.
  *
@@ -157,7 +157,10 @@
   void
   handleData(const Interest& interest, const Data& data) final
   {
-    this->emitSignal(onDiscoverySuccess, data);
+    if (!data.getName().empty() && data.getName()[-1].isVersion())
+      this->emitSignal(onDiscoverySuccess, data.getName());
+    else
+      this->emitSignal(onDiscoveryFailure, "Invalid versioned name");
   }
 
 public:
@@ -210,7 +213,8 @@
   this->advanceClocks(io, time::nanoseconds(1));
   BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
 
-  auto data = makeData(prefix.appendSegment(0));
+  // this Data packet answers the discovery Interest, so it must end with a version number
+  auto data = makeData(prefix.appendVersion(0));
   face.receive(*data);
 
   this->advanceClocks(io, time::nanoseconds(1));
diff --git a/tests/chunks/discover-version-fixture.hpp b/tests/chunks/discover-version-fixture.hpp
index 8d49537..ed18235 100644
--- a/tests/chunks/discover-version-fixture.hpp
+++ b/tests/chunks/discover-version-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2016-2018, Regents of the University of California,
+ * Copyright (c) 2016-2019, Regents of the University of California,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University.
  *
@@ -80,12 +80,12 @@
   }
 
   virtual void
-  onSuccess(const Data& data)
+  onSuccess(const Name& versionedName)
   {
     isDiscoveryFinished = true;
 
-    if (data.getName()[name.size()].isVersion())
-      discoveredVersion = data.getName()[name.size()].toVersion();
+    BOOST_REQUIRE(!versionedName.empty() && versionedName[-1].isVersion());
+    discoveredVersion = versionedName[-1].toVersion();
   }
 
   virtual void
diff --git a/tests/chunks/pipeline-interests-aimd.t.cpp b/tests/chunks/pipeline-interests-aimd.t.cpp
index 1335d67..0e6341e 100644
--- a/tests/chunks/pipeline-interests-aimd.t.cpp
+++ b/tests/chunks/pipeline-interests-aimd.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2016-2018, Regents of the University of California,
+ * Copyright (c) 2016-2019, Regents of the University of California,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University.
  *
@@ -102,11 +102,11 @@
   BOOST_REQUIRE_CLOSE(aimdPipeline->m_cwnd, 1, MARGIN);
 
   double preCwnd = aimdPipeline->m_cwnd;
-  runWithData(*makeDataWithSegment(0));
+  run(name);
   advanceClocks(io, time::nanoseconds(1));
   BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
 
-  for (uint64_t i = 1; i < nDataSegments - 1; ++i) {
+  for (uint64_t i = 0; i < nDataSegments - 1; ++i) {
     face.receive(*makeDataWithSegment(i));
     advanceClocks(io, time::nanoseconds(1));
     BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd - preCwnd, 1, MARGIN);
@@ -118,22 +118,22 @@
 
 BOOST_AUTO_TEST_CASE(CongestionAvoidance)
 {
-  nDataSegments = 8;
+  nDataSegments = 7;
   aimdPipeline->m_ssthresh = 4.0;
   BOOST_REQUIRE_CLOSE(aimdPipeline->m_cwnd, 1, MARGIN);
 
   double preCwnd = aimdPipeline->m_cwnd;
-  runWithData(*makeDataWithSegment(0));
+  run(name);
   advanceClocks(io, time::nanoseconds(1));
   BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
 
-  for (uint64_t i = 1; i < aimdPipeline->m_ssthresh; ++i) { // slow start
+  for (uint64_t i = 0; i < aimdPipeline->m_ssthresh; ++i) { // slow start
     face.receive(*makeDataWithSegment(i));
     advanceClocks(io, time::nanoseconds(1));
     preCwnd = aimdPipeline->m_cwnd;
   }
 
-  BOOST_CHECK_CLOSE(preCwnd, aimdPipeline->m_ssthresh, MARGIN);
+  BOOST_CHECK_CLOSE(preCwnd, 4.25, MARGIN);
 
   for (uint64_t i = aimdPipeline->m_ssthresh; i < nDataSegments - 1; ++i) { // congestion avoidance
     face.receive(*makeDataWithSegment(i));
@@ -151,19 +151,19 @@
   aimdPipeline->m_ssthresh = 4.0;
   BOOST_REQUIRE_CLOSE(aimdPipeline->m_cwnd, 1, MARGIN);
 
-  runWithData(*makeDataWithSegment(0));
+  run(name);
   advanceClocks(io, time::nanoseconds(1));
   BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
 
-  // receive segment 1 and segment 2
-  for (uint64_t i = 1; i < 3; ++i) {
+  // receive segment 0, 1, and 2
+  for (uint64_t i = 0; i < 3; ++i) {
     face.receive(*makeDataWithSegment(i));
     advanceClocks(io, time::nanoseconds(1));
   }
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 3);
-  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 3, MARGIN);
-  BOOST_CHECK_EQUAL(face.sentInterests.size(), 5); // request for segment 5 has been sent
+  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 4, MARGIN);
+  BOOST_CHECK_EQUAL(face.sentInterests.size(), 7); // request for segment 7 has been sent
 
   advanceClocks(io, time::milliseconds(100));
 
@@ -176,14 +176,14 @@
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
-  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 4.25, MARGIN);
-  BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments - 1); // all the segment requests have been sent
+  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 4.5, MARGIN);
+  BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all the segment requests have been sent
 
   // timeout segment 3
   advanceClocks(io, time::milliseconds(150));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
-  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 2.125, MARGIN); // window size drop to 1/2 of previous size
+  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 2.25, MARGIN); // window size drop to 1/2 of previous size
   BOOST_CHECK_EQUAL(aimdPipeline->m_retxQueue.size(), 1);
 
   // receive segment 6, retransmit 3
@@ -191,7 +191,7 @@
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
-  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 2.625, MARGIN); // congestion avoidance
+  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 2.75, MARGIN); // congestion avoidance
   BOOST_CHECK_EQUAL(aimdPipeline->m_retxQueue.size(), 0);
   BOOST_CHECK_EQUAL(aimdPipeline->m_retxCount[3], 1);
 }
@@ -202,33 +202,33 @@
   aimdPipeline->m_ssthresh = 4.0;
   BOOST_REQUIRE_CLOSE(aimdPipeline->m_cwnd, 1, MARGIN);
 
-  runWithData(*makeDataWithSegment(0));
+  run(name);
   advanceClocks(io, time::nanoseconds(1));
   BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
 
-  // receive segments 1 to 4
-  for (uint64_t i = 1; i < 5; ++i) {
+  // receive segments 0 to 4
+  for (uint64_t i = 0; i < 5; ++i) {
     face.receive(*makeDataWithSegment(i));
     advanceClocks(io, time::nanoseconds(1));
   }
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
-  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 4.25, MARGIN);
+  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 4.5, MARGIN);
 
   // receive segment 5 with congestion mark
   face.receive(*makeDataWithSegmentAndCongMark(5));
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
-  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 2.125, MARGIN); // window size drops to 1/2 of previous size
-  BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments - 1); // all interests have been sent
+  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 2.25, MARGIN); // window size drops to 1/2 of previous size
+  BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
 
   // receive the last segment with congestion mark
   face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
-  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 2.125, MARGIN); // conservative window adaption (window size should not decrease)
+  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 2.25, MARGIN); // conservative window adaption (window size should not decrease)
   BOOST_CHECK_EQUAL(aimdPipeline->m_retxQueue.size(), 0);
 
   // make sure no interest is retransmitted for marked data packets
@@ -248,26 +248,26 @@
   aimdPipeline->m_ssthresh = 4.0;
   BOOST_REQUIRE_CLOSE(aimdPipeline->m_cwnd, 1, MARGIN);
 
-  runWithData(*makeDataWithSegment(0));
+  run(name);
   advanceClocks(io, time::nanoseconds(1));
   BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
 
-  // receive segments 1 to 4
-  for (uint64_t i = 1; i < 5; ++i) {
+  // receive segments 0 to 4
+  for (uint64_t i = 0; i < 5; ++i) {
     face.receive(*makeDataWithSegment(i));
     advanceClocks(io, time::nanoseconds(1));
   }
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
-  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 4.25, MARGIN);
+  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 4.5, MARGIN);
 
   // receive segment 5 with congestion mark
   face.receive(*makeDataWithSegmentAndCongMark(5));
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
-  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 2.125, MARGIN); // window size drops to 1/2 of previous size
-  BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments - 1); // all interests have been sent
+  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 2.25, MARGIN); // window size drops to 1/2 of previous size
+  BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
 
   // receive the last segment with congestion mark
   face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
@@ -295,26 +295,26 @@
   aimdPipeline->m_ssthresh = 4.0;
   BOOST_REQUIRE_CLOSE(aimdPipeline->m_cwnd, 1, MARGIN);
 
-  runWithData(*makeDataWithSegment(0));
+  run(name);
   advanceClocks(io, time::nanoseconds(1));
   BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
 
-  // receive segments 1 to 5
-  for (uint64_t i = 1; i < 6; ++i) {
+  // receive segments 0 to 5
+  for (uint64_t i = 0; i < 6; ++i) {
     face.receive(*makeDataWithSegment(i));
     advanceClocks(io, time::nanoseconds(1));
   }
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
-  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 4.5, MARGIN);
-  BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments - 1); // all interests have been sent
+  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 4.75, MARGIN);
+  BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
 
   // receive the last segment with congestion mark
   face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
-  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 4.75, MARGIN); // window size increases
+  BOOST_CHECK_CLOSE(aimdPipeline->m_cwnd, 5.0, MARGIN); // window size increases
   BOOST_CHECK_EQUAL(aimdPipeline->m_retxQueue.size(), 0);
 
   // make sure no interest is retransmitted for marked data packet
@@ -328,16 +328,19 @@
 {
   nDataSegments = 5;
   aimdPipeline->m_cwnd = 10.0;
-  runWithData(*makeDataWithSegment(0));
+  run(name);
+  advanceClocks(io, time::nanoseconds(1));
+
+  face.receive(*makeDataWithSegment(0));
   advanceClocks(io, time::nanoseconds(1));
 
   face.receive(*makeDataWithSegment(1));
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
-  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 4);
+  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 10);
 
-  // receive a nack with NackReason::DUPLICATE for segment 2
+  // receive a nack with NackReason::DUPLICATE for segment 1
   auto nack1 = makeNack(face.sentInterests[1], lp::NackReason::DUPLICATE);
   face.receive(nack1);
   advanceClocks(io, time::nanoseconds(1));
@@ -347,15 +350,15 @@
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
   BOOST_CHECK_EQUAL(aimdPipeline->m_retxQueue.size(), 0);
 
-  // receive a nack with NackReason::CONGESTION for segment 3
+  // receive a nack with NackReason::CONGESTION for segment 2
   auto nack2 = makeNack(face.sentInterests[2], lp::NackReason::CONGESTION);
   face.receive(nack2);
   advanceClocks(io, time::nanoseconds(1));
 
-  // segment 3 is retransmitted
-  BOOST_CHECK_EQUAL(aimdPipeline->m_retxCount[3], 1);
+  // segment 2 is retransmitted
+  BOOST_CHECK_EQUAL(aimdPipeline->m_retxCount[2], 1);
 
-  // receive a nack with NackReason::NONE for segment 4
+  // receive a nack with NackReason::NONE for segment 3
   auto nack3 = makeNack(face.sentInterests[3], lp::NackReason::NONE);
   face.receive(nack3);
   advanceClocks(io, time::nanoseconds(1));
@@ -369,28 +372,28 @@
 {
   nDataSegments = 4;
   aimdPipeline->m_cwnd = 4;
-  runWithData(*makeDataWithSegment(0, false));
+  run(name);
   advanceClocks(io, time::nanoseconds(1));
 
-  // receive segment 1 without FinalBlockId
-  face.receive(*makeDataWithSegment(1, false));
+  // receive segment 0 without FinalBlockId
+  face.receive(*makeDataWithSegment(0, false));
   advanceClocks(io, time::nanoseconds(1));
 
-  // interests for segment 1 - 6 have been sent
+  // interests for segment 0 - 5 have been sent
   BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
-  BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
+  BOOST_CHECK_EQUAL(pipeline->m_nReceived, 1);
   BOOST_CHECK_EQUAL(aimdPipeline->m_hasFinalBlockId, false);
-  // pending interests: segment 2, 3, 4, 5, 6
+  // pending interests: segment 1, 2, 3, 4, 5
   BOOST_CHECK_EQUAL(face.getNPendingInterests(), 5);
 
-  // receive segment 2 with FinalBlockId
-  face.receive(*makeDataWithSegment(2));
+  // receive segment 1 with FinalBlockId
+  face.receive(*makeDataWithSegment(1));
   advanceClocks(io, time::nanoseconds(1));
-  BOOST_CHECK_EQUAL(pipeline->m_nReceived, 3);
+  BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
   BOOST_CHECK_EQUAL(aimdPipeline->m_hasFinalBlockId, true);
 
-  // pending interests for segment 2, 4, 5, 6 haven been removed
-  BOOST_CHECK_EQUAL(face.getNPendingInterests(), 1);
+  // pending interests for segment 1, 4, 5 haven been removed
+  BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
 }
 
 BOOST_AUTO_TEST_CASE(FailureBeforeFinalBlockIdReceived)
@@ -401,17 +404,22 @@
 
   nDataSegments = 4;
   aimdPipeline->m_cwnd = 4;
-  runWithData(*makeDataWithSegment(0, false));
+  run(name);
+  advanceClocks(io, time::nanoseconds(1));
+
+  // receive segment 0 without FinalBlockId
+  face.receive(*makeDataWithSegment(0, false));
   advanceClocks(io, time::nanoseconds(1));
 
   // receive segment 1 without FinalBlockId
   face.receive(*makeDataWithSegment(1, false));
   advanceClocks(io, time::nanoseconds(1));
-  // interests for segment 1 - 6 have been sent
-  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 6);
+
+  // interests for segment 0 - 7 have been sent
+  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
 
   // receive nack with NackReason::NONE for segment 3
-  auto nack = makeNack(face.sentInterests[2], lp::NackReason::NONE);
+  auto nack = makeNack(face.sentInterests[3], lp::NackReason::NONE);
   face.receive(nack);
   advanceClocks(io, time::nanoseconds(1));
 
@@ -436,22 +444,27 @@
 
   nDataSegments = 4;
   aimdPipeline->m_cwnd = 4;
-  runWithData(*makeDataWithSegment(0, false));
+  run(name);
+  advanceClocks(io, time::nanoseconds(1));
+
+  // receive segment 0 without FinalBlockId
+  face.receive(*makeDataWithSegment(0, false));
   advanceClocks(io, time::nanoseconds(1));
 
   // receive segment 1 without FinalBlockId
   face.receive(*makeDataWithSegment(1, false));
   advanceClocks(io, time::nanoseconds(1));
-  // interests for segment 1 - 6 have been sent
-  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 6);
+
+  // interests for segment 0 - 7 have been sent
+  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
 
   // receive nack with NackReason::NONE for segment 4
-  auto nack = makeNack(face.sentInterests[3], lp::NackReason::NONE);
+  auto nack = makeNack(face.sentInterests[4], lp::NackReason::NONE);
   face.receive(nack);
   advanceClocks(io, time::nanoseconds(1));
 
   // error not triggered
-  // pending interests for segment > 4 have been removed
+  // pending interests for segment > 3 have been removed
   BOOST_CHECK_EQUAL(hasFailed, false);
   BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
 
@@ -479,14 +492,18 @@
 
   nDataSegments = 3;
 
-  runWithData(*makeDataWithSegment(0));
+  run(name);
+  advanceClocks(io, time::nanoseconds(1));
+
+  // receive segment 0
+  face.receive(*makeDataWithSegment(0));
   advanceClocks(io, time::nanoseconds(1));
 
   // receive segment 1
   face.receive(*makeDataWithSegment(1));
   advanceClocks(io, time::nanoseconds(1));
 
-  BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
+  BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
 
   // check if segment 2's state is FirstTimeSent
   auto it = aimdPipeline->m_segmentInfo.find(2);
@@ -496,7 +513,7 @@
   // timeout segment 2 twice
   advanceClocks(io, time::milliseconds(400), 3);
 
-  BOOST_CHECK_EQUAL(face.sentInterests.size(), 4);
+  BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
 
   // check if segment 2's state is Retransmitted
   it = aimdPipeline->m_segmentInfo.find(2);
@@ -524,7 +541,7 @@
   // nothing changed
   it = aimdPipeline->m_segmentInfo.find(2);
   BOOST_CHECK(it == aimdPipeline->m_segmentInfo.end());
-  BOOST_CHECK_EQUAL(face.sentInterests.size(), 4);
+  BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
   BOOST_CHECK_EQUAL(rttEstimator.getAvgRtt(), prevRtt);
   BOOST_CHECK_EQUAL(rttEstimator.getEstimatedRto(), prevRto);
 }
@@ -562,10 +579,10 @@
   createPipeline();
   nDataSegments = 1;
 
-  runWithData(*makeDataWithSegment(0));
+  run(name);
   advanceClocks(io, time::nanoseconds(1));
 
-  face.receive(*makeDataWithSegment(1));
+  face.receive(*makeDataWithSegment(0));
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(aimdPipeline->m_hasFinalBlockId, true);
diff --git a/tests/chunks/pipeline-interests-fixed-window.t.cpp b/tests/chunks/pipeline-interests-fixed-window.t.cpp
index c4d4aad..e75b4a2 100644
--- a/tests/chunks/pipeline-interests-fixed-window.t.cpp
+++ b/tests/chunks/pipeline-interests-fixed-window.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2016-2018, Regents of the University of California,
+ * Copyright (c) 2016-2019, Regents of the University of California,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University.
  *
@@ -21,6 +21,7 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  *
  * @author Andrea Tosatto
+ * @author Chavoosh Ghasemi
  */
 
 #include "tools/chunks/catchunks/pipeline-interests-fixed-window.hpp"
@@ -61,53 +62,23 @@
 BOOST_AUTO_TEST_SUITE(Chunks)
 BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsFixedWindow, PipelineInterestFixedWindowFixture)
 
-BOOST_AUTO_TEST_CASE(FewerSegmentsThanPipelineCapacity)
-{
-  nDataSegments = 3;
-  BOOST_ASSERT(nDataSegments <= opt.maxPipelineSize);
-
-  runWithData(*makeDataWithSegment(0));
-  advanceClocks(io, time::nanoseconds(1), 1);
-  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), nDataSegments - 1);
-
-  for (uint64_t i = 1; i < nDataSegments - 1; ++i) {
-    face.receive(*makeDataWithSegment(i));
-    advanceClocks(io, time::nanoseconds(1), 1);
-
-    BOOST_CHECK_EQUAL(pipeline->m_nReceived, i + 1);
-    BOOST_REQUIRE_EQUAL(face.sentInterests.size(), nDataSegments - 1);
-    // check if the interest for the segment i+1 is well formed
-    const auto& sentInterest = face.sentInterests[i];
-    BOOST_CHECK_EQUAL(sentInterest.getExclude().size(), 0);
-    BOOST_CHECK_EQUAL(sentInterest.getMaxSuffixComponents(), 1);
-    BOOST_CHECK_EQUAL(sentInterest.getMustBeFresh(), opt.mustBeFresh);
-    BOOST_CHECK_EQUAL(Name(name).isPrefixOf(sentInterest.getName()), true);
-    BOOST_CHECK_EQUAL(getSegmentFromPacket(sentInterest), i + 1);
-  }
-
-  BOOST_CHECK_EQUAL(hasFailed, false);
-
-  advanceClocks(io, ndn::DEFAULT_INTEREST_LIFETIME, opt.maxRetriesOnTimeoutOrNack + 1);
-  BOOST_CHECK_EQUAL(hasFailed, true);
-}
-
 BOOST_AUTO_TEST_CASE(FullPipeline)
 {
   nDataSegments = 13;
   BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
 
-  runWithData(*makeDataWithSegment(nDataSegments - 1));
+  run(name);
   advanceClocks(io, time::nanoseconds(1), 1);
   BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
 
   for (uint64_t i = 0; i < nDataSegments - 1; ++i) {
     face.receive(*makeDataWithSegment(i));
     advanceClocks(io, time::nanoseconds(1), 1);
-    BOOST_CHECK_EQUAL(pipeline->m_nReceived, i + 2);
+    BOOST_CHECK_EQUAL(pipeline->m_nReceived, i + 1);
 
-    if (i < nDataSegments - opt.maxPipelineSize - 1) {
+    if (i < nDataSegments - opt.maxPipelineSize) {
       BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize + i + 1);
-      // check if the interest for the segment i+1 is well formed
+      // check if the interest for the segment i is well formed
       const auto& sentInterest = face.sentInterests[i];
       BOOST_CHECK_EQUAL(sentInterest.getExclude().size(), 0);
       BOOST_CHECK_EQUAL(sentInterest.getMaxSuffixComponents(), 1);
@@ -117,11 +88,14 @@
     }
     else {
       // all the interests have been sent for all the segments
-      BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments - 1);
+      BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments);
     }
   }
 
   BOOST_CHECK_EQUAL(hasFailed, false);
+
+  advanceClocks(io, ndn::DEFAULT_INTEREST_LIFETIME, opt.maxRetriesOnTimeoutOrNack + 1);
+  BOOST_CHECK_EQUAL(hasFailed, true);
 }
 
 BOOST_AUTO_TEST_CASE(TimeoutAllSegments)
@@ -129,14 +103,14 @@
   nDataSegments = 13;
   BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
 
-  runWithData(*makeDataWithSegment(nDataSegments - 1));
+  run(name);
   advanceClocks(io, time::nanoseconds(1), 1);
   BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
 
   for (int i = 0; i < opt.maxRetriesOnTimeoutOrNack; ++i) {
     advanceClocks(io, opt.interestLifetime, 1);
     BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize * (i + 2));
-    BOOST_CHECK_EQUAL(pipeline->m_nReceived, 1);
+    BOOST_CHECK_EQUAL(pipeline->m_nReceived, 0);
 
     // A single retry for every pipeline element
     for (size_t j = 0; j < opt.maxPipelineSize; ++j) {
@@ -157,7 +131,7 @@
   nDataSegments = 18;
   BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
 
-  runWithData(*makeDataWithSegment(nDataSegments - 1));
+  run(name);
   advanceClocks(io, time::nanoseconds(1), 1);
   BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
 
@@ -170,7 +144,7 @@
 
   // send a single data packet for each pipeline element
   advanceClocks(io, opt.interestLifetime, opt.maxRetriesOnTimeoutOrNack - 1);
-  for (uint64_t i = 0; i < opt.maxPipelineSize - 1; ++i) {
+  for (uint64_t i = 0; i < opt.maxPipelineSize; ++i) {
     face.receive(*makeDataWithSegment(opt.maxPipelineSize + i));
     advanceClocks(io, time::nanoseconds(1), 1);
   }
@@ -183,7 +157,7 @@
 
   // these new segments should not generate new interests
   advanceClocks(io, opt.interestLifetime, 1);
-  for (uint64_t i = 0; i < opt.maxPipelineSize - 1; ++i) {
+  for (uint64_t i = 0; i < opt.maxPipelineSize; ++i) {
     face.receive(*makeDataWithSegment(opt.maxPipelineSize * 2 + i - 1));
     advanceClocks(io, time::nanoseconds(1), 1);
   }
@@ -202,7 +176,7 @@
   nDataSegments = 22;
   BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
 
-  runWithData(*makeDataWithSegment(nDataSegments - 1, false));
+  run(name);
   advanceClocks(io, time::nanoseconds(1), 1);
   BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
 
@@ -231,8 +205,8 @@
   BOOST_CHECK_EQUAL(hasFailed, false);
 
   // data for all the pipeline element, but not the second (segment #1)
-  for (uint64_t i = opt.maxPipelineSize; i < nDataSegments - 1; ++i) {
-    if (i == nDataSegments - 2) {
+  for (uint64_t i = opt.maxPipelineSize; i < nDataSegments; ++i) {
+    if (i == nDataSegments - 1) {
       face.receive(*makeDataWithSegment(i, true));
     }
     else {
@@ -255,7 +229,7 @@
   nDataSegments = 22;
   BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
 
-  runWithData(*makeDataWithSegment(nDataSegments - 1, false));
+  run(name);
   advanceClocks(io, time::nanoseconds(1), 1);
   BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
 
@@ -272,11 +246,11 @@
   BOOST_CHECK_EQUAL(hasFailed, false);
 
   // data for the first pipeline element (segment #0), this should trigger an error because the
-  // others pipeline elements failed
+  // other pipeline elements failed
   face.receive(*makeDataWithSegment(0, false));
   advanceClocks(io, time::nanoseconds(1), 1);
 
-  BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
+  BOOST_CHECK_EQUAL(pipeline->m_nReceived, 1);
   BOOST_CHECK_EQUAL(hasFailed, true);
 }
 
@@ -285,13 +259,13 @@
   nDataSegments = 13;
   BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
 
-  runWithData(*makeDataWithSegment(nDataSegments - 1));
+  run(name);
   advanceClocks(io, time::nanoseconds(1), 1);
   BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
 
   // send nack for all the pipeline elements first interest
-  for (size_t j = 0; j < opt.maxPipelineSize; j++) {
-    auto nack = make_shared<lp::Nack>(face.sentInterests[j]);
+  for (size_t i = 0; i < opt.maxPipelineSize; i++) {
+    auto nack = make_shared<lp::Nack>(face.sentInterests[i]);
     nack->setReason(lp::NackReason::CONGESTION);
     face.receive(*nack);
     advanceClocks(io, time::nanoseconds(1), 1);
diff --git a/tests/chunks/pipeline-interests-fixture.hpp b/tests/chunks/pipeline-interests-fixture.hpp
index c9979fd..0d456c3 100644
--- a/tests/chunks/pipeline-interests-fixture.hpp
+++ b/tests/chunks/pipeline-interests-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2016-2018, Regents of the University of California,
+ * Copyright (c) 2016-2019, Regents of the University of California,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University.
  *
@@ -70,9 +70,9 @@
   }
 
   void
-  runWithData(const Data& data)
+  run(const Name& name, uint64_t version = 0)
   {
-    pipeline->run(data,
+    pipeline->run(Name(name).appendVersion(version),
                   [] (const Data&) {},
                   [this] (const std::string&) { hasFailed = true; });
   }
diff --git a/tools/chunks/catchunks/consumer.cpp b/tools/chunks/catchunks/consumer.cpp
index 0106629..e7f751e 100644
--- a/tools/chunks/catchunks/consumer.cpp
+++ b/tools/chunks/catchunks/consumer.cpp
@@ -45,8 +45,8 @@
   m_nextToPrint = 0;
   m_bufferedData.clear();
 
-  m_discover->onDiscoverySuccess.connect([this] (const Data& data) {
-    m_pipeline->run(data,
+  m_discover->onDiscoverySuccess.connect([this] (const Name& versionedName) {
+    m_pipeline->run(versionedName,
       [this] (const Data& data) { handleData(data); },
       [] (const std::string& msg) { NDN_THROW(std::runtime_error(msg)); });
   });
diff --git a/tools/chunks/catchunks/discover-version-fixed.cpp b/tools/chunks/catchunks/discover-version-fixed.cpp
index 5d434f0..c122d2f 100644
--- a/tools/chunks/catchunks/discover-version-fixed.cpp
+++ b/tools/chunks/catchunks/discover-version-fixed.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2016-2017, Regents of the University of California,
+ * Copyright (c) 2016-2019, Regents of the University of California,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University.
  *
@@ -52,16 +52,18 @@
   if (isVerbose)
     std::cerr << "Data: " << data << std::endl;
 
-  size_t segmentIndex = interest.getName().size();
-  if (data.getName()[segmentIndex].isSegment()) {
+  // data name must end with a segment number, preceded by a version number
+  if (data.getName().size() >= 2 &&
+      data.getName()[-1].isSegment() &&
+      data.getName()[-2].isVersion()) {
     if (isVerbose)
-      std::cerr << "Found data with the requested version: " << m_prefix[-1] << std::endl;
+      std::cerr << "Found data with the requested version: " << data.getName()[-2] << std::endl;
 
-    this->emitSignal(onDiscoverySuccess, data);
+    this->emitSignal(onDiscoverySuccess, data.getName().getPrefix(-1));
   }
   else {
     // data isn't a valid segment, add to the exclude list
-    m_strayExcludes.excludeOne(data.getName()[segmentIndex]);
+    m_strayExcludes.excludeOne(data.getName()[-1]);
     Interest newInterest(interest);
     newInterest.refreshNonce();
     newInterest.setExclude(m_strayExcludes);
diff --git a/tools/chunks/catchunks/discover-version-iterative.cpp b/tools/chunks/catchunks/discover-version-iterative.cpp
index fddf08e..adeb48e 100644
--- a/tools/chunks/catchunks/discover-version-iterative.cpp
+++ b/tools/chunks/catchunks/discover-version-iterative.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2016-2017, Regents of the University of California,
+ * Copyright (c) 2016-2019, Regents of the University of California,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University.
  *
@@ -109,12 +109,28 @@
       std::cerr << "Found data with the latest version: " << m_latestVersion << std::endl;
 
     // we discovered at least one version. assume what we have is the latest.
-    this->emitSignal(onDiscoverySuccess, *m_latestVersionData);
+    this->emitSignal(onDiscoverySuccess, Name(interest.getName()).appendVersion(m_latestVersion));
   }
   else {
     DiscoverVersion::handleTimeout(interest, reason);
   }
 }
 
+void
+DiscoverVersionIterative::handleNack(const Interest& interest, const std::string& reason)
+{
+  if (m_foundVersion) {
+    // a version has been found and after a nack this version can be used as the latest.
+    if (isVerbose)
+      std::cerr << "Found data with the latest version: " << m_latestVersion << std::endl;
+
+    // we discovered at least one version. assume what we have is the latest.
+    this->emitSignal(onDiscoverySuccess, Name(interest.getName()).appendVersion(m_latestVersion));
+  }
+  else {
+    DiscoverVersion::handleNack(interest, reason);
+  }
+}
+
 } // namespace chunks
 } // namespace ndn
diff --git a/tools/chunks/catchunks/discover-version-iterative.hpp b/tools/chunks/catchunks/discover-version-iterative.hpp
index e76ff17..8880a6d 100644
--- a/tools/chunks/catchunks/discover-version-iterative.hpp
+++ b/tools/chunks/catchunks/discover-version-iterative.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2016-2017, Regents of the University of California,
+ * Copyright (c) 2016-2019, Regents of the University of California,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University.
  *
@@ -95,6 +95,9 @@
   void
   handleTimeout(const Interest& interest, const std::string& reason) final;
 
+  void
+  handleNack(const Interest& interest, const std::string& reason) final;
+
 private:
   uint64_t m_latestVersion;
   shared_ptr<const Data> m_latestVersionData;
diff --git a/tools/chunks/catchunks/discover-version.cpp b/tools/chunks/catchunks/discover-version.cpp
index 78b7c41..3a4309c 100644
--- a/tools/chunks/catchunks/discover-version.cpp
+++ b/tools/chunks/catchunks/discover-version.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2016-2017, Regents of the University of California,
+ * Copyright (c) 2016-2019, Regents of the University of California,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University.
  *
@@ -50,12 +50,6 @@
 }
 
 void
-DiscoverVersion::handleData(const Interest& interest, const Data& data)
-{
-  onDiscoverySuccess(data);
-}
-
-void
 DiscoverVersion::handleNack(const Interest& interest, const std::string& reason)
 {
   onDiscoveryFailure(reason);
diff --git a/tools/chunks/catchunks/discover-version.hpp b/tools/chunks/catchunks/discover-version.hpp
index 464b28e..d29f94a 100644
--- a/tools/chunks/catchunks/discover-version.hpp
+++ b/tools/chunks/catchunks/discover-version.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2016-2017, Regents of the University of California,
+ * Copyright (c) 2016-2019, Regents of the University of California,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University.
  *
@@ -46,9 +46,9 @@
 {
 public: // signals
   /**
-   * @brief Signal emited when the first segment of a specific version is found.
+   * @brief Signal emitted when the versioned name of Data is found.
    */
-  signal::Signal<DiscoverVersion, const Data&> onDiscoverySuccess;
+  signal::Signal<DiscoverVersion, Name> onDiscoverySuccess;
 
   /**
    * @brief Signal emitted when a failure occurs.
@@ -78,7 +78,7 @@
   expressInterest(const Interest& interest, int maxRetriesNack, int maxRetriesTimeout);
 
   virtual void
-  handleData(const Interest& interest, const Data& data);
+  handleData(const Interest& interest, const Data& data) = 0;
 
   virtual void
   handleNack(const Interest& interest, const std::string& reason);
diff --git a/tools/chunks/catchunks/pipeline-interests.cpp b/tools/chunks/catchunks/pipeline-interests.cpp
index 2318378..a6c7c21 100644
--- a/tools/chunks/catchunks/pipeline-interests.cpp
+++ b/tools/chunks/catchunks/pipeline-interests.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2016-2018, Regents of the University of California,
+ * Copyright (c) 2016-2019, Regents of the University of California,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University.
  *
@@ -40,7 +40,6 @@
   , m_nReceived(0)
   , m_receivedSize(0)
   , m_nextSegmentNo(0)
-  , m_excludedSegmentNo(0)
   , m_isStopping(false)
 {
 }
@@ -48,20 +47,13 @@
 PipelineInterests::~PipelineInterests() = default;
 
 void
-PipelineInterests::run(const Data& data, DataCallback dataCb, FailureCallback failureCb)
+PipelineInterests::run(const Name& versionedName, DataCallback dataCb, FailureCallback failureCb)
 {
+  BOOST_ASSERT(!versionedName.empty() && versionedName[-1].isVersion());
   BOOST_ASSERT(dataCb != nullptr);
+  m_prefix = versionedName;
   m_onData = std::move(dataCb);
   m_onFailure = std::move(failureCb);
-  m_prefix = data.getName().getPrefix(-1);
-  m_excludedSegmentNo = getSegmentFromPacket(data);
-
-  if (data.getFinalBlock()) {
-    m_lastSegmentNo = data.getFinalBlock()->toSegment();
-    m_hasFinalBlockId = true;
-  }
-
-  onData(data);
 
   // record the start time of the pipeline
   m_startTime = time::steady_clock::now();
@@ -82,17 +74,14 @@
 bool
 PipelineInterests::allSegmentsReceived() const
 {
-  BOOST_ASSERT(m_nReceived > 0);
-  return m_hasFinalBlockId && static_cast<uint64_t>(m_nReceived - 1) >= m_lastSegmentNo;
+  return m_nReceived > 0 &&
+         m_hasFinalBlockId &&
+         static_cast<uint64_t>(m_nReceived - 1) >= m_lastSegmentNo;
 }
 
 uint64_t
 PipelineInterests::getNextSegmentNo()
 {
-  // skip the excluded segment
-  if (m_nextSegmentNo == m_excludedSegmentNo)
-    m_nextSegmentNo++;
-
   return m_nextSegmentNo++;
 }
 
diff --git a/tools/chunks/catchunks/pipeline-interests.hpp b/tools/chunks/catchunks/pipeline-interests.hpp
index 20fec04..fc17392 100644
--- a/tools/chunks/catchunks/pipeline-interests.hpp
+++ b/tools/chunks/catchunks/pipeline-interests.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2016-2018, Regents of the University of California,
+ * Copyright (c) 2016-2019, Regents of the University of California,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University.
  *
@@ -67,12 +67,12 @@
   /**
    * @brief start fetching all the segments of the specified prefix
    *
-   * @param data a segment of the segmented Data to fetch; the Data name must end with a segment number
+   * @param versionedName the name of the segmented Data ending with a version number
    * @param onData callback for every segment correctly received, must not be empty
    * @param onFailure callback if an error occurs, may be empty
    */
   void
-  run(const Data& data, DataCallback onData, FailureCallback onFailure);
+  run(const Name& versionedName, DataCallback onData, FailureCallback onFailure);
 
   /**
    * @brief stop all fetch operations
@@ -163,7 +163,6 @@
   DataCallback m_onData;
   FailureCallback m_onFailure;
   uint64_t m_nextSegmentNo;
-  uint64_t m_excludedSegmentNo;
   time::steady_clock::TimePoint m_startTime;
   bool m_isStopping;
 };