blob: 9f65f493c93054080cf7fe4f0c6c660216475b70 [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/*
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +00003 * Copyright (c) 2013-2019 Regents of the University of California.
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
Davide Pesavento7e780642018-11-24 15:51:34 -050022#include "ndn-cxx/util/segment-fetcher.hpp"
Davide Pesavento5d0b0102017-10-07 13:43:16 -040023
Davide Pesavento7e780642018-11-24 15:51:34 -050024#include "ndn-cxx/data.hpp"
25#include "ndn-cxx/lp/nack.hpp"
26#include "ndn-cxx/util/dummy-client-face.hpp"
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070027
Davide Pesavento7e780642018-11-24 15:51:34 -050028#include "tests/boost-test.hpp"
29#include "tests/make-interest-data.hpp"
30#include "tests/unit/dummy-validator.hpp"
31#include "tests/unit/identity-management-time-fixture.hpp"
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070032
Eric Newberrye345baa2018-05-23 18:17:07 -070033#include <set>
34
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070035namespace ndn {
36namespace util {
37namespace tests {
38
Junxiao Shi0f3f0b42016-07-14 13:26:37 +000039using namespace ndn::tests;
40
Alexander Afanasyev80782e02017-01-04 13:16:54 -080041class Fixture : public IdentityManagementTimeFixture
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070042{
43public:
44 Fixture()
Alexander Afanasyeve4f8c3b2016-06-23 16:03:48 -070045 : face(io, m_keyChain)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070046 {
47 }
48
Davide Pesavento5d0b0102017-10-07 13:43:16 -040049 static shared_ptr<Data>
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050050 makeDataSegment(const Name& baseName, uint64_t segment, bool isFinal)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070051 {
52 const uint8_t buffer[] = "Hello, world!";
53
Junxiao Shid5827ce2016-07-14 20:49:37 +000054 auto data = make_shared<Data>(Name(baseName).appendSegment(segment));
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +000055 data->setFreshnessPeriod(1_s);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070056 data->setContent(buffer, sizeof(buffer));
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050057 if (isFinal) {
Junxiao Shiebfe4a22018-04-01 23:53:40 +000058 data->setFinalBlock(data->getName()[-1]);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050059 }
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070060
Davide Pesavento5d0b0102017-10-07 13:43:16 -040061 return signData(data);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070062 }
63
64 void
65 onError(uint32_t errorCode)
66 {
67 ++nErrors;
68 lastError = errorCode;
69 }
70
71 void
Eric Newberrye345baa2018-05-23 18:17:07 -070072 onComplete(ConstBufferPtr data)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070073 {
Eric Newberrycc910cd2018-05-06 17:01:40 -070074 ++nCompletions;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070075 dataSize = data->size();
Eric Newberrye345baa2018-05-23 18:17:07 -070076 dataBuf = data;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070077 }
78
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050079 void
80 nackLastInterest(lp::NackReason nackReason)
81 {
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080082 const Interest& lastInterest = face.sentInterests.back();
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050083 lp::Nack nack = makeNack(lastInterest, nackReason);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080084 face.receive(nack);
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 {
91 fetcher->onComplete.connect(bind(&Fixture::onComplete, this, _1));
92 fetcher->onError.connect(bind(&Fixture::onError, this, _1));
93 }
94
Eric Newberrye345baa2018-05-23 18:17:07 -070095 void
96 onInterest(const Interest& interest)
97 {
98 if (interest.getName().get(-1).isSegment()) {
99 if (segmentsToDropOrNack.size() > 0 &&
100 interest.getName().get(-1).toSegment() == segmentsToDropOrNack.front()) {
101 segmentsToDropOrNack.pop();
102 if (sendNackInsteadOfDropping) {
103 lp::Nack nack = makeNack(interest, nackReason);
104 face.receive(nack);
105 }
106 return;
107 }
108
109 auto data = makeDataSegment("/hello/world/version0",
110 interest.getName().get(-1).toSegment(),
111 interest.getName().get(-1).toSegment() == nSegments - 1);
112 face.receive(*data);
113
114 uniqSegmentsSent.insert(interest.getName().get(-1).toSegment());
115 if (uniqSegmentsSent.size() == nSegments) {
116 io.stop();
117 }
118 }
119 else {
120 if (segmentsToDropOrNack.size() > 0 &&
121 segmentsToDropOrNack.front() == 0) {
122 segmentsToDropOrNack.pop();
123 if (sendNackInsteadOfDropping) {
124 lp::Nack nack = makeNack(interest, nackReason);
125 face.receive(nack);
126 }
127 return;
128 }
129
130 auto data = makeDataSegment("/hello/world/version0", defaultSegmentToSend, nSegments == 1);
131 face.receive(*data);
132 uniqSegmentsSent.insert(defaultSegmentToSend);
133 }
134 }
135
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700136public:
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800137 DummyClientFace face;
Eric Newberrye345baa2018-05-23 18:17:07 -0700138 std::set<uint64_t> uniqSegmentsSent;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700139
Eric Newberrycc910cd2018-05-06 17:01:40 -0700140 int nErrors = 0;
Davide Pesavento5d0b0102017-10-07 13:43:16 -0400141 uint32_t lastError = 0;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700142 int nCompletions = 0;
Davide Pesavento5d0b0102017-10-07 13:43:16 -0400143 size_t dataSize = 0;
Eric Newberrye345baa2018-05-23 18:17:07 -0700144 ConstBufferPtr dataBuf;
145
146 // number of segments in fetched object
147 uint64_t nSegments = 0;
148 std::queue<uint64_t> segmentsToDropOrNack;
149 bool sendNackInsteadOfDropping = false;
150 lp::NackReason nackReason = lp::NackReason::NONE;
151 // segment that is sent in response to an Interest w/o a segment component in its name
152 uint64_t defaultSegmentToSend = 0;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700153};
154
Eric Newberrye345baa2018-05-23 18:17:07 -0700155BOOST_AUTO_TEST_SUITE(Util)
156BOOST_FIXTURE_TEST_SUITE(TestSegmentFetcher, Fixture)
157
158BOOST_AUTO_TEST_CASE(InvalidOptions)
159{
160 SegmentFetcher::Options options;
161 options.mdCoef = 1.5;
162 DummyValidator acceptValidator;
163 BOOST_CHECK_THROW(SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options),
164 std::invalid_argument);
165}
166
167BOOST_AUTO_TEST_CASE(ExceedMaxTimeout)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700168{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800169 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700170 size_t nAfterSegmentTimedOut = 0;
171 SegmentFetcher::Options options;
172 options.maxTimeout = 100_ms;
173 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
174 acceptValidator, options);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700175 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700176 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700177
Davide Pesavento0f830802018-01-16 23:58:58 -0500178 advanceClocks(1_ms);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800179 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700180
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800181 const Interest& interest = face.sentInterests[0];
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700182 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
183 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
Eric Newberry2b765f82018-06-25 14:51:13 -0700184 BOOST_CHECK_EQUAL(interest.getCanBePrefix(), true);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800185
Davide Pesavento0f830802018-01-16 23:58:58 -0500186 advanceClocks(98_ms);
Junxiao Shid5827ce2016-07-14 20:49:37 +0000187 BOOST_CHECK_EQUAL(nErrors, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700188 BOOST_CHECK_EQUAL(nCompletions, 0);
Junxiao Shid5827ce2016-07-14 20:49:37 +0000189 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Eric Newberrye345baa2018-05-23 18:17:07 -0700190 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800191
Davide Pesavento0f830802018-01-16 23:58:58 -0500192 advanceClocks(1_ms, 2);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800193 BOOST_CHECK_EQUAL(nErrors, 1);
194 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::INTEREST_TIMEOUT));
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800195 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
196 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Eric Newberrye345baa2018-05-23 18:17:07 -0700197 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 1);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700198}
199
Eric Newberrye345baa2018-05-23 18:17:07 -0700200BOOST_AUTO_TEST_CASE(BasicSingleSegment)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700201{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800202 DummyValidator acceptValidator;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700203 size_t nAfterSegmentReceived = 0;
204 size_t nAfterSegmentValidated = 0;
Eric Newberrye345baa2018-05-23 18:17:07 -0700205 size_t nAfterSegmentNacked = 0;
206 size_t nAfterSegmentTimedOut = 0;
207 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700208 acceptValidator);
209 connectSignals(fetcher);
210 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
211 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
Eric Newberrye345baa2018-05-23 18:17:07 -0700212 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
213 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500214
Davide Pesavento0f830802018-01-16 23:58:58 -0500215 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500216
Eric Newberrye345baa2018-05-23 18:17:07 -0700217 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
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
221 BOOST_CHECK_EQUAL(nErrors, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700222 BOOST_CHECK_EQUAL(nCompletions, 1);
Eric Newberrye345baa2018-05-23 18:17:07 -0700223 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
224 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
225 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
226 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700227}
228
Eric Newberrye345baa2018-05-23 18:17:07 -0700229BOOST_AUTO_TEST_CASE(ConstantCwnd)
230{
231 SegmentFetcher::Options options;
232 options.useConstantCwnd = true;
233 DummyValidator acceptValidator;
234 size_t nAfterSegmentReceived = 0;
235 size_t nAfterSegmentValidated = 0;
236 size_t nAfterSegmentNacked = 0;
237 size_t nAfterSegmentTimedOut = 0;
238 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
239 acceptValidator, options);
240 connectSignals(fetcher);
241 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
242 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
243 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
244 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
245
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 size_t nAfterSegmentReceived = 0;
308 size_t nAfterSegmentValidated = 0;
309 size_t nAfterSegmentNacked = 0;
310 size_t nAfterSegmentTimedOut = 0;
311 nSegments = 401;
312 sendNackInsteadOfDropping = false;
313 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
314
315 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
316 acceptValidator);
317 connectSignals(fetcher);
318 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
319 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
320 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
321 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
322
323 face.processEvents(1_s);
324
325 BOOST_CHECK_EQUAL(nErrors, 0);
326 BOOST_CHECK_EQUAL(nCompletions, 1);
327 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
328 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
329 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
330 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
331 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
332}
333
334BOOST_AUTO_TEST_CASE(FirstSegmentNotZero)
335{
336 DummyValidator acceptValidator;
337 size_t nAfterSegmentReceived = 0;
338 size_t nAfterSegmentValidated = 0;
339 size_t nAfterSegmentNacked = 0;
340 size_t nAfterSegmentTimedOut = 0;
341 nSegments = 401;
342 sendNackInsteadOfDropping = false;
343 defaultSegmentToSend = 47;
344 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
345
346 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
347 acceptValidator);
348 connectSignals(fetcher);
349 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
350 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
351 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
352 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
353
354 face.processEvents(1_s);
355
356 BOOST_CHECK_EQUAL(nErrors, 0);
357 BOOST_CHECK_EQUAL(nCompletions, 1);
358 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
359 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
360 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
361 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
362 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
363}
364
365BOOST_AUTO_TEST_CASE(WindowSize)
366{
367 DummyValidator acceptValidator;
368 size_t nAfterSegmentReceived = 0;
369 size_t nAfterSegmentValidated = 0;
370 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
371 acceptValidator);
372 connectSignals(fetcher);
373 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
374 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
375
376 advanceClocks(10_ms); // T+10ms
377
378 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
379 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
380 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, 0);
381 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
382 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, std::numeric_limits<double>::max());
383 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
384 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
385 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 0);
386 BOOST_CHECK_EQUAL(fetcher->m_highInterest, 0);
387 BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
388 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
389 BOOST_CHECK_EQUAL(fetcher->m_nReceived, 0);
390 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 0);
391 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), 1);
392 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
393
394 double oldCwnd = fetcher->m_cwnd;
395 double oldSsthresh = fetcher->m_ssthresh;
396 uint64_t oldNextSegmentNum = fetcher->m_nextSegmentNum;
397
398 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
399
400 advanceClocks(10_ms); //T+20ms
401
402 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
403 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
404 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
405 // +2 below because m_nextSegmentNum will be incremented in the receive callback if segment 0 is
406 // the first received
407 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 2);
408 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
409 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
410 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd + fetcher->m_options.aiStep);
411 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
412 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 14);
413 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
414 BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
415 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
416 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 1);
417 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
418 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1 + fetcher->m_cwnd);
419
420 oldCwnd = fetcher->m_cwnd;
421 oldNextSegmentNum = fetcher->m_nextSegmentNum;
422
423 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
424
425 advanceClocks(10_ms); //T+30ms
426
427 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
428 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
429 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
430 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
431 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
432 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
433 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
434 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
435 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 28);
436 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
437 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
438 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
439 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 2);
440 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
441 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2 + fetcher->m_cwnd);
442
443 oldCwnd = fetcher->m_cwnd;
444 oldNextSegmentNum = fetcher->m_nextSegmentNum;
445
446 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
447
448 advanceClocks(10_ms); //T+40ms
449
450 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
451 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
452 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
453 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
454 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
455 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
456 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
457 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
458 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
459 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
460 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
461 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
462 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
463 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
464 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3 + fetcher->m_cwnd);
465
466 oldCwnd = fetcher->m_cwnd;
467 oldSsthresh = fetcher->m_ssthresh;
468 oldNextSegmentNum = fetcher->m_nextSegmentNum;
469 size_t oldSentInterestsSize = face.sentInterests.size();
470
471 nackLastInterest(lp::NackReason::CONGESTION); //T+50ms
472
473 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 20_ms);
474 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
475 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
476 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
477 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
478 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
479 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
480 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
481 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
482 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
483 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
484 BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
485 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
486 // The Nacked segment will remain in pendingSegments, so the size of the structure doesn't change
487 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
488 BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
489
490 advanceClocks(10_ms); //T+60ms
491
492 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 30_ms);
493 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
494 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
495 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
496 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
497 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
498 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
499 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
500 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
501 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
502 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
503 BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
504 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
505 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
506 BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
507
508 // Properly end test case
509 lp::Nack nack = makeNack(face.sentInterests[face.sentInterests.size() - 2], lp::NackReason::NO_ROUTE);
510 face.receive(nack);
511 advanceClocks(10_ms); //T+70ms
512
513 BOOST_CHECK_EQUAL(nErrors, 1);
514 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::NACK_ERROR));
515 BOOST_CHECK_EQUAL(nCompletions, 0);
516}
517
518BOOST_AUTO_TEST_CASE(MissingSegmentNum)
519{
520 DummyValidator acceptValidator;
521 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700522 acceptValidator);
523 connectSignals(fetcher);
524
525 advanceClocks(10_ms);
526
527 const uint8_t buffer[] = "Hello, world!";
528 auto data = makeData("/hello/world/version0/no-segment");
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +0000529 data->setFreshnessPeriod(1_s);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700530 data->setContent(buffer, sizeof(buffer));
531
532 face.receive(*data);
533 advanceClocks(10_ms);
534
535 BOOST_CHECK_EQUAL(nErrors, 1);
536 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::DATA_HAS_NO_SEGMENT));
537 BOOST_CHECK_EQUAL(nCompletions, 0);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500538}
539
Eric Newberrye345baa2018-05-23 18:17:07 -0700540BOOST_AUTO_TEST_CASE(MoreSegmentsThanNSegments)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500541{
Eric Newberrycc910cd2018-05-06 17:01:40 -0700542 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700543 size_t nAfterSegmentReceived = 0;
544 size_t nAfterSegmentValidated = 0;
545 size_t nAfterSegmentNacked = 0;
546 size_t nAfterSegmentTimedOut = 0;
547 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700548 acceptValidator);
549 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700550 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
551 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
552 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
553 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
554
Davide Pesavento0f830802018-01-16 23:58:58 -0500555 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500556
Eric Newberrye345baa2018-05-23 18:17:07 -0700557 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
Davide Pesavento0f830802018-01-16 23:58:58 -0500558 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500559
Eric Newberrye345baa2018-05-23 18:17:07 -0700560 BOOST_CHECK_EQUAL(nErrors, 0);
561 BOOST_CHECK_EQUAL(nCompletions, 0);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500562
Eric Newberrye345baa2018-05-23 18:17:07 -0700563 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
Davide Pesavento0f830802018-01-16 23:58:58 -0500564 advanceClocks(10_ms);
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500565
Eric Newberrye345baa2018-05-23 18:17:07 -0700566 BOOST_CHECK_EQUAL(nErrors, 0);
567 BOOST_CHECK_EQUAL(nCompletions, 0);
568
569 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
570 advanceClocks(10_ms);
571
572 BOOST_CHECK_EQUAL(nErrors, 0);
573 BOOST_CHECK_EQUAL(nCompletions, 0);
574
575 face.receive(*makeDataSegment("/hello/world/version0", 3, false));
576 advanceClocks(10_ms);
577
578 BOOST_CHECK_EQUAL(nErrors, 0);
579 BOOST_CHECK_EQUAL(nCompletions, 0);
580
581 auto data4 = makeDataSegment("/hello/world/version0", 4, false);
582 data4->setFinalBlock(name::Component::fromSegment(2));
583 face.receive(*data4);
584 advanceClocks(10_ms);
585
586 BOOST_CHECK_EQUAL(nErrors, 0);
587 BOOST_CHECK_EQUAL(nCompletions, 1);
588 BOOST_CHECK_EQUAL(dataSize, 14 * 3);
589 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 5);
590 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 5);
591 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
592 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500593}
594
Eric Newberrye345baa2018-05-23 18:17:07 -0700595BOOST_AUTO_TEST_CASE(DuplicateNack)
596{
597 DummyValidator acceptValidator;
598 size_t nAfterSegmentReceived = 0;
599 size_t nAfterSegmentValidated = 0;
600 size_t nAfterSegmentNacked = 0;
601 size_t nAfterSegmentTimedOut = 0;
602 nSegments = 401;
603 segmentsToDropOrNack.push(0);
604 segmentsToDropOrNack.push(200);
605 sendNackInsteadOfDropping = true;
606 nackReason = lp::NackReason::DUPLICATE;
607 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
608
609 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
610 acceptValidator);
611 connectSignals(fetcher);
612 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
613 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
614 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
615 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
616
617 face.processEvents(1_s);
618
619 BOOST_CHECK_EQUAL(nErrors, 0);
620 BOOST_CHECK_EQUAL(nCompletions, 1);
621 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
622 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
623 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
624 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
625 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
626}
627
628BOOST_AUTO_TEST_CASE(CongestionNack)
629{
630 DummyValidator acceptValidator;
631 size_t nAfterSegmentReceived = 0;
632 size_t nAfterSegmentValidated = 0;
633 size_t nAfterSegmentNacked = 0;
634 size_t nAfterSegmentTimedOut = 0;
635 nSegments = 401;
636 segmentsToDropOrNack.push(0);
637 segmentsToDropOrNack.push(200);
638 sendNackInsteadOfDropping = true;
639 nackReason = lp::NackReason::CONGESTION;
640 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
641
642 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
643 acceptValidator);
644 connectSignals(fetcher);
645 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
646 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
647 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
648 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
649
650 face.processEvents(1_s);
651
652 BOOST_CHECK_EQUAL(nErrors, 0);
653 BOOST_CHECK_EQUAL(nCompletions, 1);
654 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
655 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
656 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
657 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
658 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
659}
660
661BOOST_AUTO_TEST_CASE(OtherNackReason)
662{
663 DummyValidator acceptValidator;
664 size_t nAfterSegmentReceived = 0;
665 size_t nAfterSegmentValidated = 0;
666 size_t nAfterSegmentNacked = 0;
667 size_t nAfterSegmentTimedOut = 0;
668 segmentsToDropOrNack.push(0);
669 sendNackInsteadOfDropping = true;
670 nackReason = lp::NackReason::NO_ROUTE;
671 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
672
673 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
674 acceptValidator);
675 connectSignals(fetcher);
676 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
677 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
678 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
679 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
680
681 face.processEvents(1_s);
682
683 BOOST_CHECK_EQUAL(nErrors, 1);
684 BOOST_CHECK_EQUAL(nCompletions, 0);
685 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
686 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
687 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 1);
688 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
689 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
690}
691
692BOOST_AUTO_TEST_CASE(ValidationFailure)
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000693{
694 DummyValidator validator;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700695 validator.getPolicy().setResultCallback([] (const Name& name) {
696 return name.at(-1).toSegment() % 2 == 0;
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000697 });
Eric Newberrye345baa2018-05-23 18:17:07 -0700698 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700699 validator);
700 connectSignals(fetcher);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000701
702 auto data1 = makeDataSegment("/hello/world", 0, false);
703 auto data2 = makeDataSegment("/hello/world", 1, true);
704
705 size_t nRecvSegments = 0;
706 fetcher->afterSegmentReceived.connect([&nRecvSegments] (const Data& receivedSegment) {
707 ++nRecvSegments;
708 });
709
710 size_t nValidatedSegments = 0;
711 fetcher->afterSegmentValidated.connect([&nValidatedSegments] (const Data& validatedSegment) {
712 ++nValidatedSegments;
713 });
714
Davide Pesavento0f830802018-01-16 23:58:58 -0500715 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000716
Eric Newberrye345baa2018-05-23 18:17:07 -0700717 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
718
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000719 face.receive(*data1);
720
Davide Pesavento0f830802018-01-16 23:58:58 -0500721 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000722
Eric Newberrye345baa2018-05-23 18:17:07 -0700723 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
724
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000725 face.receive(*data2);
726
Davide Pesavento0f830802018-01-16 23:58:58 -0500727 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000728
Eric Newberrye345baa2018-05-23 18:17:07 -0700729 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 200_ms);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000730 BOOST_CHECK_EQUAL(nRecvSegments, 2);
731 BOOST_CHECK_EQUAL(nValidatedSegments, 1);
732 BOOST_CHECK_EQUAL(nErrors, 1);
733}
734
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500735BOOST_AUTO_TEST_CASE(Stop)
736{
737 DummyValidator acceptValidator;
738
739 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
740 connectSignals(fetcher);
741 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
742
743 fetcher->stop();
744 advanceClocks(10_ms);
745 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
746
747 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
748 advanceClocks(10_ms);
749 BOOST_CHECK_EQUAL(nErrors, 0);
750 BOOST_CHECK_EQUAL(nCompletions, 0);
751
752 fetcher.reset();
753 BOOST_CHECK_EQUAL(fetcher.use_count(), 0);
754
755 // Make sure we can re-assign w/o any complains from ASan
756 fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
757 connectSignals(fetcher);
758 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
759
760 advanceClocks(10_ms);
761
762 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
763
764 advanceClocks(10_ms);
765 BOOST_CHECK_EQUAL(nErrors, 0);
766 BOOST_CHECK_EQUAL(nCompletions, 1);
767 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
768
769 // Stop from callback
770 bool fetcherStopped = false;
771
772 fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
773 fetcher->afterSegmentReceived.connect([&fetcher, &fetcherStopped] (const Data& data) {
774 fetcherStopped = true;
775 fetcher->stop();
776 });
777 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
778
779 advanceClocks(10_ms);
780
781 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
782
783 advanceClocks(10_ms);
784 BOOST_CHECK(fetcherStopped);
785 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
786}
787
788BOOST_AUTO_TEST_CASE(Lifetime)
789{
790 // BasicSingleSegment, but with scoped fetcher
791
792 DummyValidator acceptValidator;
793 size_t nAfterSegmentReceived = 0;
794 size_t nAfterSegmentValidated = 0;
795 size_t nAfterSegmentNacked = 0;
796 size_t nAfterSegmentTimedOut = 0;
797
798 weak_ptr<SegmentFetcher> weakFetcher;
799 {
800 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
801 weakFetcher = fetcher;
802 connectSignals(fetcher);
803
804 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
805 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
806 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
807 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
808 }
809
810 advanceClocks(10_ms);
811 BOOST_CHECK_EQUAL(weakFetcher.expired(), false);
812
813 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
814
815 advanceClocks(10_ms);
816
817 BOOST_CHECK_EQUAL(nErrors, 0);
818 BOOST_CHECK_EQUAL(nCompletions, 1);
819 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
820 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
821 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
822 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
823 BOOST_CHECK_EQUAL(weakFetcher.expired(), true);
824}
825
826BOOST_AUTO_TEST_CASE(OutOfScopeTimeout)
827{
828 DummyValidator acceptValidator;
829 SegmentFetcher::Options options;
830 options.maxTimeout = 3000_ms;
831
832 size_t nAfterSegmentReceived = 0;
833 size_t nAfterSegmentValidated = 0;
834 size_t nAfterSegmentNacked = 0;
835 size_t nAfterSegmentTimedOut = 0;
836
837 weak_ptr<SegmentFetcher> weakFetcher;
838 {
839 auto fetcher = SegmentFetcher::start(face, Interest("/localhost/nfd/faces/list"),
840 acceptValidator, options);
841 weakFetcher = fetcher;
842 connectSignals(fetcher);
843 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
844 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
845 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
846 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
847 }
848
849 advanceClocks(500_ms, 7);
850 BOOST_CHECK_EQUAL(weakFetcher.expired(), true);
851
852 BOOST_CHECK_EQUAL(nErrors, 1);
853 BOOST_CHECK_EQUAL(nCompletions, 0);
854 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
855 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
856 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
857 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 2);
858}
859
Ashlesh Gawandeebe156c2018-11-12 16:27:49 -0600860BOOST_AUTO_TEST_CASE(UncanceledPendingInterestBug) // Bug #4770
861{
862 DummyValidator acceptValidator;
863 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
864 connectSignals(fetcher);
865
866 // Fetcher will send the first interest immediately
867 // and the second interest after 1 second by default
868 advanceClocks(1100_ms);
869
870 // Face will give data to the fetcher twice if the first interest is not canceled.
871 // isFinal=false to keep fetcher alive so that it can receive the second data.
872 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
873
874 advanceClocks(1100_ms);
875
876 face.receive(*makeDataSegment("/hello/world/version0", 1, true));
877
878 BOOST_CHECK_EQUAL(nErrors, 0);
879 BOOST_CHECK_EQUAL(nCompletions, 1);
880}
881
Junxiao Shid5827ce2016-07-14 20:49:37 +0000882BOOST_AUTO_TEST_SUITE_END() // TestSegmentFetcher
883BOOST_AUTO_TEST_SUITE_END() // Util
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700884
885} // namespace tests
886} // namespace util
887} // namespace ndn