blob: 126dfe53d77ecde28c1d551fd057bb203b508ff4 [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 {
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050042 auto data = makeData(Name(baseName).appendSegment(segment));
Tianyuan Yu947a3992023-07-24 12:28:40 -070043 data->setContent("Hello, world!\0"sv);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050044 data->setFreshnessPeriod(1_s);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050045 if (isFinal) {
Junxiao Shiebfe4a22018-04-01 23:53:40 +000046 data->setFinalBlock(data->getName()[-1]);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050047 }
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050048 return data;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070049 }
50
51 void
52 onError(uint32_t errorCode)
53 {
54 ++nErrors;
55 lastError = errorCode;
56 }
57
58 void
Eric Newberrye345baa2018-05-23 18:17:07 -070059 onComplete(ConstBufferPtr data)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070060 {
Eric Newberrycc910cd2018-05-06 17:01:40 -070061 ++nCompletions;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070062 dataSize = data->size();
jrclark240ebaad2020-04-02 11:18:00 -050063 }
64
65 void
66 onInOrderComplete()
67 {
68 ++nCompletions;
69 ++nOnInOrderComplete;
70 }
71
72 void
73 onInOrderData(ConstBufferPtr data)
74 {
75 ++nOnInOrderData;
76 dataSize += data->size();
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070077 }
78
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050079 void
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050080 nackLastInterest(lp::NackReason reason)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050081 {
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080082 const Interest& lastInterest = face.sentInterests.back();
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050083 face.receive(makeNack(lastInterest, reason));
Davide Pesavento0f830802018-01-16 23:58:58 -050084 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050085 }
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070086
Eric Newberrycc910cd2018-05-06 17:01:40 -070087 void
Ashlesh Gawande679dbb02018-08-21 11:43:21 -050088 connectSignals(const shared_ptr<SegmentFetcher>& fetcher)
Eric Newberrycc910cd2018-05-06 17:01:40 -070089 {
Davide Pesavento152ef442023-04-22 02:02:29 -040090 fetcher->onInOrderData.connect(std::bind(&SegmentFetcherFixture::onInOrderData, this, _1));
91 fetcher->onInOrderComplete.connect(std::bind(&SegmentFetcherFixture::onInOrderComplete, this));
92 fetcher->onComplete.connect(std::bind(&SegmentFetcherFixture::onComplete, this, _1));
93 fetcher->onError.connect(std::bind(&SegmentFetcherFixture::onError, this, _1));
jrclark240ebaad2020-04-02 11:18:00 -050094
95 fetcher->afterSegmentReceived.connect([this] (const auto&) { ++this->nAfterSegmentReceived; });
96 fetcher->afterSegmentValidated.connect([this] (const auto &) { ++this->nAfterSegmentValidated; });
97 fetcher->afterSegmentNacked.connect([this] { ++nAfterSegmentNacked; });
98 fetcher->afterSegmentTimedOut.connect([this] { ++nAfterSegmentTimedOut; });
Eric Newberrycc910cd2018-05-06 17:01:40 -070099 }
100
Eric Newberrye345baa2018-05-23 18:17:07 -0700101 void
102 onInterest(const Interest& interest)
103 {
104 if (interest.getName().get(-1).isSegment()) {
105 if (segmentsToDropOrNack.size() > 0 &&
106 interest.getName().get(-1).toSegment() == segmentsToDropOrNack.front()) {
107 segmentsToDropOrNack.pop();
108 if (sendNackInsteadOfDropping) {
109 lp::Nack nack = makeNack(interest, nackReason);
110 face.receive(nack);
111 }
112 return;
113 }
114
115 auto data = makeDataSegment("/hello/world/version0",
116 interest.getName().get(-1).toSegment(),
117 interest.getName().get(-1).toSegment() == nSegments - 1);
118 face.receive(*data);
119
120 uniqSegmentsSent.insert(interest.getName().get(-1).toSegment());
121 if (uniqSegmentsSent.size() == nSegments) {
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500122 m_io.stop();
Eric Newberrye345baa2018-05-23 18:17:07 -0700123 }
124 }
125 else {
126 if (segmentsToDropOrNack.size() > 0 &&
127 segmentsToDropOrNack.front() == 0) {
128 segmentsToDropOrNack.pop();
129 if (sendNackInsteadOfDropping) {
130 lp::Nack nack = makeNack(interest, nackReason);
131 face.receive(nack);
132 }
133 return;
134 }
135
136 auto data = makeDataSegment("/hello/world/version0", defaultSegmentToSend, nSegments == 1);
137 face.receive(*data);
138 uniqSegmentsSent.insert(defaultSegmentToSend);
139 }
140 }
141
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700142public:
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500143 DummyClientFace face{m_io, m_keyChain};
Eric Newberrye345baa2018-05-23 18:17:07 -0700144 std::set<uint64_t> uniqSegmentsSent;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700145
Eric Newberrycc910cd2018-05-06 17:01:40 -0700146 int nErrors = 0;
Davide Pesavento5d0b0102017-10-07 13:43:16 -0400147 uint32_t lastError = 0;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700148 int nCompletions = 0;
Davide Pesavento5d0b0102017-10-07 13:43:16 -0400149 size_t dataSize = 0;
jrclark240ebaad2020-04-02 11:18:00 -0500150 size_t nAfterSegmentReceived = 0;
151 size_t nAfterSegmentValidated = 0;
152 size_t nAfterSegmentNacked = 0;
153 size_t nAfterSegmentTimedOut = 0;
154 size_t nOnInOrderData = 0;
155 size_t nOnInOrderComplete = 0;
Eric Newberrye345baa2018-05-23 18:17:07 -0700156
157 // number of segments in fetched object
158 uint64_t nSegments = 0;
159 std::queue<uint64_t> segmentsToDropOrNack;
160 bool sendNackInsteadOfDropping = false;
161 lp::NackReason nackReason = lp::NackReason::NONE;
162 // segment that is sent in response to an Interest w/o a segment component in its name
163 uint64_t defaultSegmentToSend = 0;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700164};
165
Eric Newberrye345baa2018-05-23 18:17:07 -0700166BOOST_AUTO_TEST_SUITE(Util)
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500167BOOST_FIXTURE_TEST_SUITE(TestSegmentFetcher, SegmentFetcherFixture)
Eric Newberrye345baa2018-05-23 18:17:07 -0700168
169BOOST_AUTO_TEST_CASE(InvalidOptions)
170{
171 SegmentFetcher::Options options;
172 options.mdCoef = 1.5;
173 DummyValidator acceptValidator;
174 BOOST_CHECK_THROW(SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options),
175 std::invalid_argument);
176}
177
Tianyuan Yu947a3992023-07-24 12:28:40 -0700178BOOST_AUTO_TEST_CASE(BasicSingleSegment)
179{
180 DummyValidator acceptValidator;
181 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
182 acceptValidator);
183 connectSignals(fetcher);
184
185 advanceClocks(10_ms);
186 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
187
188 const Interest& interest = face.sentInterests[0];
189 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
190 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
191 BOOST_CHECK_EQUAL(interest.getCanBePrefix(), true);
192
193 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
194 advanceClocks(10_ms);
195
196 BOOST_CHECK_EQUAL(nErrors, 0);
197 BOOST_CHECK_EQUAL(nCompletions, 1);
198 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
199 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
200 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
201 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
202}
203
Eric Newberrye345baa2018-05-23 18:17:07 -0700204BOOST_AUTO_TEST_CASE(ExceedMaxTimeout)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700205{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800206 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700207 size_t nAfterSegmentTimedOut = 0;
208 SegmentFetcher::Options options;
209 options.maxTimeout = 100_ms;
210 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
211 acceptValidator, options);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700212 connectSignals(fetcher);
Davide Pesavento152ef442023-04-22 02:02:29 -0400213 fetcher->afterSegmentTimedOut.connect([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; });
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700214
Davide Pesavento0f830802018-01-16 23:58:58 -0500215 advanceClocks(1_ms);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800216 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700217
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800218 const Interest& interest = face.sentInterests[0];
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700219 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
220 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
Eric Newberry2b765f82018-06-25 14:51:13 -0700221 BOOST_CHECK_EQUAL(interest.getCanBePrefix(), true);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800222
Davide Pesavento0f830802018-01-16 23:58:58 -0500223 advanceClocks(98_ms);
Junxiao Shid5827ce2016-07-14 20:49:37 +0000224 BOOST_CHECK_EQUAL(nErrors, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700225 BOOST_CHECK_EQUAL(nCompletions, 0);
Junxiao Shid5827ce2016-07-14 20:49:37 +0000226 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Eric Newberrye345baa2018-05-23 18:17:07 -0700227 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800228
Davide Pesavento0f830802018-01-16 23:58:58 -0500229 advanceClocks(1_ms, 2);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800230 BOOST_CHECK_EQUAL(nErrors, 1);
231 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::INTEREST_TIMEOUT));
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800232 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
233 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Eric Newberrye345baa2018-05-23 18:17:07 -0700234 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 1);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -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));
Eric Newberrye345baa2018-05-23 18:17:07 -0700252 advanceClocks(10_ms);
253
254 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
255 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
256 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 2);
257 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 1);
Eric Newberrye345baa2018-05-23 18:17:07 -0700258
Tianyuan Yu947a3992023-07-24 12:28:40 -0700259 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
Eric Newberrye345baa2018-05-23 18:17:07 -0700260 advanceClocks(10_ms);
261
262 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
263 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
264 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
265 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 2);
Eric Newberrye345baa2018-05-23 18:17:07 -0700266
Tianyuan Yu947a3992023-07-24 12:28:40 -0700267 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
Eric Newberrye345baa2018-05-23 18:17:07 -0700268 advanceClocks(10_ms);
269
270 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
271 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
272 BOOST_CHECK_EQUAL(face.sentInterests.size(), 4);
273 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 3);
Eric Newberrye345baa2018-05-23 18:17:07 -0700274
Tianyuan Yu947a3992023-07-24 12:28:40 -0700275 face.receive(*makeDataSegment("/hello/world/version0", 3, false));
Eric Newberrye345baa2018-05-23 18:17:07 -0700276 advanceClocks(10_ms);
277
278 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
279 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
280 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
281 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 4);
282 nackLastInterest(lp::NackReason::CONGESTION);
283
284 advanceClocks(10_ms);
285
286 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
287 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
288 BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
289 BOOST_CHECK_EQUAL(face.sentInterests.back().getName().get(-1).toSegment(), 4);
Eric Newberrye345baa2018-05-23 18:17:07 -0700290
Tianyuan Yu947a3992023-07-24 12:28:40 -0700291 face.receive(*makeDataSegment("/hello/world/version0", 4, true));
Eric Newberrye345baa2018-05-23 18:17:07 -0700292 advanceClocks(10_ms);
293
294 BOOST_CHECK_EQUAL(nErrors, 0);
295 BOOST_CHECK_EQUAL(nCompletions, 1);
296 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 5);
297 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 5);
298 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 1);
299 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
300 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
301}
302
303BOOST_AUTO_TEST_CASE(BasicMultipleSegments)
Eric Newberrycc910cd2018-05-06 17:01:40 -0700304{
305 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700306 nSegments = 401;
307 sendNackInsteadOfDropping = false;
Eric Newberrye345baa2018-05-23 18:17:07 -0700308
Tianyuan Yu947a3992023-07-24 12:28:40 -0700309 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
Davide Pesavento152ef442023-04-22 02:02:29 -0400310 face.onSendInterest.connect(std::bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700311 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700312
313 face.processEvents(1_s);
Tianyuan Yu947a3992023-07-24 12:28:40 -0700314 BOOST_REQUIRE_GE(face.sentInterests.size(), 2);
315
316 BOOST_CHECK_EQUAL(face.sentInterests[0].getName(), "/hello/world");
317 BOOST_CHECK_EQUAL(face.sentInterests[0].getMustBeFresh(), true);
318 BOOST_CHECK_EQUAL(face.sentInterests[0].getCanBePrefix(), true);
319 BOOST_CHECK_EQUAL(face.sentInterests[1].getName().size(), 4);
320 BOOST_CHECK(face.sentInterests[1].getName().at(-1).isSegment());
321 BOOST_CHECK_EQUAL(face.sentInterests[1].getMustBeFresh(), false);
322 BOOST_CHECK_EQUAL(face.sentInterests[1].getCanBePrefix(), false);
Eric Newberrye345baa2018-05-23 18:17:07 -0700323
324 BOOST_CHECK_EQUAL(nErrors, 0);
325 BOOST_CHECK_EQUAL(nCompletions, 1);
326 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
327 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
328 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
329 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
330 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
331}
332
jrclark240ebaad2020-04-02 11:18:00 -0500333BOOST_AUTO_TEST_CASE(BasicInOrder)
334{
335 DummyValidator acceptValidator;
336 SegmentFetcher::Options options;
337 options.inOrder = true;
338 nSegments = 401;
339 sendNackInsteadOfDropping = false;
340
341 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options);
Davide Pesavento152ef442023-04-22 02:02:29 -0400342 face.onSendInterest.connect(std::bind(&SegmentFetcherFixture::onInterest, this, _1));
jrclark240ebaad2020-04-02 11:18:00 -0500343 connectSignals(fetcher);
344
345 face.processEvents(1_s);
346
347 BOOST_CHECK_EQUAL(nErrors, 0);
348 BOOST_CHECK_EQUAL(nCompletions, 1);
349 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
350 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
351 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
352 BOOST_CHECK_EQUAL(nOnInOrderData, 401);
353 BOOST_CHECK_EQUAL(nOnInOrderComplete, 1);
354 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
355 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
356}
357
Tianyuan Yu947a3992023-07-24 12:28:40 -0700358BOOST_AUTO_TEST_CASE(VersionedPrefix)
359{
360 DummyValidator acceptValidator;
361 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world/v=42"), acceptValidator);
362 connectSignals(fetcher);
363
364 advanceClocks(1_ms);
365 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
366
367 const Interest& interest = face.sentInterests[0];
368 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world/v=42");
369 BOOST_CHECK_EQUAL(interest.getCanBePrefix(), true);
370 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), false);
371
372 face.receive(*makeDataSegment("/hello/world/v=42", 0, true));
373 advanceClocks(10_ms);
374
375 BOOST_CHECK_EQUAL(nErrors, 0);
376 BOOST_CHECK_EQUAL(nCompletions, 1);
377 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
378 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
379 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
380 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
381}
382
383BOOST_AUTO_TEST_CASE(ProbeLatestVersionDisabled)
384{
385 DummyValidator acceptValidator;
386 SegmentFetcher::Options options;
387 options.probeLatestVersion = false;
388 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options);
389 connectSignals(fetcher);
390
391 advanceClocks(1_ms);
392 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
393
394 const Interest& interest = face.sentInterests[0];
395 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
396 BOOST_CHECK_EQUAL(interest.getCanBePrefix(), true);
397 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), false);
398
399 face.receive(*makeDataSegment("/hello/world/v=0", 0, true));
400 advanceClocks(10_ms);
401
402 BOOST_CHECK_EQUAL(nErrors, 0);
403 BOOST_CHECK_EQUAL(nCompletions, 1);
404 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
405 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
406 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
407 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
408}
409
Eric Newberrye345baa2018-05-23 18:17:07 -0700410BOOST_AUTO_TEST_CASE(FirstSegmentNotZero)
411{
412 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700413 nSegments = 401;
414 sendNackInsteadOfDropping = false;
415 defaultSegmentToSend = 47;
Eric Newberrye345baa2018-05-23 18:17:07 -0700416
417 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
418 acceptValidator);
Davide Pesavento152ef442023-04-22 02:02:29 -0400419 face.onSendInterest.connect(std::bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700420 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700421
422 face.processEvents(1_s);
423
424 BOOST_CHECK_EQUAL(nErrors, 0);
425 BOOST_CHECK_EQUAL(nCompletions, 1);
426 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
427 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
428 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
429 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
430 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
431}
432
jrclark240ebaad2020-04-02 11:18:00 -0500433BOOST_AUTO_TEST_CASE(FirstSegmentNotZeroInOrder)
434{
435 DummyValidator acceptValidator;
436 SegmentFetcher::Options options;
437 options.inOrder = true;
438 nSegments = 401;
439 sendNackInsteadOfDropping = false;
440 defaultSegmentToSend = 47;
441
442 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options);
Davide Pesavento152ef442023-04-22 02:02:29 -0400443 face.onSendInterest.connect(std::bind(&SegmentFetcherFixture::onInterest, this, _1));
jrclark240ebaad2020-04-02 11:18:00 -0500444 connectSignals(fetcher);
445
446 face.processEvents(1_s);
447
448 BOOST_CHECK_EQUAL(nErrors, 0);
449 BOOST_CHECK_EQUAL(nCompletions, 1);
450 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
451 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
452 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
453 BOOST_CHECK_EQUAL(nOnInOrderData, 401);
454 BOOST_CHECK_EQUAL(nOnInOrderComplete, 1);
455 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
456 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
457}
458
Eric Newberrye345baa2018-05-23 18:17:07 -0700459BOOST_AUTO_TEST_CASE(WindowSize)
460{
461 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700462 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
463 acceptValidator);
464 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700465
466 advanceClocks(10_ms); // T+10ms
467
468 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
469 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
470 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, 0);
471 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
472 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, std::numeric_limits<double>::max());
473 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
474 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
475 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 0);
476 BOOST_CHECK_EQUAL(fetcher->m_highInterest, 0);
477 BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
478 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
479 BOOST_CHECK_EQUAL(fetcher->m_nReceived, 0);
480 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 0);
481 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), 1);
482 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
483
484 double oldCwnd = fetcher->m_cwnd;
485 double oldSsthresh = fetcher->m_ssthresh;
486 uint64_t oldNextSegmentNum = fetcher->m_nextSegmentNum;
487
488 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
489
490 advanceClocks(10_ms); //T+20ms
491
492 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
493 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
494 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
495 // +2 below because m_nextSegmentNum will be incremented in the receive callback if segment 0 is
496 // the first received
497 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 2);
498 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
499 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
500 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd + fetcher->m_options.aiStep);
501 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
502 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 14);
503 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
504 BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
505 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
506 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 1);
507 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
508 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1 + fetcher->m_cwnd);
509
510 oldCwnd = fetcher->m_cwnd;
511 oldNextSegmentNum = fetcher->m_nextSegmentNum;
512
513 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
514
515 advanceClocks(10_ms); //T+30ms
516
517 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
518 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
519 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
520 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
521 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
522 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
523 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
524 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
525 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 28);
526 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
527 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
528 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
529 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 2);
530 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
531 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2 + fetcher->m_cwnd);
532
533 oldCwnd = fetcher->m_cwnd;
534 oldNextSegmentNum = fetcher->m_nextSegmentNum;
535
536 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
537
538 advanceClocks(10_ms); //T+40ms
539
540 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
541 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
542 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
543 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
544 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
545 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
546 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
547 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
548 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
549 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
550 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
551 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
552 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
553 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
554 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3 + fetcher->m_cwnd);
555
556 oldCwnd = fetcher->m_cwnd;
557 oldSsthresh = fetcher->m_ssthresh;
558 oldNextSegmentNum = fetcher->m_nextSegmentNum;
559 size_t oldSentInterestsSize = face.sentInterests.size();
560
561 nackLastInterest(lp::NackReason::CONGESTION); //T+50ms
562
563 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 20_ms);
564 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
565 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
566 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
567 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
568 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
569 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
570 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
571 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
572 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
573 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
574 BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
575 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
576 // The Nacked segment will remain in pendingSegments, so the size of the structure doesn't change
577 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
578 BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
579
580 advanceClocks(10_ms); //T+60ms
581
582 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 30_ms);
583 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
584 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
585 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
586 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
587 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
588 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
589 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
590 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
591 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
592 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
593 BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
594 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
595 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
596 BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
597
598 // Properly end test case
599 lp::Nack nack = makeNack(face.sentInterests[face.sentInterests.size() - 2], lp::NackReason::NO_ROUTE);
600 face.receive(nack);
601 advanceClocks(10_ms); //T+70ms
602
603 BOOST_CHECK_EQUAL(nErrors, 1);
604 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::NACK_ERROR));
605 BOOST_CHECK_EQUAL(nCompletions, 0);
606}
607
608BOOST_AUTO_TEST_CASE(MissingSegmentNum)
609{
610 DummyValidator acceptValidator;
611 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700612 acceptValidator);
613 connectSignals(fetcher);
614
615 advanceClocks(10_ms);
616
617 const uint8_t buffer[] = "Hello, world!";
618 auto data = makeData("/hello/world/version0/no-segment");
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +0000619 data->setFreshnessPeriod(1_s);
Davide Pesaventoa3d809e2022-02-06 11:55:02 -0500620 data->setContent(buffer);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700621
622 face.receive(*data);
623 advanceClocks(10_ms);
624
625 BOOST_CHECK_EQUAL(nErrors, 1);
626 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::DATA_HAS_NO_SEGMENT));
627 BOOST_CHECK_EQUAL(nCompletions, 0);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500628}
629
Eric Newberrye345baa2018-05-23 18:17:07 -0700630BOOST_AUTO_TEST_CASE(MoreSegmentsThanNSegments)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500631{
Eric Newberrycc910cd2018-05-06 17:01:40 -0700632 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700633 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700634 acceptValidator);
635 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700636
Davide Pesavento0f830802018-01-16 23:58:58 -0500637 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500638
Eric Newberrye345baa2018-05-23 18:17:07 -0700639 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
Davide Pesavento0f830802018-01-16 23:58:58 -0500640 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500641
Eric Newberrye345baa2018-05-23 18:17:07 -0700642 BOOST_CHECK_EQUAL(nErrors, 0);
643 BOOST_CHECK_EQUAL(nCompletions, 0);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500644
Eric Newberrye345baa2018-05-23 18:17:07 -0700645 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
Davide Pesavento0f830802018-01-16 23:58:58 -0500646 advanceClocks(10_ms);
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500647
Eric Newberrye345baa2018-05-23 18:17:07 -0700648 BOOST_CHECK_EQUAL(nErrors, 0);
649 BOOST_CHECK_EQUAL(nCompletions, 0);
650
651 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
652 advanceClocks(10_ms);
653
654 BOOST_CHECK_EQUAL(nErrors, 0);
655 BOOST_CHECK_EQUAL(nCompletions, 0);
656
657 face.receive(*makeDataSegment("/hello/world/version0", 3, false));
658 advanceClocks(10_ms);
659
660 BOOST_CHECK_EQUAL(nErrors, 0);
661 BOOST_CHECK_EQUAL(nCompletions, 0);
662
663 auto data4 = makeDataSegment("/hello/world/version0", 4, false);
664 data4->setFinalBlock(name::Component::fromSegment(2));
665 face.receive(*data4);
666 advanceClocks(10_ms);
667
668 BOOST_CHECK_EQUAL(nErrors, 0);
669 BOOST_CHECK_EQUAL(nCompletions, 1);
670 BOOST_CHECK_EQUAL(dataSize, 14 * 3);
671 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 5);
672 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 5);
673 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
674 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500675}
676
Eric Newberrye345baa2018-05-23 18:17:07 -0700677BOOST_AUTO_TEST_CASE(DuplicateNack)
678{
679 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700680 nSegments = 401;
681 segmentsToDropOrNack.push(0);
682 segmentsToDropOrNack.push(200);
683 sendNackInsteadOfDropping = true;
684 nackReason = lp::NackReason::DUPLICATE;
Eric Newberrye345baa2018-05-23 18:17:07 -0700685
Tianyuan Yu947a3992023-07-24 12:28:40 -0700686 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
Davide Pesavento152ef442023-04-22 02:02:29 -0400687 face.onSendInterest.connect(std::bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700688 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700689
690 face.processEvents(1_s);
691
692 BOOST_CHECK_EQUAL(nErrors, 0);
693 BOOST_CHECK_EQUAL(nCompletions, 1);
694 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
695 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
696 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
697 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
698 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
699}
700
701BOOST_AUTO_TEST_CASE(CongestionNack)
702{
703 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700704 nSegments = 401;
705 segmentsToDropOrNack.push(0);
706 segmentsToDropOrNack.push(200);
707 sendNackInsteadOfDropping = true;
708 nackReason = lp::NackReason::CONGESTION;
Eric Newberrye345baa2018-05-23 18:17:07 -0700709
Tianyuan Yu947a3992023-07-24 12:28:40 -0700710 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
Davide Pesavento152ef442023-04-22 02:02:29 -0400711 face.onSendInterest.connect(std::bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700712 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700713
714 face.processEvents(1_s);
715
716 BOOST_CHECK_EQUAL(nErrors, 0);
717 BOOST_CHECK_EQUAL(nCompletions, 1);
718 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
719 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
720 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
721 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
722 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
723}
724
725BOOST_AUTO_TEST_CASE(OtherNackReason)
726{
727 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700728 segmentsToDropOrNack.push(0);
729 sendNackInsteadOfDropping = true;
730 nackReason = lp::NackReason::NO_ROUTE;
Davide Pesavento152ef442023-04-22 02:02:29 -0400731 face.onSendInterest.connect(std::bind(&SegmentFetcherFixture::onInterest, this, _1));
Eric Newberrye345baa2018-05-23 18:17:07 -0700732
Tianyuan Yu947a3992023-07-24 12:28:40 -0700733 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
Eric Newberrye345baa2018-05-23 18:17:07 -0700734 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700735
736 face.processEvents(1_s);
737
738 BOOST_CHECK_EQUAL(nErrors, 1);
739 BOOST_CHECK_EQUAL(nCompletions, 0);
740 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
741 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
742 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 1);
743 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
744 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
745}
746
747BOOST_AUTO_TEST_CASE(ValidationFailure)
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000748{
749 DummyValidator validator;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700750 validator.getPolicy().setResultCallback([] (const Name& name) {
jrclark240ebaad2020-04-02 11:18:00 -0500751 return name.at(-1).toSegment() % 2 == 0;
752 });
Tianyuan Yu947a3992023-07-24 12:28:40 -0700753 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), validator);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700754 connectSignals(fetcher);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000755
756 auto data1 = makeDataSegment("/hello/world", 0, false);
757 auto data2 = makeDataSegment("/hello/world", 1, true);
758
Davide Pesavento0f830802018-01-16 23:58:58 -0500759 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000760
Eric Newberrye345baa2018-05-23 18:17:07 -0700761 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
762
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000763 face.receive(*data1);
764
Davide Pesavento0f830802018-01-16 23:58:58 -0500765 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000766
Eric Newberrye345baa2018-05-23 18:17:07 -0700767 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
768
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000769 face.receive(*data2);
770
Davide Pesavento0f830802018-01-16 23:58:58 -0500771 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000772
Eric Newberrye345baa2018-05-23 18:17:07 -0700773 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 200_ms);
jrclark240ebaad2020-04-02 11:18:00 -0500774 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 2);
775 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000776 BOOST_CHECK_EQUAL(nErrors, 1);
777}
778
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500779BOOST_AUTO_TEST_CASE(Stop)
780{
781 DummyValidator acceptValidator;
782
783 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
784 connectSignals(fetcher);
785 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
786
787 fetcher->stop();
788 advanceClocks(10_ms);
789 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
790
791 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
792 advanceClocks(10_ms);
793 BOOST_CHECK_EQUAL(nErrors, 0);
794 BOOST_CHECK_EQUAL(nCompletions, 0);
795
796 fetcher.reset();
797 BOOST_CHECK_EQUAL(fetcher.use_count(), 0);
798
799 // Make sure we can re-assign w/o any complains from ASan
800 fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
801 connectSignals(fetcher);
802 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
803
804 advanceClocks(10_ms);
805
806 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
807
808 advanceClocks(10_ms);
809 BOOST_CHECK_EQUAL(nErrors, 0);
810 BOOST_CHECK_EQUAL(nCompletions, 1);
811 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
812
813 // Stop from callback
814 bool fetcherStopped = false;
815
816 fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
jrclark240ebaad2020-04-02 11:18:00 -0500817 fetcher->afterSegmentReceived.connect([&fetcher, &fetcherStopped] (const Data&) {
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500818 fetcherStopped = true;
819 fetcher->stop();
820 });
821 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
822
823 advanceClocks(10_ms);
824
825 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
826
827 advanceClocks(10_ms);
828 BOOST_CHECK(fetcherStopped);
829 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
830}
831
832BOOST_AUTO_TEST_CASE(Lifetime)
833{
834 // BasicSingleSegment, but with scoped fetcher
835
836 DummyValidator acceptValidator;
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500837
838 weak_ptr<SegmentFetcher> weakFetcher;
839 {
840 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
841 weakFetcher = fetcher;
842 connectSignals(fetcher);
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500843 }
844
845 advanceClocks(10_ms);
846 BOOST_CHECK_EQUAL(weakFetcher.expired(), false);
847
848 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500849 advanceClocks(10_ms);
850
851 BOOST_CHECK_EQUAL(nErrors, 0);
852 BOOST_CHECK_EQUAL(nCompletions, 1);
853 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
854 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
855 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
856 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
857 BOOST_CHECK_EQUAL(weakFetcher.expired(), true);
858}
859
860BOOST_AUTO_TEST_CASE(OutOfScopeTimeout)
861{
862 DummyValidator acceptValidator;
863 SegmentFetcher::Options options;
864 options.maxTimeout = 3000_ms;
865
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500866 weak_ptr<SegmentFetcher> weakFetcher;
867 {
868 auto fetcher = SegmentFetcher::start(face, Interest("/localhost/nfd/faces/list"),
869 acceptValidator, options);
870 weakFetcher = fetcher;
871 connectSignals(fetcher);
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500872 }
873
874 advanceClocks(500_ms, 7);
875 BOOST_CHECK_EQUAL(weakFetcher.expired(), true);
876
877 BOOST_CHECK_EQUAL(nErrors, 1);
878 BOOST_CHECK_EQUAL(nCompletions, 0);
879 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
880 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
881 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
882 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 2);
883}
884
Davide Pesavento0c526032024-01-31 21:14:01 -0500885BOOST_AUTO_TEST_CASE(UncanceledPendingInterest,
886 * ut::description("test for bug #4770"))
Ashlesh Gawandeebe156c2018-11-12 16:27:49 -0600887{
888 DummyValidator acceptValidator;
889 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
890 connectSignals(fetcher);
891
892 // Fetcher will send the first interest immediately
893 // and the second interest after 1 second by default
894 advanceClocks(1100_ms);
895
896 // Face will give data to the fetcher twice if the first interest is not canceled.
897 // isFinal=false to keep fetcher alive so that it can receive the second data.
898 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
899
900 advanceClocks(1100_ms);
901
902 face.receive(*makeDataSegment("/hello/world/version0", 1, true));
903
904 BOOST_CHECK_EQUAL(nErrors, 0);
905 BOOST_CHECK_EQUAL(nCompletions, 1);
906}
907
Junxiao Shid5827ce2016-07-14 20:49:37 +0000908BOOST_AUTO_TEST_SUITE_END() // TestSegmentFetcher
909BOOST_AUTO_TEST_SUITE_END() // Util
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700910
Davide Pesavento47ce2ee2023-05-09 01:33:33 -0400911} // namespace ndn::tests