blob: 7f63db8ca559c429348ed8ccb865d93052a78109 [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/*
jrclark240ebaad2020-04-02 11:18:00 -05003 * Copyright (c) 2013-2020 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 Pesavento7e780642018-11-24 15:51:34 -050028#include "tests/boost-test.hpp"
29#include "tests/make-interest-data.hpp"
30#include "tests/unit/dummy-validator.hpp"
31#include "tests/unit/identity-management-time-fixture.hpp"
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070032
Eric Newberrye345baa2018-05-23 18:17:07 -070033#include <set>
34
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070035namespace ndn {
36namespace util {
37namespace tests {
38
Junxiao Shi0f3f0b42016-07-14 13:26:37 +000039using namespace ndn::tests;
40
Alexander Afanasyev80782e02017-01-04 13:16:54 -080041class Fixture : public IdentityManagementTimeFixture
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070042{
43public:
44 Fixture()
Alexander Afanasyeve4f8c3b2016-06-23 16:03:48 -070045 : face(io, m_keyChain)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070046 {
47 }
48
Davide Pesavento5d0b0102017-10-07 13:43:16 -040049 static shared_ptr<Data>
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050050 makeDataSegment(const Name& baseName, uint64_t segment, bool isFinal)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070051 {
52 const uint8_t buffer[] = "Hello, world!";
53
Junxiao Shid5827ce2016-07-14 20:49:37 +000054 auto data = make_shared<Data>(Name(baseName).appendSegment(segment));
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +000055 data->setFreshnessPeriod(1_s);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070056 data->setContent(buffer, sizeof(buffer));
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050057 if (isFinal) {
Junxiao Shiebfe4a22018-04-01 23:53:40 +000058 data->setFinalBlock(data->getName()[-1]);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050059 }
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070060
Davide Pesavento5d0b0102017-10-07 13:43:16 -040061 return signData(data);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070062 }
63
64 void
65 onError(uint32_t errorCode)
66 {
67 ++nErrors;
68 lastError = errorCode;
69 }
70
71 void
Eric Newberrye345baa2018-05-23 18:17:07 -070072 onComplete(ConstBufferPtr data)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070073 {
Eric Newberrycc910cd2018-05-06 17:01:40 -070074 ++nCompletions;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070075 dataSize = data->size();
jrclark240ebaad2020-04-02 11:18:00 -050076 }
77
78 void
79 onInOrderComplete()
80 {
81 ++nCompletions;
82 ++nOnInOrderComplete;
83 }
84
85 void
86 onInOrderData(ConstBufferPtr data)
87 {
88 ++nOnInOrderData;
89 dataSize += data->size();
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070090 }
91
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050092 void
93 nackLastInterest(lp::NackReason nackReason)
94 {
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080095 const Interest& lastInterest = face.sentInterests.back();
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050096 lp::Nack nack = makeNack(lastInterest, nackReason);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080097 face.receive(nack);
Davide Pesavento0f830802018-01-16 23:58:58 -050098 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050099 }
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700100
Eric Newberrycc910cd2018-05-06 17:01:40 -0700101 void
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500102 connectSignals(const shared_ptr<SegmentFetcher>& fetcher)
Eric Newberrycc910cd2018-05-06 17:01:40 -0700103 {
jrclark240ebaad2020-04-02 11:18:00 -0500104 fetcher->onInOrderData.connect(bind(&Fixture::onInOrderData, this, _1));
105 fetcher->onInOrderComplete.connect(bind(&Fixture::onInOrderComplete, this));
Eric Newberrycc910cd2018-05-06 17:01:40 -0700106 fetcher->onComplete.connect(bind(&Fixture::onComplete, this, _1));
107 fetcher->onError.connect(bind(&Fixture::onError, this, _1));
jrclark240ebaad2020-04-02 11:18:00 -0500108
109 fetcher->afterSegmentReceived.connect([this] (const auto&) { ++this->nAfterSegmentReceived; });
110 fetcher->afterSegmentValidated.connect([this] (const auto &) { ++this->nAfterSegmentValidated; });
111 fetcher->afterSegmentNacked.connect([this] { ++nAfterSegmentNacked; });
112 fetcher->afterSegmentTimedOut.connect([this] { ++nAfterSegmentTimedOut; });
Eric Newberrycc910cd2018-05-06 17:01:40 -0700113 }
114
Eric Newberrye345baa2018-05-23 18:17:07 -0700115 void
116 onInterest(const Interest& interest)
117 {
118 if (interest.getName().get(-1).isSegment()) {
119 if (segmentsToDropOrNack.size() > 0 &&
120 interest.getName().get(-1).toSegment() == segmentsToDropOrNack.front()) {
121 segmentsToDropOrNack.pop();
122 if (sendNackInsteadOfDropping) {
123 lp::Nack nack = makeNack(interest, nackReason);
124 face.receive(nack);
125 }
126 return;
127 }
128
129 auto data = makeDataSegment("/hello/world/version0",
130 interest.getName().get(-1).toSegment(),
131 interest.getName().get(-1).toSegment() == nSegments - 1);
132 face.receive(*data);
133
134 uniqSegmentsSent.insert(interest.getName().get(-1).toSegment());
135 if (uniqSegmentsSent.size() == nSegments) {
136 io.stop();
137 }
138 }
139 else {
140 if (segmentsToDropOrNack.size() > 0 &&
141 segmentsToDropOrNack.front() == 0) {
142 segmentsToDropOrNack.pop();
143 if (sendNackInsteadOfDropping) {
144 lp::Nack nack = makeNack(interest, nackReason);
145 face.receive(nack);
146 }
147 return;
148 }
149
150 auto data = makeDataSegment("/hello/world/version0", defaultSegmentToSend, nSegments == 1);
151 face.receive(*data);
152 uniqSegmentsSent.insert(defaultSegmentToSend);
153 }
154 }
155
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700156public:
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800157 DummyClientFace face;
Eric Newberrye345baa2018-05-23 18:17:07 -0700158 std::set<uint64_t> uniqSegmentsSent;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700159
Eric Newberrycc910cd2018-05-06 17:01:40 -0700160 int nErrors = 0;
Davide Pesavento5d0b0102017-10-07 13:43:16 -0400161 uint32_t lastError = 0;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700162 int nCompletions = 0;
Davide Pesavento5d0b0102017-10-07 13:43:16 -0400163 size_t dataSize = 0;
jrclark240ebaad2020-04-02 11:18:00 -0500164 size_t nAfterSegmentReceived = 0;
165 size_t nAfterSegmentValidated = 0;
166 size_t nAfterSegmentNacked = 0;
167 size_t nAfterSegmentTimedOut = 0;
168 size_t nOnInOrderData = 0;
169 size_t nOnInOrderComplete = 0;
Eric Newberrye345baa2018-05-23 18:17:07 -0700170
171 // number of segments in fetched object
172 uint64_t nSegments = 0;
173 std::queue<uint64_t> segmentsToDropOrNack;
174 bool sendNackInsteadOfDropping = false;
175 lp::NackReason nackReason = lp::NackReason::NONE;
176 // segment that is sent in response to an Interest w/o a segment component in its name
177 uint64_t defaultSegmentToSend = 0;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700178};
179
Eric Newberrye345baa2018-05-23 18:17:07 -0700180BOOST_AUTO_TEST_SUITE(Util)
181BOOST_FIXTURE_TEST_SUITE(TestSegmentFetcher, Fixture)
182
183BOOST_AUTO_TEST_CASE(InvalidOptions)
184{
185 SegmentFetcher::Options options;
186 options.mdCoef = 1.5;
187 DummyValidator acceptValidator;
188 BOOST_CHECK_THROW(SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options),
189 std::invalid_argument);
190}
191
192BOOST_AUTO_TEST_CASE(ExceedMaxTimeout)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700193{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800194 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700195 size_t nAfterSegmentTimedOut = 0;
196 SegmentFetcher::Options options;
197 options.maxTimeout = 100_ms;
198 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
199 acceptValidator, options);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700200 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700201 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700202
Davide Pesavento0f830802018-01-16 23:58:58 -0500203 advanceClocks(1_ms);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800204 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700205
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800206 const Interest& interest = face.sentInterests[0];
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700207 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
208 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
Eric Newberry2b765f82018-06-25 14:51:13 -0700209 BOOST_CHECK_EQUAL(interest.getCanBePrefix(), true);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800210
Davide Pesavento0f830802018-01-16 23:58:58 -0500211 advanceClocks(98_ms);
Junxiao Shid5827ce2016-07-14 20:49:37 +0000212 BOOST_CHECK_EQUAL(nErrors, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700213 BOOST_CHECK_EQUAL(nCompletions, 0);
Junxiao Shid5827ce2016-07-14 20:49:37 +0000214 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Eric Newberrye345baa2018-05-23 18:17:07 -0700215 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800216
Davide Pesavento0f830802018-01-16 23:58:58 -0500217 advanceClocks(1_ms, 2);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800218 BOOST_CHECK_EQUAL(nErrors, 1);
219 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::INTEREST_TIMEOUT));
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800220 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
221 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Eric Newberrye345baa2018-05-23 18:17:07 -0700222 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 1);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700223}
224
Eric Newberrye345baa2018-05-23 18:17:07 -0700225BOOST_AUTO_TEST_CASE(BasicSingleSegment)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700226{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800227 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700228 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700229 acceptValidator);
230 connectSignals(fetcher);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500231
Davide Pesavento0f830802018-01-16 23:58:58 -0500232 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500233
Eric Newberrye345baa2018-05-23 18:17:07 -0700234 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500235
Davide Pesavento0f830802018-01-16 23:58:58 -0500236 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500237
238 BOOST_CHECK_EQUAL(nErrors, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700239 BOOST_CHECK_EQUAL(nCompletions, 1);
Eric Newberrye345baa2018-05-23 18:17:07 -0700240 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
241 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
242 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
243 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700244}
245
Eric Newberrye345baa2018-05-23 18:17:07 -0700246BOOST_AUTO_TEST_CASE(ConstantCwnd)
247{
248 SegmentFetcher::Options options;
249 options.useConstantCwnd = true;
250 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700251 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
252 acceptValidator, options);
253 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700254
255 advanceClocks(10_ms);
256
257 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
258 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
259
260 face.receive(*makeDataSegment("/hello/world/version0", 0, 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_REQUIRE_EQUAL(face.sentInterests.size(), 2);
267 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 1);
268 face.receive(*makeDataSegment("/hello/world/version0", 1, 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(), 3);
275 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 2);
276 face.receive(*makeDataSegment("/hello/world/version0", 2, 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(), 4);
283 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 3);
284 face.receive(*makeDataSegment("/hello/world/version0", 3, false));
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(), 5);
291 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 4);
292 nackLastInterest(lp::NackReason::CONGESTION);
293
294 advanceClocks(10_ms);
295
296 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
297 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
298 BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
299 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 4);
300 face.receive(*makeDataSegment("/hello/world/version0", 4, true));
301
302 advanceClocks(10_ms);
303
304 BOOST_CHECK_EQUAL(nErrors, 0);
305 BOOST_CHECK_EQUAL(nCompletions, 1);
306 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 5);
307 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 5);
308 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 1);
309 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
310 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
311}
312
313BOOST_AUTO_TEST_CASE(BasicMultipleSegments)
Eric Newberrycc910cd2018-05-06 17:01:40 -0700314{
315 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700316 nSegments = 401;
317 sendNackInsteadOfDropping = false;
Eric Newberrye345baa2018-05-23 18:17:07 -0700318
319 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
320 acceptValidator);
jrclark240ebaad2020-04-02 11:18:00 -0500321 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700322 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700323
324 face.processEvents(1_s);
325
326 BOOST_CHECK_EQUAL(nErrors, 0);
327 BOOST_CHECK_EQUAL(nCompletions, 1);
328 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
329 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
330 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
331 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
332 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
333}
334
jrclark240ebaad2020-04-02 11:18:00 -0500335BOOST_AUTO_TEST_CASE(BasicInOrder)
336{
337 DummyValidator acceptValidator;
338 SegmentFetcher::Options options;
339 options.inOrder = true;
340 nSegments = 401;
341 sendNackInsteadOfDropping = false;
342
343 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options);
344 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
345 connectSignals(fetcher);
346
347 face.processEvents(1_s);
348
349 BOOST_CHECK_EQUAL(nErrors, 0);
350 BOOST_CHECK_EQUAL(nCompletions, 1);
351 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
352 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
353 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
354 BOOST_CHECK_EQUAL(nOnInOrderData, 401);
355 BOOST_CHECK_EQUAL(nOnInOrderComplete, 1);
356 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
357 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
358}
359
Eric Newberrye345baa2018-05-23 18:17:07 -0700360BOOST_AUTO_TEST_CASE(FirstSegmentNotZero)
361{
362 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700363 nSegments = 401;
364 sendNackInsteadOfDropping = false;
365 defaultSegmentToSend = 47;
Eric Newberrye345baa2018-05-23 18:17:07 -0700366
367 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
368 acceptValidator);
jrclark240ebaad2020-04-02 11:18:00 -0500369 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700370 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700371
372 face.processEvents(1_s);
373
374 BOOST_CHECK_EQUAL(nErrors, 0);
375 BOOST_CHECK_EQUAL(nCompletions, 1);
376 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
377 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
378 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
379 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
380 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
381}
382
jrclark240ebaad2020-04-02 11:18:00 -0500383BOOST_AUTO_TEST_CASE(FirstSegmentNotZeroInOrder)
384{
385 DummyValidator acceptValidator;
386 SegmentFetcher::Options options;
387 options.inOrder = true;
388 nSegments = 401;
389 sendNackInsteadOfDropping = false;
390 defaultSegmentToSend = 47;
391
392 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options);
393 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
394 connectSignals(fetcher);
395
396 face.processEvents(1_s);
397
398 BOOST_CHECK_EQUAL(nErrors, 0);
399 BOOST_CHECK_EQUAL(nCompletions, 1);
400 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
401 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
402 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
403 BOOST_CHECK_EQUAL(nOnInOrderData, 401);
404 BOOST_CHECK_EQUAL(nOnInOrderComplete, 1);
405 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
406 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
407}
408
Eric Newberrye345baa2018-05-23 18:17:07 -0700409BOOST_AUTO_TEST_CASE(WindowSize)
410{
411 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700412 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
413 acceptValidator);
414 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700415
416 advanceClocks(10_ms); // T+10ms
417
418 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
419 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
420 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, 0);
421 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
422 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, std::numeric_limits<double>::max());
423 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
424 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
425 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 0);
426 BOOST_CHECK_EQUAL(fetcher->m_highInterest, 0);
427 BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
428 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
429 BOOST_CHECK_EQUAL(fetcher->m_nReceived, 0);
430 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 0);
431 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), 1);
432 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
433
434 double oldCwnd = fetcher->m_cwnd;
435 double oldSsthresh = fetcher->m_ssthresh;
436 uint64_t oldNextSegmentNum = fetcher->m_nextSegmentNum;
437
438 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
439
440 advanceClocks(10_ms); //T+20ms
441
442 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
443 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
444 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
445 // +2 below because m_nextSegmentNum will be incremented in the receive callback if segment 0 is
446 // the first received
447 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 2);
448 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
449 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
450 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd + fetcher->m_options.aiStep);
451 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
452 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 14);
453 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
454 BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
455 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
456 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 1);
457 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
458 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1 + fetcher->m_cwnd);
459
460 oldCwnd = fetcher->m_cwnd;
461 oldNextSegmentNum = fetcher->m_nextSegmentNum;
462
463 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
464
465 advanceClocks(10_ms); //T+30ms
466
467 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
468 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
469 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
470 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
471 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
472 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
473 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
474 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
475 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 28);
476 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
477 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
478 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
479 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 2);
480 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
481 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2 + fetcher->m_cwnd);
482
483 oldCwnd = fetcher->m_cwnd;
484 oldNextSegmentNum = fetcher->m_nextSegmentNum;
485
486 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
487
488 advanceClocks(10_ms); //T+40ms
489
490 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
491 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
492 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
493 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
494 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
495 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
496 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
497 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
498 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
499 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
500 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
501 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
502 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
503 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
504 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3 + fetcher->m_cwnd);
505
506 oldCwnd = fetcher->m_cwnd;
507 oldSsthresh = fetcher->m_ssthresh;
508 oldNextSegmentNum = fetcher->m_nextSegmentNum;
509 size_t oldSentInterestsSize = face.sentInterests.size();
510
511 nackLastInterest(lp::NackReason::CONGESTION); //T+50ms
512
513 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 20_ms);
514 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
515 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
516 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
517 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
518 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
519 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
520 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
521 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
522 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
523 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
524 BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
525 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
526 // The Nacked segment will remain in pendingSegments, so the size of the structure doesn't change
527 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
528 BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
529
530 advanceClocks(10_ms); //T+60ms
531
532 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 30_ms);
533 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
534 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
535 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
536 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
537 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
538 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
539 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
540 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
541 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
542 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
543 BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
544 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
545 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
546 BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
547
548 // Properly end test case
549 lp::Nack nack = makeNack(face.sentInterests[face.sentInterests.size() - 2], lp::NackReason::NO_ROUTE);
550 face.receive(nack);
551 advanceClocks(10_ms); //T+70ms
552
553 BOOST_CHECK_EQUAL(nErrors, 1);
554 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::NACK_ERROR));
555 BOOST_CHECK_EQUAL(nCompletions, 0);
556}
557
558BOOST_AUTO_TEST_CASE(MissingSegmentNum)
559{
560 DummyValidator acceptValidator;
561 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700562 acceptValidator);
563 connectSignals(fetcher);
564
565 advanceClocks(10_ms);
566
567 const uint8_t buffer[] = "Hello, world!";
568 auto data = makeData("/hello/world/version0/no-segment");
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +0000569 data->setFreshnessPeriod(1_s);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700570 data->setContent(buffer, sizeof(buffer));
571
572 face.receive(*data);
573 advanceClocks(10_ms);
574
575 BOOST_CHECK_EQUAL(nErrors, 1);
576 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::DATA_HAS_NO_SEGMENT));
577 BOOST_CHECK_EQUAL(nCompletions, 0);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500578}
579
Eric Newberrye345baa2018-05-23 18:17:07 -0700580BOOST_AUTO_TEST_CASE(MoreSegmentsThanNSegments)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500581{
Eric Newberrycc910cd2018-05-06 17:01:40 -0700582 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700583 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700584 acceptValidator);
585 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700586
Davide Pesavento0f830802018-01-16 23:58:58 -0500587 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500588
Eric Newberrye345baa2018-05-23 18:17:07 -0700589 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
Davide Pesavento0f830802018-01-16 23:58:58 -0500590 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500591
Eric Newberrye345baa2018-05-23 18:17:07 -0700592 BOOST_CHECK_EQUAL(nErrors, 0);
593 BOOST_CHECK_EQUAL(nCompletions, 0);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500594
Eric Newberrye345baa2018-05-23 18:17:07 -0700595 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
Davide Pesavento0f830802018-01-16 23:58:58 -0500596 advanceClocks(10_ms);
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500597
Eric Newberrye345baa2018-05-23 18:17:07 -0700598 BOOST_CHECK_EQUAL(nErrors, 0);
599 BOOST_CHECK_EQUAL(nCompletions, 0);
600
601 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
602 advanceClocks(10_ms);
603
604 BOOST_CHECK_EQUAL(nErrors, 0);
605 BOOST_CHECK_EQUAL(nCompletions, 0);
606
607 face.receive(*makeDataSegment("/hello/world/version0", 3, false));
608 advanceClocks(10_ms);
609
610 BOOST_CHECK_EQUAL(nErrors, 0);
611 BOOST_CHECK_EQUAL(nCompletions, 0);
612
613 auto data4 = makeDataSegment("/hello/world/version0", 4, false);
614 data4->setFinalBlock(name::Component::fromSegment(2));
615 face.receive(*data4);
616 advanceClocks(10_ms);
617
618 BOOST_CHECK_EQUAL(nErrors, 0);
619 BOOST_CHECK_EQUAL(nCompletions, 1);
620 BOOST_CHECK_EQUAL(dataSize, 14 * 3);
621 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 5);
622 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 5);
623 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
624 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500625}
626
Eric Newberrye345baa2018-05-23 18:17:07 -0700627BOOST_AUTO_TEST_CASE(DuplicateNack)
628{
629 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700630 nSegments = 401;
631 segmentsToDropOrNack.push(0);
632 segmentsToDropOrNack.push(200);
633 sendNackInsteadOfDropping = true;
634 nackReason = lp::NackReason::DUPLICATE;
Eric Newberrye345baa2018-05-23 18:17:07 -0700635
636 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
637 acceptValidator);
jrclark240ebaad2020-04-02 11:18:00 -0500638 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700639 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700640
641 face.processEvents(1_s);
642
643 BOOST_CHECK_EQUAL(nErrors, 0);
644 BOOST_CHECK_EQUAL(nCompletions, 1);
645 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
646 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
647 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
648 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
649 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
650}
651
652BOOST_AUTO_TEST_CASE(CongestionNack)
653{
654 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700655 nSegments = 401;
656 segmentsToDropOrNack.push(0);
657 segmentsToDropOrNack.push(200);
658 sendNackInsteadOfDropping = true;
659 nackReason = lp::NackReason::CONGESTION;
Eric Newberrye345baa2018-05-23 18:17:07 -0700660
661 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
662 acceptValidator);
jrclark240ebaad2020-04-02 11:18:00 -0500663 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700664 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700665
666 face.processEvents(1_s);
667
668 BOOST_CHECK_EQUAL(nErrors, 0);
669 BOOST_CHECK_EQUAL(nCompletions, 1);
670 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
671 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
672 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
673 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
674 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
675}
676
677BOOST_AUTO_TEST_CASE(OtherNackReason)
678{
679 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700680 segmentsToDropOrNack.push(0);
681 sendNackInsteadOfDropping = true;
682 nackReason = lp::NackReason::NO_ROUTE;
683 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
684
685 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
686 acceptValidator);
687 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700688
689 face.processEvents(1_s);
690
691 BOOST_CHECK_EQUAL(nErrors, 1);
692 BOOST_CHECK_EQUAL(nCompletions, 0);
693 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
694 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
695 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 1);
696 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
697 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
698}
699
700BOOST_AUTO_TEST_CASE(ValidationFailure)
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000701{
702 DummyValidator validator;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700703 validator.getPolicy().setResultCallback([] (const Name& name) {
jrclark240ebaad2020-04-02 11:18:00 -0500704 return name.at(-1).toSegment() % 2 == 0;
705 });
Eric Newberrye345baa2018-05-23 18:17:07 -0700706 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700707 validator);
708 connectSignals(fetcher);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000709
710 auto data1 = makeDataSegment("/hello/world", 0, false);
711 auto data2 = makeDataSegment("/hello/world", 1, true);
712
Davide Pesavento0f830802018-01-16 23:58:58 -0500713 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000714
Eric Newberrye345baa2018-05-23 18:17:07 -0700715 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
716
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000717 face.receive(*data1);
718
Davide Pesavento0f830802018-01-16 23:58:58 -0500719 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000720
Eric Newberrye345baa2018-05-23 18:17:07 -0700721 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
722
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000723 face.receive(*data2);
724
Davide Pesavento0f830802018-01-16 23:58:58 -0500725 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000726
Eric Newberrye345baa2018-05-23 18:17:07 -0700727 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 200_ms);
jrclark240ebaad2020-04-02 11:18:00 -0500728 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 2);
729 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000730 BOOST_CHECK_EQUAL(nErrors, 1);
731}
732
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500733BOOST_AUTO_TEST_CASE(Stop)
734{
735 DummyValidator acceptValidator;
736
737 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
738 connectSignals(fetcher);
739 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
740
741 fetcher->stop();
742 advanceClocks(10_ms);
743 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
744
745 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
746 advanceClocks(10_ms);
747 BOOST_CHECK_EQUAL(nErrors, 0);
748 BOOST_CHECK_EQUAL(nCompletions, 0);
749
750 fetcher.reset();
751 BOOST_CHECK_EQUAL(fetcher.use_count(), 0);
752
753 // Make sure we can re-assign w/o any complains from ASan
754 fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
755 connectSignals(fetcher);
756 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
757
758 advanceClocks(10_ms);
759
760 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
761
762 advanceClocks(10_ms);
763 BOOST_CHECK_EQUAL(nErrors, 0);
764 BOOST_CHECK_EQUAL(nCompletions, 1);
765 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
766
767 // Stop from callback
768 bool fetcherStopped = false;
769
770 fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
jrclark240ebaad2020-04-02 11:18:00 -0500771 fetcher->afterSegmentReceived.connect([&fetcher, &fetcherStopped] (const Data&) {
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500772 fetcherStopped = true;
773 fetcher->stop();
774 });
775 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
776
777 advanceClocks(10_ms);
778
779 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
780
781 advanceClocks(10_ms);
782 BOOST_CHECK(fetcherStopped);
783 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
784}
785
786BOOST_AUTO_TEST_CASE(Lifetime)
787{
788 // BasicSingleSegment, but with scoped fetcher
789
790 DummyValidator acceptValidator;
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500791
792 weak_ptr<SegmentFetcher> weakFetcher;
793 {
794 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
795 weakFetcher = fetcher;
796 connectSignals(fetcher);
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500797 }
798
799 advanceClocks(10_ms);
800 BOOST_CHECK_EQUAL(weakFetcher.expired(), false);
801
802 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
803
804 advanceClocks(10_ms);
805
806 BOOST_CHECK_EQUAL(nErrors, 0);
807 BOOST_CHECK_EQUAL(nCompletions, 1);
808 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
809 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
810 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
811 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
812 BOOST_CHECK_EQUAL(weakFetcher.expired(), true);
813}
814
815BOOST_AUTO_TEST_CASE(OutOfScopeTimeout)
816{
817 DummyValidator acceptValidator;
818 SegmentFetcher::Options options;
819 options.maxTimeout = 3000_ms;
820
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500821 weak_ptr<SegmentFetcher> weakFetcher;
822 {
823 auto fetcher = SegmentFetcher::start(face, Interest("/localhost/nfd/faces/list"),
824 acceptValidator, options);
825 weakFetcher = fetcher;
826 connectSignals(fetcher);
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500827 }
828
829 advanceClocks(500_ms, 7);
830 BOOST_CHECK_EQUAL(weakFetcher.expired(), true);
831
832 BOOST_CHECK_EQUAL(nErrors, 1);
833 BOOST_CHECK_EQUAL(nCompletions, 0);
834 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
835 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
836 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
837 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 2);
838}
839
Ashlesh Gawandeebe156c2018-11-12 16:27:49 -0600840BOOST_AUTO_TEST_CASE(UncanceledPendingInterestBug) // Bug #4770
841{
842 DummyValidator acceptValidator;
843 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
844 connectSignals(fetcher);
845
846 // Fetcher will send the first interest immediately
847 // and the second interest after 1 second by default
848 advanceClocks(1100_ms);
849
850 // Face will give data to the fetcher twice if the first interest is not canceled.
851 // isFinal=false to keep fetcher alive so that it can receive the second data.
852 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
853
854 advanceClocks(1100_ms);
855
856 face.receive(*makeDataSegment("/hello/world/version0", 1, true));
857
858 BOOST_CHECK_EQUAL(nErrors, 0);
859 BOOST_CHECK_EQUAL(nCompletions, 1);
860}
861
Junxiao Shid5827ce2016-07-14 20:49:37 +0000862BOOST_AUTO_TEST_SUITE_END() // TestSegmentFetcher
863BOOST_AUTO_TEST_SUITE_END() // Util
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700864
865} // namespace tests
866} // namespace util
867} // namespace ndn