blob: cd74372a5d22155b369a0de6251703fd6226731f [file] [log] [blame]
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -08002/*
Davide Pesaventoa3d809e2022-02-06 11:55:02 -05003 * Copyright (c) 2013-2022 Regents of the University of California.
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library 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 * ndn-cxx library 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
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
Davide Pesavento7e780642018-11-24 15:51:34 -050022#include "ndn-cxx/util/segment-fetcher.hpp"
Davide Pesavento5d0b0102017-10-07 13:43:16 -040023
Davide Pesavento7e780642018-11-24 15:51:34 -050024#include "ndn-cxx/data.hpp"
25#include "ndn-cxx/lp/nack.hpp"
26#include "ndn-cxx/util/dummy-client-face.hpp"
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070027
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050028#include "tests/test-common.hpp"
Davide Pesavento7e780642018-11-24 15:51:34 -050029#include "tests/unit/dummy-validator.hpp"
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050030#include "tests/unit/io-key-chain-fixture.hpp"
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070031
Eric Newberrye345baa2018-05-23 18:17:07 -070032#include <set>
33
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070034namespace ndn {
35namespace util {
36namespace tests {
37
Junxiao Shi0f3f0b42016-07-14 13:26:37 +000038using namespace ndn::tests;
Davide Pesavento2e481fc2021-07-02 18:20:03 -040039using std::bind;
Junxiao Shi0f3f0b42016-07-14 13:26:37 +000040
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050041class SegmentFetcherFixture : public IoKeyChainFixture
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070042{
43public:
Davide Pesavento5d0b0102017-10-07 13:43:16 -040044 static shared_ptr<Data>
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050045 makeDataSegment(const Name& baseName, uint64_t segment, bool isFinal)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070046 {
47 const uint8_t buffer[] = "Hello, world!";
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050048 auto data = makeData(Name(baseName).appendSegment(segment));
Davide Pesaventoa3d809e2022-02-06 11:55:02 -050049 data->setContent(buffer);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050050 data->setFreshnessPeriod(1_s);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050051 if (isFinal) {
Junxiao Shiebfe4a22018-04-01 23:53:40 +000052 data->setFinalBlock(data->getName()[-1]);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050053 }
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050054 return data;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070055 }
56
57 void
58 onError(uint32_t errorCode)
59 {
60 ++nErrors;
61 lastError = errorCode;
62 }
63
64 void
Eric Newberrye345baa2018-05-23 18:17:07 -070065 onComplete(ConstBufferPtr data)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070066 {
Eric Newberrycc910cd2018-05-06 17:01:40 -070067 ++nCompletions;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070068 dataSize = data->size();
jrclark240ebaad2020-04-02 11:18:00 -050069 }
70
71 void
72 onInOrderComplete()
73 {
74 ++nCompletions;
75 ++nOnInOrderComplete;
76 }
77
78 void
79 onInOrderData(ConstBufferPtr data)
80 {
81 ++nOnInOrderData;
82 dataSize += data->size();
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070083 }
84
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050085 void
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050086 nackLastInterest(lp::NackReason reason)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050087 {
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080088 const Interest& lastInterest = face.sentInterests.back();
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050089 face.receive(makeNack(lastInterest, reason));
Davide Pesavento0f830802018-01-16 23:58:58 -050090 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050091 }
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070092
Eric Newberrycc910cd2018-05-06 17:01:40 -070093 void
Ashlesh Gawande679dbb02018-08-21 11:43:21 -050094 connectSignals(const shared_ptr<SegmentFetcher>& fetcher)
Eric Newberrycc910cd2018-05-06 17:01:40 -070095 {
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050096 fetcher->onInOrderData.connect(bind(&SegmentFetcherFixture::onInOrderData, this, _1));
97 fetcher->onInOrderComplete.connect(bind(&SegmentFetcherFixture::onInOrderComplete, this));
98 fetcher->onComplete.connect(bind(&SegmentFetcherFixture::onComplete, this, _1));
99 fetcher->onError.connect(bind(&SegmentFetcherFixture::onError, this, _1));
jrclark240ebaad2020-04-02 11:18:00 -0500100
101 fetcher->afterSegmentReceived.connect([this] (const auto&) { ++this->nAfterSegmentReceived; });
102 fetcher->afterSegmentValidated.connect([this] (const auto &) { ++this->nAfterSegmentValidated; });
103 fetcher->afterSegmentNacked.connect([this] { ++nAfterSegmentNacked; });
104 fetcher->afterSegmentTimedOut.connect([this] { ++nAfterSegmentTimedOut; });
Eric Newberrycc910cd2018-05-06 17:01:40 -0700105 }
106
Eric Newberrye345baa2018-05-23 18:17:07 -0700107 void
108 onInterest(const Interest& interest)
109 {
110 if (interest.getName().get(-1).isSegment()) {
111 if (segmentsToDropOrNack.size() > 0 &&
112 interest.getName().get(-1).toSegment() == segmentsToDropOrNack.front()) {
113 segmentsToDropOrNack.pop();
114 if (sendNackInsteadOfDropping) {
115 lp::Nack nack = makeNack(interest, nackReason);
116 face.receive(nack);
117 }
118 return;
119 }
120
121 auto data = makeDataSegment("/hello/world/version0",
122 interest.getName().get(-1).toSegment(),
123 interest.getName().get(-1).toSegment() == nSegments - 1);
124 face.receive(*data);
125
126 uniqSegmentsSent.insert(interest.getName().get(-1).toSegment());
127 if (uniqSegmentsSent.size() == nSegments) {
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500128 m_io.stop();
Eric Newberrye345baa2018-05-23 18:17:07 -0700129 }
130 }
131 else {
132 if (segmentsToDropOrNack.size() > 0 &&
133 segmentsToDropOrNack.front() == 0) {
134 segmentsToDropOrNack.pop();
135 if (sendNackInsteadOfDropping) {
136 lp::Nack nack = makeNack(interest, nackReason);
137 face.receive(nack);
138 }
139 return;
140 }
141
142 auto data = makeDataSegment("/hello/world/version0", defaultSegmentToSend, nSegments == 1);
143 face.receive(*data);
144 uniqSegmentsSent.insert(defaultSegmentToSend);
145 }
146 }
147
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700148public:
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500149 DummyClientFace face{m_io, m_keyChain};
Eric Newberrye345baa2018-05-23 18:17:07 -0700150 std::set<uint64_t> uniqSegmentsSent;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700151
Eric Newberrycc910cd2018-05-06 17:01:40 -0700152 int nErrors = 0;
Davide Pesavento5d0b0102017-10-07 13:43:16 -0400153 uint32_t lastError = 0;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700154 int nCompletions = 0;
Davide Pesavento5d0b0102017-10-07 13:43:16 -0400155 size_t dataSize = 0;
jrclark240ebaad2020-04-02 11:18:00 -0500156 size_t nAfterSegmentReceived = 0;
157 size_t nAfterSegmentValidated = 0;
158 size_t nAfterSegmentNacked = 0;
159 size_t nAfterSegmentTimedOut = 0;
160 size_t nOnInOrderData = 0;
161 size_t nOnInOrderComplete = 0;
Eric Newberrye345baa2018-05-23 18:17:07 -0700162
163 // number of segments in fetched object
164 uint64_t nSegments = 0;
165 std::queue<uint64_t> segmentsToDropOrNack;
166 bool sendNackInsteadOfDropping = false;
167 lp::NackReason nackReason = lp::NackReason::NONE;
168 // segment that is sent in response to an Interest w/o a segment component in its name
169 uint64_t defaultSegmentToSend = 0;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700170};
171
Eric Newberrye345baa2018-05-23 18:17:07 -0700172BOOST_AUTO_TEST_SUITE(Util)
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500173BOOST_FIXTURE_TEST_SUITE(TestSegmentFetcher, SegmentFetcherFixture)
Eric Newberrye345baa2018-05-23 18:17:07 -0700174
175BOOST_AUTO_TEST_CASE(InvalidOptions)
176{
177 SegmentFetcher::Options options;
178 options.mdCoef = 1.5;
179 DummyValidator acceptValidator;
180 BOOST_CHECK_THROW(SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options),
181 std::invalid_argument);
182}
183
184BOOST_AUTO_TEST_CASE(ExceedMaxTimeout)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700185{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800186 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700187 size_t nAfterSegmentTimedOut = 0;
188 SegmentFetcher::Options options;
189 options.maxTimeout = 100_ms;
190 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
191 acceptValidator, options);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700192 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700193 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700194
Davide Pesavento0f830802018-01-16 23:58:58 -0500195 advanceClocks(1_ms);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800196 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700197
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800198 const Interest& interest = face.sentInterests[0];
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700199 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
200 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
Eric Newberry2b765f82018-06-25 14:51:13 -0700201 BOOST_CHECK_EQUAL(interest.getCanBePrefix(), true);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800202
Davide Pesavento0f830802018-01-16 23:58:58 -0500203 advanceClocks(98_ms);
Junxiao Shid5827ce2016-07-14 20:49:37 +0000204 BOOST_CHECK_EQUAL(nErrors, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700205 BOOST_CHECK_EQUAL(nCompletions, 0);
Junxiao Shid5827ce2016-07-14 20:49:37 +0000206 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Eric Newberrye345baa2018-05-23 18:17:07 -0700207 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800208
Davide Pesavento0f830802018-01-16 23:58:58 -0500209 advanceClocks(1_ms, 2);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800210 BOOST_CHECK_EQUAL(nErrors, 1);
211 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::INTEREST_TIMEOUT));
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800212 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
213 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Eric Newberrye345baa2018-05-23 18:17:07 -0700214 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 1);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700215}
216
Eric Newberrye345baa2018-05-23 18:17:07 -0700217BOOST_AUTO_TEST_CASE(BasicSingleSegment)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700218{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800219 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700220 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700221 acceptValidator);
222 connectSignals(fetcher);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500223
Davide Pesavento0f830802018-01-16 23:58:58 -0500224 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500225
Eric Newberrye345baa2018-05-23 18:17:07 -0700226 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500227
Davide Pesavento0f830802018-01-16 23:58:58 -0500228 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500229
230 BOOST_CHECK_EQUAL(nErrors, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700231 BOOST_CHECK_EQUAL(nCompletions, 1);
Eric Newberrye345baa2018-05-23 18:17:07 -0700232 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
233 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
234 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
235 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700236}
237
Eric Newberrye345baa2018-05-23 18:17:07 -0700238BOOST_AUTO_TEST_CASE(ConstantCwnd)
239{
240 SegmentFetcher::Options options;
241 options.useConstantCwnd = true;
242 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700243 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
244 acceptValidator, options);
245 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700246
247 advanceClocks(10_ms);
248
249 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
250 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
251
252 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
253
254 advanceClocks(10_ms);
255
256 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
257 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
258 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 2);
259 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 1);
260 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
261
262 advanceClocks(10_ms);
263
264 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
265 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
266 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
267 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 2);
268 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
269
270 advanceClocks(10_ms);
271
272 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
273 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
274 BOOST_CHECK_EQUAL(face.sentInterests.size(), 4);
275 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 3);
276 face.receive(*makeDataSegment("/hello/world/version0", 3, false));
277
278 advanceClocks(10_ms);
279
280 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
281 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
282 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
283 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 4);
284 nackLastInterest(lp::NackReason::CONGESTION);
285
286 advanceClocks(10_ms);
287
288 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
289 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
290 BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
291 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 4);
292 face.receive(*makeDataSegment("/hello/world/version0", 4, true));
293
294 advanceClocks(10_ms);
295
296 BOOST_CHECK_EQUAL(nErrors, 0);
297 BOOST_CHECK_EQUAL(nCompletions, 1);
298 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 5);
299 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 5);
300 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 1);
301 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
302 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
303}
304
305BOOST_AUTO_TEST_CASE(BasicMultipleSegments)
Eric Newberrycc910cd2018-05-06 17:01:40 -0700306{
307 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700308 nSegments = 401;
309 sendNackInsteadOfDropping = false;
Eric Newberrye345baa2018-05-23 18:17:07 -0700310
311 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
312 acceptValidator);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500313 face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700314 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700315
316 face.processEvents(1_s);
317
318 BOOST_CHECK_EQUAL(nErrors, 0);
319 BOOST_CHECK_EQUAL(nCompletions, 1);
320 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
321 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
322 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
323 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
324 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
325}
326
jrclark240ebaad2020-04-02 11:18:00 -0500327BOOST_AUTO_TEST_CASE(BasicInOrder)
328{
329 DummyValidator acceptValidator;
330 SegmentFetcher::Options options;
331 options.inOrder = true;
332 nSegments = 401;
333 sendNackInsteadOfDropping = false;
334
335 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500336 face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
jrclark240ebaad2020-04-02 11:18:00 -0500337 connectSignals(fetcher);
338
339 face.processEvents(1_s);
340
341 BOOST_CHECK_EQUAL(nErrors, 0);
342 BOOST_CHECK_EQUAL(nCompletions, 1);
343 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
344 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
345 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
346 BOOST_CHECK_EQUAL(nOnInOrderData, 401);
347 BOOST_CHECK_EQUAL(nOnInOrderComplete, 1);
348 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
349 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
350}
351
Eric Newberrye345baa2018-05-23 18:17:07 -0700352BOOST_AUTO_TEST_CASE(FirstSegmentNotZero)
353{
354 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700355 nSegments = 401;
356 sendNackInsteadOfDropping = false;
357 defaultSegmentToSend = 47;
Eric Newberrye345baa2018-05-23 18:17:07 -0700358
359 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
360 acceptValidator);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500361 face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700362 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700363
364 face.processEvents(1_s);
365
366 BOOST_CHECK_EQUAL(nErrors, 0);
367 BOOST_CHECK_EQUAL(nCompletions, 1);
368 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
369 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
370 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
371 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
372 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
373}
374
jrclark240ebaad2020-04-02 11:18:00 -0500375BOOST_AUTO_TEST_CASE(FirstSegmentNotZeroInOrder)
376{
377 DummyValidator acceptValidator;
378 SegmentFetcher::Options options;
379 options.inOrder = true;
380 nSegments = 401;
381 sendNackInsteadOfDropping = false;
382 defaultSegmentToSend = 47;
383
384 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500385 face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
jrclark240ebaad2020-04-02 11:18:00 -0500386 connectSignals(fetcher);
387
388 face.processEvents(1_s);
389
390 BOOST_CHECK_EQUAL(nErrors, 0);
391 BOOST_CHECK_EQUAL(nCompletions, 1);
392 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
393 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
394 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
395 BOOST_CHECK_EQUAL(nOnInOrderData, 401);
396 BOOST_CHECK_EQUAL(nOnInOrderComplete, 1);
397 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
398 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
399}
400
Eric Newberrye345baa2018-05-23 18:17:07 -0700401BOOST_AUTO_TEST_CASE(WindowSize)
402{
403 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700404 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
405 acceptValidator);
406 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700407
408 advanceClocks(10_ms); // T+10ms
409
410 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
411 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
412 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, 0);
413 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
414 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, std::numeric_limits<double>::max());
415 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
416 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
417 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 0);
418 BOOST_CHECK_EQUAL(fetcher->m_highInterest, 0);
419 BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
420 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
421 BOOST_CHECK_EQUAL(fetcher->m_nReceived, 0);
422 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 0);
423 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), 1);
424 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
425
426 double oldCwnd = fetcher->m_cwnd;
427 double oldSsthresh = fetcher->m_ssthresh;
428 uint64_t oldNextSegmentNum = fetcher->m_nextSegmentNum;
429
430 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
431
432 advanceClocks(10_ms); //T+20ms
433
434 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
435 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
436 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
437 // +2 below because m_nextSegmentNum will be incremented in the receive callback if segment 0 is
438 // the first received
439 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 2);
440 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
441 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
442 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd + fetcher->m_options.aiStep);
443 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
444 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 14);
445 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
446 BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
447 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
448 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 1);
449 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
450 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1 + fetcher->m_cwnd);
451
452 oldCwnd = fetcher->m_cwnd;
453 oldNextSegmentNum = fetcher->m_nextSegmentNum;
454
455 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
456
457 advanceClocks(10_ms); //T+30ms
458
459 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
460 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
461 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
462 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
463 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
464 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
465 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
466 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
467 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 28);
468 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
469 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
470 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
471 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 2);
472 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
473 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2 + fetcher->m_cwnd);
474
475 oldCwnd = fetcher->m_cwnd;
476 oldNextSegmentNum = fetcher->m_nextSegmentNum;
477
478 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
479
480 advanceClocks(10_ms); //T+40ms
481
482 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
483 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
484 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
485 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
486 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
487 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
488 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
489 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
490 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
491 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
492 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
493 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
494 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
495 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
496 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3 + fetcher->m_cwnd);
497
498 oldCwnd = fetcher->m_cwnd;
499 oldSsthresh = fetcher->m_ssthresh;
500 oldNextSegmentNum = fetcher->m_nextSegmentNum;
501 size_t oldSentInterestsSize = face.sentInterests.size();
502
503 nackLastInterest(lp::NackReason::CONGESTION); //T+50ms
504
505 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 20_ms);
506 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
507 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
508 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
509 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
510 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
511 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
512 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
513 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
514 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
515 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
516 BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
517 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
518 // The Nacked segment will remain in pendingSegments, so the size of the structure doesn't change
519 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
520 BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
521
522 advanceClocks(10_ms); //T+60ms
523
524 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 30_ms);
525 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
526 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
527 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
528 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
529 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
530 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
531 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
532 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
533 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
534 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
535 BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
536 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
537 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
538 BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
539
540 // Properly end test case
541 lp::Nack nack = makeNack(face.sentInterests[face.sentInterests.size() - 2], lp::NackReason::NO_ROUTE);
542 face.receive(nack);
543 advanceClocks(10_ms); //T+70ms
544
545 BOOST_CHECK_EQUAL(nErrors, 1);
546 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::NACK_ERROR));
547 BOOST_CHECK_EQUAL(nCompletions, 0);
548}
549
550BOOST_AUTO_TEST_CASE(MissingSegmentNum)
551{
552 DummyValidator acceptValidator;
553 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700554 acceptValidator);
555 connectSignals(fetcher);
556
557 advanceClocks(10_ms);
558
559 const uint8_t buffer[] = "Hello, world!";
560 auto data = makeData("/hello/world/version0/no-segment");
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +0000561 data->setFreshnessPeriod(1_s);
Davide Pesaventoa3d809e2022-02-06 11:55:02 -0500562 data->setContent(buffer);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700563
564 face.receive(*data);
565 advanceClocks(10_ms);
566
567 BOOST_CHECK_EQUAL(nErrors, 1);
568 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::DATA_HAS_NO_SEGMENT));
569 BOOST_CHECK_EQUAL(nCompletions, 0);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500570}
571
Eric Newberrye345baa2018-05-23 18:17:07 -0700572BOOST_AUTO_TEST_CASE(MoreSegmentsThanNSegments)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500573{
Eric Newberrycc910cd2018-05-06 17:01:40 -0700574 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700575 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700576 acceptValidator);
577 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700578
Davide Pesavento0f830802018-01-16 23:58:58 -0500579 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500580
Eric Newberrye345baa2018-05-23 18:17:07 -0700581 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
Davide Pesavento0f830802018-01-16 23:58:58 -0500582 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500583
Eric Newberrye345baa2018-05-23 18:17:07 -0700584 BOOST_CHECK_EQUAL(nErrors, 0);
585 BOOST_CHECK_EQUAL(nCompletions, 0);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500586
Eric Newberrye345baa2018-05-23 18:17:07 -0700587 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
Davide Pesavento0f830802018-01-16 23:58:58 -0500588 advanceClocks(10_ms);
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500589
Eric Newberrye345baa2018-05-23 18:17:07 -0700590 BOOST_CHECK_EQUAL(nErrors, 0);
591 BOOST_CHECK_EQUAL(nCompletions, 0);
592
593 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
594 advanceClocks(10_ms);
595
596 BOOST_CHECK_EQUAL(nErrors, 0);
597 BOOST_CHECK_EQUAL(nCompletions, 0);
598
599 face.receive(*makeDataSegment("/hello/world/version0", 3, false));
600 advanceClocks(10_ms);
601
602 BOOST_CHECK_EQUAL(nErrors, 0);
603 BOOST_CHECK_EQUAL(nCompletions, 0);
604
605 auto data4 = makeDataSegment("/hello/world/version0", 4, false);
606 data4->setFinalBlock(name::Component::fromSegment(2));
607 face.receive(*data4);
608 advanceClocks(10_ms);
609
610 BOOST_CHECK_EQUAL(nErrors, 0);
611 BOOST_CHECK_EQUAL(nCompletions, 1);
612 BOOST_CHECK_EQUAL(dataSize, 14 * 3);
613 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 5);
614 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 5);
615 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
616 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500617}
618
Eric Newberrye345baa2018-05-23 18:17:07 -0700619BOOST_AUTO_TEST_CASE(DuplicateNack)
620{
621 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700622 nSegments = 401;
623 segmentsToDropOrNack.push(0);
624 segmentsToDropOrNack.push(200);
625 sendNackInsteadOfDropping = true;
626 nackReason = lp::NackReason::DUPLICATE;
Eric Newberrye345baa2018-05-23 18:17:07 -0700627
628 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
629 acceptValidator);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500630 face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700631 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700632
633 face.processEvents(1_s);
634
635 BOOST_CHECK_EQUAL(nErrors, 0);
636 BOOST_CHECK_EQUAL(nCompletions, 1);
637 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
638 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
639 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
640 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
641 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
642}
643
644BOOST_AUTO_TEST_CASE(CongestionNack)
645{
646 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700647 nSegments = 401;
648 segmentsToDropOrNack.push(0);
649 segmentsToDropOrNack.push(200);
650 sendNackInsteadOfDropping = true;
651 nackReason = lp::NackReason::CONGESTION;
Eric Newberrye345baa2018-05-23 18:17:07 -0700652
653 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
654 acceptValidator);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500655 face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700656 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700657
658 face.processEvents(1_s);
659
660 BOOST_CHECK_EQUAL(nErrors, 0);
661 BOOST_CHECK_EQUAL(nCompletions, 1);
662 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
663 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
664 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
665 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
666 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
667}
668
669BOOST_AUTO_TEST_CASE(OtherNackReason)
670{
671 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700672 segmentsToDropOrNack.push(0);
673 sendNackInsteadOfDropping = true;
674 nackReason = lp::NackReason::NO_ROUTE;
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500675 face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700676
677 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
678 acceptValidator);
679 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700680
681 face.processEvents(1_s);
682
683 BOOST_CHECK_EQUAL(nErrors, 1);
684 BOOST_CHECK_EQUAL(nCompletions, 0);
685 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
686 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
687 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 1);
688 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
689 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
690}
691
692BOOST_AUTO_TEST_CASE(ValidationFailure)
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000693{
694 DummyValidator validator;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700695 validator.getPolicy().setResultCallback([] (const Name& name) {
jrclark240ebaad2020-04-02 11:18:00 -0500696 return name.at(-1).toSegment() % 2 == 0;
697 });
Eric Newberrye345baa2018-05-23 18:17:07 -0700698 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700699 validator);
700 connectSignals(fetcher);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000701
702 auto data1 = makeDataSegment("/hello/world", 0, false);
703 auto data2 = makeDataSegment("/hello/world", 1, true);
704
Davide Pesavento0f830802018-01-16 23:58:58 -0500705 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000706
Eric Newberrye345baa2018-05-23 18:17:07 -0700707 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
708
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000709 face.receive(*data1);
710
Davide Pesavento0f830802018-01-16 23:58:58 -0500711 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000712
Eric Newberrye345baa2018-05-23 18:17:07 -0700713 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
714
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000715 face.receive(*data2);
716
Davide Pesavento0f830802018-01-16 23:58:58 -0500717 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000718
Eric Newberrye345baa2018-05-23 18:17:07 -0700719 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 200_ms);
jrclark240ebaad2020-04-02 11:18:00 -0500720 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 2);
721 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000722 BOOST_CHECK_EQUAL(nErrors, 1);
723}
724
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500725BOOST_AUTO_TEST_CASE(Stop)
726{
727 DummyValidator acceptValidator;
728
729 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
730 connectSignals(fetcher);
731 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
732
733 fetcher->stop();
734 advanceClocks(10_ms);
735 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
736
737 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
738 advanceClocks(10_ms);
739 BOOST_CHECK_EQUAL(nErrors, 0);
740 BOOST_CHECK_EQUAL(nCompletions, 0);
741
742 fetcher.reset();
743 BOOST_CHECK_EQUAL(fetcher.use_count(), 0);
744
745 // Make sure we can re-assign w/o any complains from ASan
746 fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
747 connectSignals(fetcher);
748 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
749
750 advanceClocks(10_ms);
751
752 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
753
754 advanceClocks(10_ms);
755 BOOST_CHECK_EQUAL(nErrors, 0);
756 BOOST_CHECK_EQUAL(nCompletions, 1);
757 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
758
759 // Stop from callback
760 bool fetcherStopped = false;
761
762 fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
jrclark240ebaad2020-04-02 11:18:00 -0500763 fetcher->afterSegmentReceived.connect([&fetcher, &fetcherStopped] (const Data&) {
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500764 fetcherStopped = true;
765 fetcher->stop();
766 });
767 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
768
769 advanceClocks(10_ms);
770
771 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
772
773 advanceClocks(10_ms);
774 BOOST_CHECK(fetcherStopped);
775 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
776}
777
778BOOST_AUTO_TEST_CASE(Lifetime)
779{
780 // BasicSingleSegment, but with scoped fetcher
781
782 DummyValidator acceptValidator;
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500783
784 weak_ptr<SegmentFetcher> weakFetcher;
785 {
786 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
787 weakFetcher = fetcher;
788 connectSignals(fetcher);
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500789 }
790
791 advanceClocks(10_ms);
792 BOOST_CHECK_EQUAL(weakFetcher.expired(), false);
793
794 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
795
796 advanceClocks(10_ms);
797
798 BOOST_CHECK_EQUAL(nErrors, 0);
799 BOOST_CHECK_EQUAL(nCompletions, 1);
800 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
801 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
802 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
803 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
804 BOOST_CHECK_EQUAL(weakFetcher.expired(), true);
805}
806
807BOOST_AUTO_TEST_CASE(OutOfScopeTimeout)
808{
809 DummyValidator acceptValidator;
810 SegmentFetcher::Options options;
811 options.maxTimeout = 3000_ms;
812
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500813 weak_ptr<SegmentFetcher> weakFetcher;
814 {
815 auto fetcher = SegmentFetcher::start(face, Interest("/localhost/nfd/faces/list"),
816 acceptValidator, options);
817 weakFetcher = fetcher;
818 connectSignals(fetcher);
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500819 }
820
821 advanceClocks(500_ms, 7);
822 BOOST_CHECK_EQUAL(weakFetcher.expired(), true);
823
824 BOOST_CHECK_EQUAL(nErrors, 1);
825 BOOST_CHECK_EQUAL(nCompletions, 0);
826 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
827 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
828 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
829 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 2);
830}
831
Ashlesh Gawandeebe156c2018-11-12 16:27:49 -0600832BOOST_AUTO_TEST_CASE(UncanceledPendingInterestBug) // Bug #4770
833{
834 DummyValidator acceptValidator;
835 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
836 connectSignals(fetcher);
837
838 // Fetcher will send the first interest immediately
839 // and the second interest after 1 second by default
840 advanceClocks(1100_ms);
841
842 // Face will give data to the fetcher twice if the first interest is not canceled.
843 // isFinal=false to keep fetcher alive so that it can receive the second data.
844 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
845
846 advanceClocks(1100_ms);
847
848 face.receive(*makeDataSegment("/hello/world/version0", 1, true));
849
850 BOOST_CHECK_EQUAL(nErrors, 0);
851 BOOST_CHECK_EQUAL(nCompletions, 1);
852}
853
Junxiao Shid5827ce2016-07-14 20:49:37 +0000854BOOST_AUTO_TEST_SUITE_END() // TestSegmentFetcher
855BOOST_AUTO_TEST_SUITE_END() // Util
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700856
857} // namespace tests
858} // namespace util
859} // namespace ndn