blob: 567918aa035fd7ecb6e10f7cab4153a6d77e1c9d [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 Pesavento0c526032024-01-31 21:14:01 -05003 * Copyright (c) 2013-2024 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
Davide Pesavento47ce2ee2023-05-09 01:33:33 -040034namespace ndn::tests {
Junxiao Shi0f3f0b42016-07-14 13:26:37 +000035
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050036class SegmentFetcherFixture : public IoKeyChainFixture
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070037{
38public:
Davide Pesavento5d0b0102017-10-07 13:43:16 -040039 static shared_ptr<Data>
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050040 makeDataSegment(const Name& baseName, uint64_t segment, bool isFinal)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070041 {
42 const uint8_t buffer[] = "Hello, world!";
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050043 auto data = makeData(Name(baseName).appendSegment(segment));
Davide Pesaventoa3d809e2022-02-06 11:55:02 -050044 data->setContent(buffer);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050045 data->setFreshnessPeriod(1_s);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050046 if (isFinal) {
Junxiao Shiebfe4a22018-04-01 23:53:40 +000047 data->setFinalBlock(data->getName()[-1]);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050048 }
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050049 return data;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070050 }
51
52 void
53 onError(uint32_t errorCode)
54 {
55 ++nErrors;
56 lastError = errorCode;
57 }
58
59 void
Eric Newberrye345baa2018-05-23 18:17:07 -070060 onComplete(ConstBufferPtr data)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070061 {
Eric Newberrycc910cd2018-05-06 17:01:40 -070062 ++nCompletions;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070063 dataSize = data->size();
jrclark240ebaad2020-04-02 11:18:00 -050064 }
65
66 void
67 onInOrderComplete()
68 {
69 ++nCompletions;
70 ++nOnInOrderComplete;
71 }
72
73 void
74 onInOrderData(ConstBufferPtr data)
75 {
76 ++nOnInOrderData;
77 dataSize += data->size();
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070078 }
79
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050080 void
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050081 nackLastInterest(lp::NackReason reason)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050082 {
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080083 const Interest& lastInterest = face.sentInterests.back();
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050084 face.receive(makeNack(lastInterest, reason));
Davide Pesavento0f830802018-01-16 23:58:58 -050085 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050086 }
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070087
Eric Newberrycc910cd2018-05-06 17:01:40 -070088 void
Ashlesh Gawande679dbb02018-08-21 11:43:21 -050089 connectSignals(const shared_ptr<SegmentFetcher>& fetcher)
Eric Newberrycc910cd2018-05-06 17:01:40 -070090 {
Davide Pesavento152ef442023-04-22 02:02:29 -040091 fetcher->onInOrderData.connect(std::bind(&SegmentFetcherFixture::onInOrderData, this, _1));
92 fetcher->onInOrderComplete.connect(std::bind(&SegmentFetcherFixture::onInOrderComplete, this));
93 fetcher->onComplete.connect(std::bind(&SegmentFetcherFixture::onComplete, this, _1));
94 fetcher->onError.connect(std::bind(&SegmentFetcherFixture::onError, this, _1));
jrclark240ebaad2020-04-02 11:18:00 -050095
96 fetcher->afterSegmentReceived.connect([this] (const auto&) { ++this->nAfterSegmentReceived; });
97 fetcher->afterSegmentValidated.connect([this] (const auto &) { ++this->nAfterSegmentValidated; });
98 fetcher->afterSegmentNacked.connect([this] { ++nAfterSegmentNacked; });
99 fetcher->afterSegmentTimedOut.connect([this] { ++nAfterSegmentTimedOut; });
Eric Newberrycc910cd2018-05-06 17:01:40 -0700100 }
101
Eric Newberrye345baa2018-05-23 18:17:07 -0700102 void
103 onInterest(const Interest& interest)
104 {
105 if (interest.getName().get(-1).isSegment()) {
106 if (segmentsToDropOrNack.size() > 0 &&
107 interest.getName().get(-1).toSegment() == segmentsToDropOrNack.front()) {
108 segmentsToDropOrNack.pop();
109 if (sendNackInsteadOfDropping) {
110 lp::Nack nack = makeNack(interest, nackReason);
111 face.receive(nack);
112 }
113 return;
114 }
115
116 auto data = makeDataSegment("/hello/world/version0",
117 interest.getName().get(-1).toSegment(),
118 interest.getName().get(-1).toSegment() == nSegments - 1);
119 face.receive(*data);
120
121 uniqSegmentsSent.insert(interest.getName().get(-1).toSegment());
122 if (uniqSegmentsSent.size() == nSegments) {
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500123 m_io.stop();
Eric Newberrye345baa2018-05-23 18:17:07 -0700124 }
125 }
126 else {
127 if (segmentsToDropOrNack.size() > 0 &&
128 segmentsToDropOrNack.front() == 0) {
129 segmentsToDropOrNack.pop();
130 if (sendNackInsteadOfDropping) {
131 lp::Nack nack = makeNack(interest, nackReason);
132 face.receive(nack);
133 }
134 return;
135 }
136
137 auto data = makeDataSegment("/hello/world/version0", defaultSegmentToSend, nSegments == 1);
138 face.receive(*data);
139 uniqSegmentsSent.insert(defaultSegmentToSend);
140 }
141 }
142
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700143public:
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500144 DummyClientFace face{m_io, m_keyChain};
Eric Newberrye345baa2018-05-23 18:17:07 -0700145 std::set<uint64_t> uniqSegmentsSent;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700146
Eric Newberrycc910cd2018-05-06 17:01:40 -0700147 int nErrors = 0;
Davide Pesavento5d0b0102017-10-07 13:43:16 -0400148 uint32_t lastError = 0;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700149 int nCompletions = 0;
Davide Pesavento5d0b0102017-10-07 13:43:16 -0400150 size_t dataSize = 0;
jrclark240ebaad2020-04-02 11:18:00 -0500151 size_t nAfterSegmentReceived = 0;
152 size_t nAfterSegmentValidated = 0;
153 size_t nAfterSegmentNacked = 0;
154 size_t nAfterSegmentTimedOut = 0;
155 size_t nOnInOrderData = 0;
156 size_t nOnInOrderComplete = 0;
Eric Newberrye345baa2018-05-23 18:17:07 -0700157
158 // number of segments in fetched object
159 uint64_t nSegments = 0;
160 std::queue<uint64_t> segmentsToDropOrNack;
161 bool sendNackInsteadOfDropping = false;
162 lp::NackReason nackReason = lp::NackReason::NONE;
163 // segment that is sent in response to an Interest w/o a segment component in its name
164 uint64_t defaultSegmentToSend = 0;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700165};
166
Eric Newberrye345baa2018-05-23 18:17:07 -0700167BOOST_AUTO_TEST_SUITE(Util)
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500168BOOST_FIXTURE_TEST_SUITE(TestSegmentFetcher, SegmentFetcherFixture)
Eric Newberrye345baa2018-05-23 18:17:07 -0700169
170BOOST_AUTO_TEST_CASE(InvalidOptions)
171{
172 SegmentFetcher::Options options;
173 options.mdCoef = 1.5;
174 DummyValidator acceptValidator;
175 BOOST_CHECK_THROW(SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options),
176 std::invalid_argument);
177}
178
179BOOST_AUTO_TEST_CASE(ExceedMaxTimeout)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700180{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800181 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700182 size_t nAfterSegmentTimedOut = 0;
183 SegmentFetcher::Options options;
184 options.maxTimeout = 100_ms;
185 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
186 acceptValidator, options);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700187 connectSignals(fetcher);
Davide Pesavento152ef442023-04-22 02:02:29 -0400188 fetcher->afterSegmentTimedOut.connect([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; });
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700189
Davide Pesavento0f830802018-01-16 23:58:58 -0500190 advanceClocks(1_ms);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800191 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700192
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800193 const Interest& interest = face.sentInterests[0];
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700194 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
195 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
Eric Newberry2b765f82018-06-25 14:51:13 -0700196 BOOST_CHECK_EQUAL(interest.getCanBePrefix(), true);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800197
Davide Pesavento0f830802018-01-16 23:58:58 -0500198 advanceClocks(98_ms);
Junxiao Shid5827ce2016-07-14 20:49:37 +0000199 BOOST_CHECK_EQUAL(nErrors, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700200 BOOST_CHECK_EQUAL(nCompletions, 0);
Junxiao Shid5827ce2016-07-14 20:49:37 +0000201 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Eric Newberrye345baa2018-05-23 18:17:07 -0700202 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800203
Davide Pesavento0f830802018-01-16 23:58:58 -0500204 advanceClocks(1_ms, 2);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800205 BOOST_CHECK_EQUAL(nErrors, 1);
206 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::INTEREST_TIMEOUT));
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800207 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
208 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Eric Newberrye345baa2018-05-23 18:17:07 -0700209 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 1);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700210}
211
Eric Newberrye345baa2018-05-23 18:17:07 -0700212BOOST_AUTO_TEST_CASE(BasicSingleSegment)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700213{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800214 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700215 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700216 acceptValidator);
217 connectSignals(fetcher);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500218
Davide Pesavento0f830802018-01-16 23:58:58 -0500219 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500220
Eric Newberrye345baa2018-05-23 18:17:07 -0700221 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
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
225 BOOST_CHECK_EQUAL(nErrors, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700226 BOOST_CHECK_EQUAL(nCompletions, 1);
Eric Newberrye345baa2018-05-23 18:17:07 -0700227 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
228 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
229 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
230 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700231}
232
Eric Newberrye345baa2018-05-23 18:17:07 -0700233BOOST_AUTO_TEST_CASE(ConstantCwnd)
234{
235 SegmentFetcher::Options options;
236 options.useConstantCwnd = true;
237 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700238 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
239 acceptValidator, options);
240 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700241
242 advanceClocks(10_ms);
243
244 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
245 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
246
247 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
248
249 advanceClocks(10_ms);
250
251 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
252 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
253 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 2);
254 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 1);
255 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
256
257 advanceClocks(10_ms);
258
259 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
260 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
261 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
262 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 2);
263 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
264
265 advanceClocks(10_ms);
266
267 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
268 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
269 BOOST_CHECK_EQUAL(face.sentInterests.size(), 4);
270 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 3);
271 face.receive(*makeDataSegment("/hello/world/version0", 3, false));
272
273 advanceClocks(10_ms);
274
275 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
276 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
277 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
278 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 4);
279 nackLastInterest(lp::NackReason::CONGESTION);
280
281 advanceClocks(10_ms);
282
283 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
284 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
285 BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
286 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 4);
287 face.receive(*makeDataSegment("/hello/world/version0", 4, true));
288
289 advanceClocks(10_ms);
290
291 BOOST_CHECK_EQUAL(nErrors, 0);
292 BOOST_CHECK_EQUAL(nCompletions, 1);
293 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 5);
294 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 5);
295 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 1);
296 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
297 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
298}
299
300BOOST_AUTO_TEST_CASE(BasicMultipleSegments)
Eric Newberrycc910cd2018-05-06 17:01:40 -0700301{
302 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700303 nSegments = 401;
304 sendNackInsteadOfDropping = false;
Eric Newberrye345baa2018-05-23 18:17:07 -0700305
306 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
307 acceptValidator);
Davide Pesavento152ef442023-04-22 02:02:29 -0400308 face.onSendInterest.connect(std::bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700309 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700310
311 face.processEvents(1_s);
312
313 BOOST_CHECK_EQUAL(nErrors, 0);
314 BOOST_CHECK_EQUAL(nCompletions, 1);
315 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
316 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
317 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
318 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
319 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
320}
321
jrclark240ebaad2020-04-02 11:18:00 -0500322BOOST_AUTO_TEST_CASE(BasicInOrder)
323{
324 DummyValidator acceptValidator;
325 SegmentFetcher::Options options;
326 options.inOrder = true;
327 nSegments = 401;
328 sendNackInsteadOfDropping = false;
329
330 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options);
Davide Pesavento152ef442023-04-22 02:02:29 -0400331 face.onSendInterest.connect(std::bind(&SegmentFetcherFixture::onInterest, this, _1));
jrclark240ebaad2020-04-02 11:18:00 -0500332 connectSignals(fetcher);
333
334 face.processEvents(1_s);
335
336 BOOST_CHECK_EQUAL(nErrors, 0);
337 BOOST_CHECK_EQUAL(nCompletions, 1);
338 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
339 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
340 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
341 BOOST_CHECK_EQUAL(nOnInOrderData, 401);
342 BOOST_CHECK_EQUAL(nOnInOrderComplete, 1);
343 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
344 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
345}
346
Eric Newberrye345baa2018-05-23 18:17:07 -0700347BOOST_AUTO_TEST_CASE(FirstSegmentNotZero)
348{
349 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700350 nSegments = 401;
351 sendNackInsteadOfDropping = false;
352 defaultSegmentToSend = 47;
Eric Newberrye345baa2018-05-23 18:17:07 -0700353
354 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
355 acceptValidator);
Davide Pesavento152ef442023-04-22 02:02:29 -0400356 face.onSendInterest.connect(std::bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700357 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700358
359 face.processEvents(1_s);
360
361 BOOST_CHECK_EQUAL(nErrors, 0);
362 BOOST_CHECK_EQUAL(nCompletions, 1);
363 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
364 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
365 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
366 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
367 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
368}
369
jrclark240ebaad2020-04-02 11:18:00 -0500370BOOST_AUTO_TEST_CASE(FirstSegmentNotZeroInOrder)
371{
372 DummyValidator acceptValidator;
373 SegmentFetcher::Options options;
374 options.inOrder = true;
375 nSegments = 401;
376 sendNackInsteadOfDropping = false;
377 defaultSegmentToSend = 47;
378
379 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options);
Davide Pesavento152ef442023-04-22 02:02:29 -0400380 face.onSendInterest.connect(std::bind(&SegmentFetcherFixture::onInterest, this, _1));
jrclark240ebaad2020-04-02 11:18:00 -0500381 connectSignals(fetcher);
382
383 face.processEvents(1_s);
384
385 BOOST_CHECK_EQUAL(nErrors, 0);
386 BOOST_CHECK_EQUAL(nCompletions, 1);
387 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
388 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
389 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
390 BOOST_CHECK_EQUAL(nOnInOrderData, 401);
391 BOOST_CHECK_EQUAL(nOnInOrderComplete, 1);
392 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
393 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
394}
395
Eric Newberrye345baa2018-05-23 18:17:07 -0700396BOOST_AUTO_TEST_CASE(WindowSize)
397{
398 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700399 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
400 acceptValidator);
401 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700402
403 advanceClocks(10_ms); // T+10ms
404
405 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
406 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
407 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, 0);
408 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
409 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, std::numeric_limits<double>::max());
410 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
411 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
412 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 0);
413 BOOST_CHECK_EQUAL(fetcher->m_highInterest, 0);
414 BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
415 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
416 BOOST_CHECK_EQUAL(fetcher->m_nReceived, 0);
417 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 0);
418 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), 1);
419 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
420
421 double oldCwnd = fetcher->m_cwnd;
422 double oldSsthresh = fetcher->m_ssthresh;
423 uint64_t oldNextSegmentNum = fetcher->m_nextSegmentNum;
424
425 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
426
427 advanceClocks(10_ms); //T+20ms
428
429 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
430 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
431 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
432 // +2 below because m_nextSegmentNum will be incremented in the receive callback if segment 0 is
433 // the first received
434 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 2);
435 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
436 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
437 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd + fetcher->m_options.aiStep);
438 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
439 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 14);
440 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
441 BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
442 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
443 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 1);
444 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
445 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1 + fetcher->m_cwnd);
446
447 oldCwnd = fetcher->m_cwnd;
448 oldNextSegmentNum = fetcher->m_nextSegmentNum;
449
450 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
451
452 advanceClocks(10_ms); //T+30ms
453
454 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
455 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
456 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
457 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
458 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
459 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
460 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
461 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
462 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 28);
463 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
464 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
465 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
466 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 2);
467 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
468 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2 + fetcher->m_cwnd);
469
470 oldCwnd = fetcher->m_cwnd;
471 oldNextSegmentNum = fetcher->m_nextSegmentNum;
472
473 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
474
475 advanceClocks(10_ms); //T+40ms
476
477 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
478 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
479 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
480 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
481 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
482 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
483 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
484 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
485 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
486 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
487 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
488 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
489 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
490 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
491 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3 + fetcher->m_cwnd);
492
493 oldCwnd = fetcher->m_cwnd;
494 oldSsthresh = fetcher->m_ssthresh;
495 oldNextSegmentNum = fetcher->m_nextSegmentNum;
496 size_t oldSentInterestsSize = face.sentInterests.size();
497
498 nackLastInterest(lp::NackReason::CONGESTION); //T+50ms
499
500 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 20_ms);
501 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
502 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
503 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
504 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
505 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
506 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
507 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
508 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
509 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
510 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
511 BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
512 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
513 // The Nacked segment will remain in pendingSegments, so the size of the structure doesn't change
514 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
515 BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
516
517 advanceClocks(10_ms); //T+60ms
518
519 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 30_ms);
520 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
521 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
522 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
523 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
524 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
525 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
526 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
527 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
528 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
529 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
530 BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
531 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
532 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
533 BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
534
535 // Properly end test case
536 lp::Nack nack = makeNack(face.sentInterests[face.sentInterests.size() - 2], lp::NackReason::NO_ROUTE);
537 face.receive(nack);
538 advanceClocks(10_ms); //T+70ms
539
540 BOOST_CHECK_EQUAL(nErrors, 1);
541 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::NACK_ERROR));
542 BOOST_CHECK_EQUAL(nCompletions, 0);
543}
544
545BOOST_AUTO_TEST_CASE(MissingSegmentNum)
546{
547 DummyValidator acceptValidator;
548 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700549 acceptValidator);
550 connectSignals(fetcher);
551
552 advanceClocks(10_ms);
553
554 const uint8_t buffer[] = "Hello, world!";
555 auto data = makeData("/hello/world/version0/no-segment");
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +0000556 data->setFreshnessPeriod(1_s);
Davide Pesaventoa3d809e2022-02-06 11:55:02 -0500557 data->setContent(buffer);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700558
559 face.receive(*data);
560 advanceClocks(10_ms);
561
562 BOOST_CHECK_EQUAL(nErrors, 1);
563 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::DATA_HAS_NO_SEGMENT));
564 BOOST_CHECK_EQUAL(nCompletions, 0);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500565}
566
Eric Newberrye345baa2018-05-23 18:17:07 -0700567BOOST_AUTO_TEST_CASE(MoreSegmentsThanNSegments)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500568{
Eric Newberrycc910cd2018-05-06 17:01:40 -0700569 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700570 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700571 acceptValidator);
572 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700573
Davide Pesavento0f830802018-01-16 23:58:58 -0500574 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500575
Eric Newberrye345baa2018-05-23 18:17:07 -0700576 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
Davide Pesavento0f830802018-01-16 23:58:58 -0500577 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500578
Eric Newberrye345baa2018-05-23 18:17:07 -0700579 BOOST_CHECK_EQUAL(nErrors, 0);
580 BOOST_CHECK_EQUAL(nCompletions, 0);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500581
Eric Newberrye345baa2018-05-23 18:17:07 -0700582 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
Davide Pesavento0f830802018-01-16 23:58:58 -0500583 advanceClocks(10_ms);
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500584
Eric Newberrye345baa2018-05-23 18:17:07 -0700585 BOOST_CHECK_EQUAL(nErrors, 0);
586 BOOST_CHECK_EQUAL(nCompletions, 0);
587
588 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
589 advanceClocks(10_ms);
590
591 BOOST_CHECK_EQUAL(nErrors, 0);
592 BOOST_CHECK_EQUAL(nCompletions, 0);
593
594 face.receive(*makeDataSegment("/hello/world/version0", 3, false));
595 advanceClocks(10_ms);
596
597 BOOST_CHECK_EQUAL(nErrors, 0);
598 BOOST_CHECK_EQUAL(nCompletions, 0);
599
600 auto data4 = makeDataSegment("/hello/world/version0", 4, false);
601 data4->setFinalBlock(name::Component::fromSegment(2));
602 face.receive(*data4);
603 advanceClocks(10_ms);
604
605 BOOST_CHECK_EQUAL(nErrors, 0);
606 BOOST_CHECK_EQUAL(nCompletions, 1);
607 BOOST_CHECK_EQUAL(dataSize, 14 * 3);
608 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 5);
609 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 5);
610 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
611 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500612}
613
Eric Newberrye345baa2018-05-23 18:17:07 -0700614BOOST_AUTO_TEST_CASE(DuplicateNack)
615{
616 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700617 nSegments = 401;
618 segmentsToDropOrNack.push(0);
619 segmentsToDropOrNack.push(200);
620 sendNackInsteadOfDropping = true;
621 nackReason = lp::NackReason::DUPLICATE;
Eric Newberrye345baa2018-05-23 18:17:07 -0700622
623 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
624 acceptValidator);
Davide Pesavento152ef442023-04-22 02:02:29 -0400625 face.onSendInterest.connect(std::bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700626 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700627
628 face.processEvents(1_s);
629
630 BOOST_CHECK_EQUAL(nErrors, 0);
631 BOOST_CHECK_EQUAL(nCompletions, 1);
632 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
633 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
634 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
635 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
636 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
637}
638
639BOOST_AUTO_TEST_CASE(CongestionNack)
640{
641 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700642 nSegments = 401;
643 segmentsToDropOrNack.push(0);
644 segmentsToDropOrNack.push(200);
645 sendNackInsteadOfDropping = true;
646 nackReason = lp::NackReason::CONGESTION;
Eric Newberrye345baa2018-05-23 18:17:07 -0700647
648 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
649 acceptValidator);
Davide Pesavento152ef442023-04-22 02:02:29 -0400650 face.onSendInterest.connect(std::bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700651 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700652
653 face.processEvents(1_s);
654
655 BOOST_CHECK_EQUAL(nErrors, 0);
656 BOOST_CHECK_EQUAL(nCompletions, 1);
657 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
658 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
659 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
660 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
661 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
662}
663
664BOOST_AUTO_TEST_CASE(OtherNackReason)
665{
666 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700667 segmentsToDropOrNack.push(0);
668 sendNackInsteadOfDropping = true;
669 nackReason = lp::NackReason::NO_ROUTE;
Davide Pesavento152ef442023-04-22 02:02:29 -0400670 face.onSendInterest.connect(std::bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700671
672 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
673 acceptValidator);
674 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700675
676 face.processEvents(1_s);
677
678 BOOST_CHECK_EQUAL(nErrors, 1);
679 BOOST_CHECK_EQUAL(nCompletions, 0);
680 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
681 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
682 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 1);
683 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
684 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
685}
686
687BOOST_AUTO_TEST_CASE(ValidationFailure)
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000688{
689 DummyValidator validator;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700690 validator.getPolicy().setResultCallback([] (const Name& name) {
jrclark240ebaad2020-04-02 11:18:00 -0500691 return name.at(-1).toSegment() % 2 == 0;
692 });
Eric Newberrye345baa2018-05-23 18:17:07 -0700693 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700694 validator);
695 connectSignals(fetcher);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000696
697 auto data1 = makeDataSegment("/hello/world", 0, false);
698 auto data2 = makeDataSegment("/hello/world", 1, true);
699
Davide Pesavento0f830802018-01-16 23:58:58 -0500700 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000701
Eric Newberrye345baa2018-05-23 18:17:07 -0700702 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
703
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000704 face.receive(*data1);
705
Davide Pesavento0f830802018-01-16 23:58:58 -0500706 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000707
Eric Newberrye345baa2018-05-23 18:17:07 -0700708 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
709
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000710 face.receive(*data2);
711
Davide Pesavento0f830802018-01-16 23:58:58 -0500712 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000713
Eric Newberrye345baa2018-05-23 18:17:07 -0700714 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 200_ms);
jrclark240ebaad2020-04-02 11:18:00 -0500715 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 2);
716 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000717 BOOST_CHECK_EQUAL(nErrors, 1);
718}
719
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500720BOOST_AUTO_TEST_CASE(Stop)
721{
722 DummyValidator acceptValidator;
723
724 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
725 connectSignals(fetcher);
726 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
727
728 fetcher->stop();
729 advanceClocks(10_ms);
730 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
731
732 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
733 advanceClocks(10_ms);
734 BOOST_CHECK_EQUAL(nErrors, 0);
735 BOOST_CHECK_EQUAL(nCompletions, 0);
736
737 fetcher.reset();
738 BOOST_CHECK_EQUAL(fetcher.use_count(), 0);
739
740 // Make sure we can re-assign w/o any complains from ASan
741 fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
742 connectSignals(fetcher);
743 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
744
745 advanceClocks(10_ms);
746
747 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
748
749 advanceClocks(10_ms);
750 BOOST_CHECK_EQUAL(nErrors, 0);
751 BOOST_CHECK_EQUAL(nCompletions, 1);
752 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
753
754 // Stop from callback
755 bool fetcherStopped = false;
756
757 fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
jrclark240ebaad2020-04-02 11:18:00 -0500758 fetcher->afterSegmentReceived.connect([&fetcher, &fetcherStopped] (const Data&) {
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500759 fetcherStopped = true;
760 fetcher->stop();
761 });
762 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
763
764 advanceClocks(10_ms);
765
766 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
767
768 advanceClocks(10_ms);
769 BOOST_CHECK(fetcherStopped);
770 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
771}
772
773BOOST_AUTO_TEST_CASE(Lifetime)
774{
775 // BasicSingleSegment, but with scoped fetcher
776
777 DummyValidator acceptValidator;
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500778
779 weak_ptr<SegmentFetcher> weakFetcher;
780 {
781 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
782 weakFetcher = fetcher;
783 connectSignals(fetcher);
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500784 }
785
786 advanceClocks(10_ms);
787 BOOST_CHECK_EQUAL(weakFetcher.expired(), false);
788
789 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
790
791 advanceClocks(10_ms);
792
793 BOOST_CHECK_EQUAL(nErrors, 0);
794 BOOST_CHECK_EQUAL(nCompletions, 1);
795 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
796 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
797 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
798 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
799 BOOST_CHECK_EQUAL(weakFetcher.expired(), true);
800}
801
802BOOST_AUTO_TEST_CASE(OutOfScopeTimeout)
803{
804 DummyValidator acceptValidator;
805 SegmentFetcher::Options options;
806 options.maxTimeout = 3000_ms;
807
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500808 weak_ptr<SegmentFetcher> weakFetcher;
809 {
810 auto fetcher = SegmentFetcher::start(face, Interest("/localhost/nfd/faces/list"),
811 acceptValidator, options);
812 weakFetcher = fetcher;
813 connectSignals(fetcher);
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500814 }
815
816 advanceClocks(500_ms, 7);
817 BOOST_CHECK_EQUAL(weakFetcher.expired(), true);
818
819 BOOST_CHECK_EQUAL(nErrors, 1);
820 BOOST_CHECK_EQUAL(nCompletions, 0);
821 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
822 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
823 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
824 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 2);
825}
826
Davide Pesavento0c526032024-01-31 21:14:01 -0500827BOOST_AUTO_TEST_CASE(UncanceledPendingInterest,
828 * ut::description("test for bug #4770"))
Ashlesh Gawandeebe156c2018-11-12 16:27:49 -0600829{
830 DummyValidator acceptValidator;
831 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
832 connectSignals(fetcher);
833
834 // Fetcher will send the first interest immediately
835 // and the second interest after 1 second by default
836 advanceClocks(1100_ms);
837
838 // Face will give data to the fetcher twice if the first interest is not canceled.
839 // isFinal=false to keep fetcher alive so that it can receive the second data.
840 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
841
842 advanceClocks(1100_ms);
843
844 face.receive(*makeDataSegment("/hello/world/version0", 1, true));
845
846 BOOST_CHECK_EQUAL(nErrors, 0);
847 BOOST_CHECK_EQUAL(nCompletions, 1);
848}
849
Junxiao Shid5827ce2016-07-14 20:49:37 +0000850BOOST_AUTO_TEST_SUITE_END() // TestSegmentFetcher
851BOOST_AUTO_TEST_SUITE_END() // Util
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700852
Davide Pesavento47ce2ee2023-05-09 01:33:33 -0400853} // namespace ndn::tests