blob: c58c1f9ff5cf1ea844b4f675d5a6798e6b3b8ab9 [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 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;
39
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050040class SegmentFetcherFixture : public IoKeyChainFixture
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070041{
42public:
Davide Pesavento5d0b0102017-10-07 13:43:16 -040043 static shared_ptr<Data>
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050044 makeDataSegment(const Name& baseName, uint64_t segment, bool isFinal)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070045 {
46 const uint8_t buffer[] = "Hello, world!";
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050047 auto data = makeData(Name(baseName).appendSegment(segment));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070048 data->setContent(buffer, sizeof(buffer));
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050049 data->setFreshnessPeriod(1_s);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050050 if (isFinal) {
Junxiao Shiebfe4a22018-04-01 23:53:40 +000051 data->setFinalBlock(data->getName()[-1]);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050052 }
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050053 return data;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070054 }
55
56 void
57 onError(uint32_t errorCode)
58 {
59 ++nErrors;
60 lastError = errorCode;
61 }
62
63 void
Eric Newberrye345baa2018-05-23 18:17:07 -070064 onComplete(ConstBufferPtr data)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070065 {
Eric Newberrycc910cd2018-05-06 17:01:40 -070066 ++nCompletions;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070067 dataSize = data->size();
jrclark240ebaad2020-04-02 11:18:00 -050068 }
69
70 void
71 onInOrderComplete()
72 {
73 ++nCompletions;
74 ++nOnInOrderComplete;
75 }
76
77 void
78 onInOrderData(ConstBufferPtr data)
79 {
80 ++nOnInOrderData;
81 dataSize += data->size();
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070082 }
83
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050084 void
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050085 nackLastInterest(lp::NackReason reason)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050086 {
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080087 const Interest& lastInterest = face.sentInterests.back();
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050088 face.receive(makeNack(lastInterest, reason));
Davide Pesavento0f830802018-01-16 23:58:58 -050089 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050090 }
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070091
Eric Newberrycc910cd2018-05-06 17:01:40 -070092 void
Ashlesh Gawande679dbb02018-08-21 11:43:21 -050093 connectSignals(const shared_ptr<SegmentFetcher>& fetcher)
Eric Newberrycc910cd2018-05-06 17:01:40 -070094 {
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050095 fetcher->onInOrderData.connect(bind(&SegmentFetcherFixture::onInOrderData, this, _1));
96 fetcher->onInOrderComplete.connect(bind(&SegmentFetcherFixture::onInOrderComplete, this));
97 fetcher->onComplete.connect(bind(&SegmentFetcherFixture::onComplete, this, _1));
98 fetcher->onError.connect(bind(&SegmentFetcherFixture::onError, this, _1));
jrclark240ebaad2020-04-02 11:18:00 -050099
100 fetcher->afterSegmentReceived.connect([this] (const auto&) { ++this->nAfterSegmentReceived; });
101 fetcher->afterSegmentValidated.connect([this] (const auto &) { ++this->nAfterSegmentValidated; });
102 fetcher->afterSegmentNacked.connect([this] { ++nAfterSegmentNacked; });
103 fetcher->afterSegmentTimedOut.connect([this] { ++nAfterSegmentTimedOut; });
Eric Newberrycc910cd2018-05-06 17:01:40 -0700104 }
105
Eric Newberrye345baa2018-05-23 18:17:07 -0700106 void
107 onInterest(const Interest& interest)
108 {
109 if (interest.getName().get(-1).isSegment()) {
110 if (segmentsToDropOrNack.size() > 0 &&
111 interest.getName().get(-1).toSegment() == segmentsToDropOrNack.front()) {
112 segmentsToDropOrNack.pop();
113 if (sendNackInsteadOfDropping) {
114 lp::Nack nack = makeNack(interest, nackReason);
115 face.receive(nack);
116 }
117 return;
118 }
119
120 auto data = makeDataSegment("/hello/world/version0",
121 interest.getName().get(-1).toSegment(),
122 interest.getName().get(-1).toSegment() == nSegments - 1);
123 face.receive(*data);
124
125 uniqSegmentsSent.insert(interest.getName().get(-1).toSegment());
126 if (uniqSegmentsSent.size() == nSegments) {
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500127 m_io.stop();
Eric Newberrye345baa2018-05-23 18:17:07 -0700128 }
129 }
130 else {
131 if (segmentsToDropOrNack.size() > 0 &&
132 segmentsToDropOrNack.front() == 0) {
133 segmentsToDropOrNack.pop();
134 if (sendNackInsteadOfDropping) {
135 lp::Nack nack = makeNack(interest, nackReason);
136 face.receive(nack);
137 }
138 return;
139 }
140
141 auto data = makeDataSegment("/hello/world/version0", defaultSegmentToSend, nSegments == 1);
142 face.receive(*data);
143 uniqSegmentsSent.insert(defaultSegmentToSend);
144 }
145 }
146
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700147public:
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500148 DummyClientFace face{m_io, m_keyChain};
Eric Newberrye345baa2018-05-23 18:17:07 -0700149 std::set<uint64_t> uniqSegmentsSent;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700150
Eric Newberrycc910cd2018-05-06 17:01:40 -0700151 int nErrors = 0;
Davide Pesavento5d0b0102017-10-07 13:43:16 -0400152 uint32_t lastError = 0;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700153 int nCompletions = 0;
Davide Pesavento5d0b0102017-10-07 13:43:16 -0400154 size_t dataSize = 0;
jrclark240ebaad2020-04-02 11:18:00 -0500155 size_t nAfterSegmentReceived = 0;
156 size_t nAfterSegmentValidated = 0;
157 size_t nAfterSegmentNacked = 0;
158 size_t nAfterSegmentTimedOut = 0;
159 size_t nOnInOrderData = 0;
160 size_t nOnInOrderComplete = 0;
Eric Newberrye345baa2018-05-23 18:17:07 -0700161
162 // number of segments in fetched object
163 uint64_t nSegments = 0;
164 std::queue<uint64_t> segmentsToDropOrNack;
165 bool sendNackInsteadOfDropping = false;
166 lp::NackReason nackReason = lp::NackReason::NONE;
167 // segment that is sent in response to an Interest w/o a segment component in its name
168 uint64_t defaultSegmentToSend = 0;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700169};
170
Eric Newberrye345baa2018-05-23 18:17:07 -0700171BOOST_AUTO_TEST_SUITE(Util)
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500172BOOST_FIXTURE_TEST_SUITE(TestSegmentFetcher, SegmentFetcherFixture)
Eric Newberrye345baa2018-05-23 18:17:07 -0700173
174BOOST_AUTO_TEST_CASE(InvalidOptions)
175{
176 SegmentFetcher::Options options;
177 options.mdCoef = 1.5;
178 DummyValidator acceptValidator;
179 BOOST_CHECK_THROW(SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options),
180 std::invalid_argument);
181}
182
183BOOST_AUTO_TEST_CASE(ExceedMaxTimeout)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700184{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800185 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700186 size_t nAfterSegmentTimedOut = 0;
187 SegmentFetcher::Options options;
188 options.maxTimeout = 100_ms;
189 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
190 acceptValidator, options);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700191 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700192 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700193
Davide Pesavento0f830802018-01-16 23:58:58 -0500194 advanceClocks(1_ms);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800195 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700196
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800197 const Interest& interest = face.sentInterests[0];
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700198 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
199 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
Eric Newberry2b765f82018-06-25 14:51:13 -0700200 BOOST_CHECK_EQUAL(interest.getCanBePrefix(), true);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800201
Davide Pesavento0f830802018-01-16 23:58:58 -0500202 advanceClocks(98_ms);
Junxiao Shid5827ce2016-07-14 20:49:37 +0000203 BOOST_CHECK_EQUAL(nErrors, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700204 BOOST_CHECK_EQUAL(nCompletions, 0);
Junxiao Shid5827ce2016-07-14 20:49:37 +0000205 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Eric Newberrye345baa2018-05-23 18:17:07 -0700206 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800207
Davide Pesavento0f830802018-01-16 23:58:58 -0500208 advanceClocks(1_ms, 2);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800209 BOOST_CHECK_EQUAL(nErrors, 1);
210 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::INTEREST_TIMEOUT));
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800211 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
212 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Eric Newberrye345baa2018-05-23 18:17:07 -0700213 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 1);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700214}
215
Eric Newberrye345baa2018-05-23 18:17:07 -0700216BOOST_AUTO_TEST_CASE(BasicSingleSegment)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700217{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800218 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700219 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700220 acceptValidator);
221 connectSignals(fetcher);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500222
Davide Pesavento0f830802018-01-16 23:58:58 -0500223 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500224
Eric Newberrye345baa2018-05-23 18:17:07 -0700225 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500226
Davide Pesavento0f830802018-01-16 23:58:58 -0500227 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500228
229 BOOST_CHECK_EQUAL(nErrors, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700230 BOOST_CHECK_EQUAL(nCompletions, 1);
Eric Newberrye345baa2018-05-23 18:17:07 -0700231 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
232 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
233 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
234 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700235}
236
Eric Newberrye345baa2018-05-23 18:17:07 -0700237BOOST_AUTO_TEST_CASE(ConstantCwnd)
238{
239 SegmentFetcher::Options options;
240 options.useConstantCwnd = true;
241 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700242 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
243 acceptValidator, options);
244 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700245
246 advanceClocks(10_ms);
247
248 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
249 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
250
251 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
252
253 advanceClocks(10_ms);
254
255 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
256 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
257 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 2);
258 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 1);
259 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
260
261 advanceClocks(10_ms);
262
263 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
264 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
265 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
266 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 2);
267 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
268
269 advanceClocks(10_ms);
270
271 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
272 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
273 BOOST_CHECK_EQUAL(face.sentInterests.size(), 4);
274 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 3);
275 face.receive(*makeDataSegment("/hello/world/version0", 3, false));
276
277 advanceClocks(10_ms);
278
279 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
280 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
281 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
282 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 4);
283 nackLastInterest(lp::NackReason::CONGESTION);
284
285 advanceClocks(10_ms);
286
287 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
288 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
289 BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
290 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 4);
291 face.receive(*makeDataSegment("/hello/world/version0", 4, true));
292
293 advanceClocks(10_ms);
294
295 BOOST_CHECK_EQUAL(nErrors, 0);
296 BOOST_CHECK_EQUAL(nCompletions, 1);
297 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 5);
298 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 5);
299 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 1);
300 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
301 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
302}
303
304BOOST_AUTO_TEST_CASE(BasicMultipleSegments)
Eric Newberrycc910cd2018-05-06 17:01:40 -0700305{
306 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700307 nSegments = 401;
308 sendNackInsteadOfDropping = false;
Eric Newberrye345baa2018-05-23 18:17:07 -0700309
310 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
311 acceptValidator);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500312 face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700313 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700314
315 face.processEvents(1_s);
316
317 BOOST_CHECK_EQUAL(nErrors, 0);
318 BOOST_CHECK_EQUAL(nCompletions, 1);
319 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
320 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
321 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
322 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
323 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
324}
325
jrclark240ebaad2020-04-02 11:18:00 -0500326BOOST_AUTO_TEST_CASE(BasicInOrder)
327{
328 DummyValidator acceptValidator;
329 SegmentFetcher::Options options;
330 options.inOrder = true;
331 nSegments = 401;
332 sendNackInsteadOfDropping = false;
333
334 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500335 face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
jrclark240ebaad2020-04-02 11:18:00 -0500336 connectSignals(fetcher);
337
338 face.processEvents(1_s);
339
340 BOOST_CHECK_EQUAL(nErrors, 0);
341 BOOST_CHECK_EQUAL(nCompletions, 1);
342 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
343 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
344 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
345 BOOST_CHECK_EQUAL(nOnInOrderData, 401);
346 BOOST_CHECK_EQUAL(nOnInOrderComplete, 1);
347 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
348 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
349}
350
Eric Newberrye345baa2018-05-23 18:17:07 -0700351BOOST_AUTO_TEST_CASE(FirstSegmentNotZero)
352{
353 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700354 nSegments = 401;
355 sendNackInsteadOfDropping = false;
356 defaultSegmentToSend = 47;
Eric Newberrye345baa2018-05-23 18:17:07 -0700357
358 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
359 acceptValidator);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500360 face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700361 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700362
363 face.processEvents(1_s);
364
365 BOOST_CHECK_EQUAL(nErrors, 0);
366 BOOST_CHECK_EQUAL(nCompletions, 1);
367 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
368 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
369 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
370 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
371 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
372}
373
jrclark240ebaad2020-04-02 11:18:00 -0500374BOOST_AUTO_TEST_CASE(FirstSegmentNotZeroInOrder)
375{
376 DummyValidator acceptValidator;
377 SegmentFetcher::Options options;
378 options.inOrder = true;
379 nSegments = 401;
380 sendNackInsteadOfDropping = false;
381 defaultSegmentToSend = 47;
382
383 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500384 face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
jrclark240ebaad2020-04-02 11:18:00 -0500385 connectSignals(fetcher);
386
387 face.processEvents(1_s);
388
389 BOOST_CHECK_EQUAL(nErrors, 0);
390 BOOST_CHECK_EQUAL(nCompletions, 1);
391 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
392 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
393 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
394 BOOST_CHECK_EQUAL(nOnInOrderData, 401);
395 BOOST_CHECK_EQUAL(nOnInOrderComplete, 1);
396 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
397 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
398}
399
Eric Newberrye345baa2018-05-23 18:17:07 -0700400BOOST_AUTO_TEST_CASE(WindowSize)
401{
402 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700403 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
404 acceptValidator);
405 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700406
407 advanceClocks(10_ms); // T+10ms
408
409 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
410 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
411 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, 0);
412 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
413 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, std::numeric_limits<double>::max());
414 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
415 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
416 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 0);
417 BOOST_CHECK_EQUAL(fetcher->m_highInterest, 0);
418 BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
419 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
420 BOOST_CHECK_EQUAL(fetcher->m_nReceived, 0);
421 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 0);
422 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), 1);
423 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
424
425 double oldCwnd = fetcher->m_cwnd;
426 double oldSsthresh = fetcher->m_ssthresh;
427 uint64_t oldNextSegmentNum = fetcher->m_nextSegmentNum;
428
429 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
430
431 advanceClocks(10_ms); //T+20ms
432
433 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
434 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
435 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
436 // +2 below because m_nextSegmentNum will be incremented in the receive callback if segment 0 is
437 // the first received
438 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 2);
439 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
440 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
441 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd + fetcher->m_options.aiStep);
442 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
443 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 14);
444 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
445 BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
446 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
447 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 1);
448 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
449 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1 + fetcher->m_cwnd);
450
451 oldCwnd = fetcher->m_cwnd;
452 oldNextSegmentNum = fetcher->m_nextSegmentNum;
453
454 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
455
456 advanceClocks(10_ms); //T+30ms
457
458 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
459 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
460 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
461 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
462 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
463 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
464 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
465 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
466 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 28);
467 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
468 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
469 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
470 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 2);
471 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
472 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2 + fetcher->m_cwnd);
473
474 oldCwnd = fetcher->m_cwnd;
475 oldNextSegmentNum = fetcher->m_nextSegmentNum;
476
477 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
478
479 advanceClocks(10_ms); //T+40ms
480
481 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
482 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
483 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
484 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
485 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
486 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
487 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
488 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
489 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
490 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
491 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
492 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
493 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
494 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
495 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3 + fetcher->m_cwnd);
496
497 oldCwnd = fetcher->m_cwnd;
498 oldSsthresh = fetcher->m_ssthresh;
499 oldNextSegmentNum = fetcher->m_nextSegmentNum;
500 size_t oldSentInterestsSize = face.sentInterests.size();
501
502 nackLastInterest(lp::NackReason::CONGESTION); //T+50ms
503
504 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 20_ms);
505 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
506 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
507 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
508 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
509 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
510 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
511 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
512 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
513 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
514 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
515 BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
516 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
517 // The Nacked segment will remain in pendingSegments, so the size of the structure doesn't change
518 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
519 BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
520
521 advanceClocks(10_ms); //T+60ms
522
523 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 30_ms);
524 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
525 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
526 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
527 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
528 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
529 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
530 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
531 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
532 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
533 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
534 BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
535 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
536 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
537 BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
538
539 // Properly end test case
540 lp::Nack nack = makeNack(face.sentInterests[face.sentInterests.size() - 2], lp::NackReason::NO_ROUTE);
541 face.receive(nack);
542 advanceClocks(10_ms); //T+70ms
543
544 BOOST_CHECK_EQUAL(nErrors, 1);
545 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::NACK_ERROR));
546 BOOST_CHECK_EQUAL(nCompletions, 0);
547}
548
549BOOST_AUTO_TEST_CASE(MissingSegmentNum)
550{
551 DummyValidator acceptValidator;
552 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700553 acceptValidator);
554 connectSignals(fetcher);
555
556 advanceClocks(10_ms);
557
558 const uint8_t buffer[] = "Hello, world!";
559 auto data = makeData("/hello/world/version0/no-segment");
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +0000560 data->setFreshnessPeriod(1_s);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700561 data->setContent(buffer, sizeof(buffer));
562
563 face.receive(*data);
564 advanceClocks(10_ms);
565
566 BOOST_CHECK_EQUAL(nErrors, 1);
567 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::DATA_HAS_NO_SEGMENT));
568 BOOST_CHECK_EQUAL(nCompletions, 0);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500569}
570
Eric Newberrye345baa2018-05-23 18:17:07 -0700571BOOST_AUTO_TEST_CASE(MoreSegmentsThanNSegments)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500572{
Eric Newberrycc910cd2018-05-06 17:01:40 -0700573 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700574 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700575 acceptValidator);
576 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700577
Davide Pesavento0f830802018-01-16 23:58:58 -0500578 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500579
Eric Newberrye345baa2018-05-23 18:17:07 -0700580 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
Davide Pesavento0f830802018-01-16 23:58:58 -0500581 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500582
Eric Newberrye345baa2018-05-23 18:17:07 -0700583 BOOST_CHECK_EQUAL(nErrors, 0);
584 BOOST_CHECK_EQUAL(nCompletions, 0);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500585
Eric Newberrye345baa2018-05-23 18:17:07 -0700586 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
Davide Pesavento0f830802018-01-16 23:58:58 -0500587 advanceClocks(10_ms);
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500588
Eric Newberrye345baa2018-05-23 18:17:07 -0700589 BOOST_CHECK_EQUAL(nErrors, 0);
590 BOOST_CHECK_EQUAL(nCompletions, 0);
591
592 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
593 advanceClocks(10_ms);
594
595 BOOST_CHECK_EQUAL(nErrors, 0);
596 BOOST_CHECK_EQUAL(nCompletions, 0);
597
598 face.receive(*makeDataSegment("/hello/world/version0", 3, false));
599 advanceClocks(10_ms);
600
601 BOOST_CHECK_EQUAL(nErrors, 0);
602 BOOST_CHECK_EQUAL(nCompletions, 0);
603
604 auto data4 = makeDataSegment("/hello/world/version0", 4, false);
605 data4->setFinalBlock(name::Component::fromSegment(2));
606 face.receive(*data4);
607 advanceClocks(10_ms);
608
609 BOOST_CHECK_EQUAL(nErrors, 0);
610 BOOST_CHECK_EQUAL(nCompletions, 1);
611 BOOST_CHECK_EQUAL(dataSize, 14 * 3);
612 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 5);
613 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 5);
614 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
615 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500616}
617
Eric Newberrye345baa2018-05-23 18:17:07 -0700618BOOST_AUTO_TEST_CASE(DuplicateNack)
619{
620 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700621 nSegments = 401;
622 segmentsToDropOrNack.push(0);
623 segmentsToDropOrNack.push(200);
624 sendNackInsteadOfDropping = true;
625 nackReason = lp::NackReason::DUPLICATE;
Eric Newberrye345baa2018-05-23 18:17:07 -0700626
627 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
628 acceptValidator);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500629 face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700630 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700631
632 face.processEvents(1_s);
633
634 BOOST_CHECK_EQUAL(nErrors, 0);
635 BOOST_CHECK_EQUAL(nCompletions, 1);
636 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
637 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
638 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
639 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
640 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
641}
642
643BOOST_AUTO_TEST_CASE(CongestionNack)
644{
645 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700646 nSegments = 401;
647 segmentsToDropOrNack.push(0);
648 segmentsToDropOrNack.push(200);
649 sendNackInsteadOfDropping = true;
650 nackReason = lp::NackReason::CONGESTION;
Eric Newberrye345baa2018-05-23 18:17:07 -0700651
652 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
653 acceptValidator);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500654 face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700655 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700656
657 face.processEvents(1_s);
658
659 BOOST_CHECK_EQUAL(nErrors, 0);
660 BOOST_CHECK_EQUAL(nCompletions, 1);
661 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
662 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
663 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
664 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
665 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
666}
667
668BOOST_AUTO_TEST_CASE(OtherNackReason)
669{
670 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700671 segmentsToDropOrNack.push(0);
672 sendNackInsteadOfDropping = true;
673 nackReason = lp::NackReason::NO_ROUTE;
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500674 face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700675
676 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
677 acceptValidator);
678 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700679
680 face.processEvents(1_s);
681
682 BOOST_CHECK_EQUAL(nErrors, 1);
683 BOOST_CHECK_EQUAL(nCompletions, 0);
684 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
685 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
686 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 1);
687 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
688 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
689}
690
691BOOST_AUTO_TEST_CASE(ValidationFailure)
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000692{
693 DummyValidator validator;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700694 validator.getPolicy().setResultCallback([] (const Name& name) {
jrclark240ebaad2020-04-02 11:18:00 -0500695 return name.at(-1).toSegment() % 2 == 0;
696 });
Eric Newberrye345baa2018-05-23 18:17:07 -0700697 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700698 validator);
699 connectSignals(fetcher);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000700
701 auto data1 = makeDataSegment("/hello/world", 0, false);
702 auto data2 = makeDataSegment("/hello/world", 1, true);
703
Davide Pesavento0f830802018-01-16 23:58:58 -0500704 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000705
Eric Newberrye345baa2018-05-23 18:17:07 -0700706 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
707
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000708 face.receive(*data1);
709
Davide Pesavento0f830802018-01-16 23:58:58 -0500710 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000711
Eric Newberrye345baa2018-05-23 18:17:07 -0700712 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
713
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000714 face.receive(*data2);
715
Davide Pesavento0f830802018-01-16 23:58:58 -0500716 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000717
Eric Newberrye345baa2018-05-23 18:17:07 -0700718 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 200_ms);
jrclark240ebaad2020-04-02 11:18:00 -0500719 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 2);
720 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000721 BOOST_CHECK_EQUAL(nErrors, 1);
722}
723
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500724BOOST_AUTO_TEST_CASE(Stop)
725{
726 DummyValidator acceptValidator;
727
728 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
729 connectSignals(fetcher);
730 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
731
732 fetcher->stop();
733 advanceClocks(10_ms);
734 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
735
736 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
737 advanceClocks(10_ms);
738 BOOST_CHECK_EQUAL(nErrors, 0);
739 BOOST_CHECK_EQUAL(nCompletions, 0);
740
741 fetcher.reset();
742 BOOST_CHECK_EQUAL(fetcher.use_count(), 0);
743
744 // Make sure we can re-assign w/o any complains from ASan
745 fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
746 connectSignals(fetcher);
747 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
748
749 advanceClocks(10_ms);
750
751 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
752
753 advanceClocks(10_ms);
754 BOOST_CHECK_EQUAL(nErrors, 0);
755 BOOST_CHECK_EQUAL(nCompletions, 1);
756 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
757
758 // Stop from callback
759 bool fetcherStopped = false;
760
761 fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
jrclark240ebaad2020-04-02 11:18:00 -0500762 fetcher->afterSegmentReceived.connect([&fetcher, &fetcherStopped] (const Data&) {
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500763 fetcherStopped = true;
764 fetcher->stop();
765 });
766 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
767
768 advanceClocks(10_ms);
769
770 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
771
772 advanceClocks(10_ms);
773 BOOST_CHECK(fetcherStopped);
774 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
775}
776
777BOOST_AUTO_TEST_CASE(Lifetime)
778{
779 // BasicSingleSegment, but with scoped fetcher
780
781 DummyValidator acceptValidator;
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500782
783 weak_ptr<SegmentFetcher> weakFetcher;
784 {
785 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
786 weakFetcher = fetcher;
787 connectSignals(fetcher);
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500788 }
789
790 advanceClocks(10_ms);
791 BOOST_CHECK_EQUAL(weakFetcher.expired(), false);
792
793 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
794
795 advanceClocks(10_ms);
796
797 BOOST_CHECK_EQUAL(nErrors, 0);
798 BOOST_CHECK_EQUAL(nCompletions, 1);
799 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
800 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
801 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
802 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
803 BOOST_CHECK_EQUAL(weakFetcher.expired(), true);
804}
805
806BOOST_AUTO_TEST_CASE(OutOfScopeTimeout)
807{
808 DummyValidator acceptValidator;
809 SegmentFetcher::Options options;
810 options.maxTimeout = 3000_ms;
811
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500812 weak_ptr<SegmentFetcher> weakFetcher;
813 {
814 auto fetcher = SegmentFetcher::start(face, Interest("/localhost/nfd/faces/list"),
815 acceptValidator, options);
816 weakFetcher = fetcher;
817 connectSignals(fetcher);
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500818 }
819
820 advanceClocks(500_ms, 7);
821 BOOST_CHECK_EQUAL(weakFetcher.expired(), true);
822
823 BOOST_CHECK_EQUAL(nErrors, 1);
824 BOOST_CHECK_EQUAL(nCompletions, 0);
825 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
826 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
827 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
828 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 2);
829}
830
Ashlesh Gawandeebe156c2018-11-12 16:27:49 -0600831BOOST_AUTO_TEST_CASE(UncanceledPendingInterestBug) // Bug #4770
832{
833 DummyValidator acceptValidator;
834 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
835 connectSignals(fetcher);
836
837 // Fetcher will send the first interest immediately
838 // and the second interest after 1 second by default
839 advanceClocks(1100_ms);
840
841 // Face will give data to the fetcher twice if the first interest is not canceled.
842 // isFinal=false to keep fetcher alive so that it can receive the second data.
843 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
844
845 advanceClocks(1100_ms);
846
847 face.receive(*makeDataSegment("/hello/world/version0", 1, true));
848
849 BOOST_CHECK_EQUAL(nErrors, 0);
850 BOOST_CHECK_EQUAL(nCompletions, 1);
851}
852
Junxiao Shid5827ce2016-07-14 20:49:37 +0000853BOOST_AUTO_TEST_SUITE_END() // TestSegmentFetcher
854BOOST_AUTO_TEST_SUITE_END() // Util
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700855
856} // namespace tests
857} // namespace util
858} // namespace ndn