blob: 22aa0b7e01d5dedeca26023cecc708feb33f7133 [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/*
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +00003 * Copyright (c) 2013-2018 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));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070055 data->setContent(buffer, sizeof(buffer));
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050056 if (isFinal) {
Junxiao Shiebfe4a22018-04-01 23:53:40 +000057 data->setFinalBlock(data->getName()[-1]);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050058 }
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070059
Davide Pesavento5d0b0102017-10-07 13:43:16 -040060 return signData(data);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070061 }
62
63 void
64 onError(uint32_t errorCode)
65 {
66 ++nErrors;
67 lastError = errorCode;
68 }
69
70 void
Eric Newberrye345baa2018-05-23 18:17:07 -070071 onComplete(ConstBufferPtr data)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070072 {
Eric Newberrycc910cd2018-05-06 17:01:40 -070073 ++nCompletions;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070074 dataSize = data->size();
Eric Newberrye345baa2018-05-23 18:17:07 -070075 dataBuf = data;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -070076 }
77
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050078 void
79 nackLastInterest(lp::NackReason nackReason)
80 {
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080081 const Interest& lastInterest = face.sentInterests.back();
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -050082 lp::Nack nack = makeNack(lastInterest, nackReason);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080083 face.receive(nack);
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 {
90 fetcher->onComplete.connect(bind(&Fixture::onComplete, this, _1));
91 fetcher->onError.connect(bind(&Fixture::onError, this, _1));
92 }
93
Eric Newberrye345baa2018-05-23 18:17:07 -070094 void
95 onInterest(const Interest& interest)
96 {
97 if (interest.getName().get(-1).isSegment()) {
98 if (segmentsToDropOrNack.size() > 0 &&
99 interest.getName().get(-1).toSegment() == segmentsToDropOrNack.front()) {
100 segmentsToDropOrNack.pop();
101 if (sendNackInsteadOfDropping) {
102 lp::Nack nack = makeNack(interest, nackReason);
103 face.receive(nack);
104 }
105 return;
106 }
107
108 auto data = makeDataSegment("/hello/world/version0",
109 interest.getName().get(-1).toSegment(),
110 interest.getName().get(-1).toSegment() == nSegments - 1);
111 face.receive(*data);
112
113 uniqSegmentsSent.insert(interest.getName().get(-1).toSegment());
114 if (uniqSegmentsSent.size() == nSegments) {
115 io.stop();
116 }
117 }
118 else {
119 if (segmentsToDropOrNack.size() > 0 &&
120 segmentsToDropOrNack.front() == 0) {
121 segmentsToDropOrNack.pop();
122 if (sendNackInsteadOfDropping) {
123 lp::Nack nack = makeNack(interest, nackReason);
124 face.receive(nack);
125 }
126 return;
127 }
128
129 auto data = makeDataSegment("/hello/world/version0", defaultSegmentToSend, nSegments == 1);
130 face.receive(*data);
131 uniqSegmentsSent.insert(defaultSegmentToSend);
132 }
133 }
134
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700135public:
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800136 DummyClientFace face;
Eric Newberrye345baa2018-05-23 18:17:07 -0700137 std::set<uint64_t> uniqSegmentsSent;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700138
Eric Newberrycc910cd2018-05-06 17:01:40 -0700139 int nErrors = 0;
Davide Pesavento5d0b0102017-10-07 13:43:16 -0400140 uint32_t lastError = 0;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700141 int nCompletions = 0;
Davide Pesavento5d0b0102017-10-07 13:43:16 -0400142 size_t dataSize = 0;
Eric Newberrye345baa2018-05-23 18:17:07 -0700143 ConstBufferPtr dataBuf;
144
145 // number of segments in fetched object
146 uint64_t nSegments = 0;
147 std::queue<uint64_t> segmentsToDropOrNack;
148 bool sendNackInsteadOfDropping = false;
149 lp::NackReason nackReason = lp::NackReason::NONE;
150 // segment that is sent in response to an Interest w/o a segment component in its name
151 uint64_t defaultSegmentToSend = 0;
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700152};
153
Eric Newberrye345baa2018-05-23 18:17:07 -0700154BOOST_AUTO_TEST_SUITE(Util)
155BOOST_FIXTURE_TEST_SUITE(TestSegmentFetcher, Fixture)
156
157BOOST_AUTO_TEST_CASE(InvalidOptions)
158{
159 SegmentFetcher::Options options;
160 options.mdCoef = 1.5;
161 DummyValidator acceptValidator;
162 BOOST_CHECK_THROW(SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options),
163 std::invalid_argument);
164}
165
166BOOST_AUTO_TEST_CASE(ExceedMaxTimeout)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700167{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800168 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700169 size_t nAfterSegmentTimedOut = 0;
170 SegmentFetcher::Options options;
171 options.maxTimeout = 100_ms;
172 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
173 acceptValidator, options);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700174 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700175 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700176
Davide Pesavento0f830802018-01-16 23:58:58 -0500177 advanceClocks(1_ms);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800178 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700179
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800180 const Interest& interest = face.sentInterests[0];
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700181 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
182 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
Eric Newberry2b765f82018-06-25 14:51:13 -0700183 BOOST_CHECK_EQUAL(interest.getCanBePrefix(), true);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800184
Davide Pesavento0f830802018-01-16 23:58:58 -0500185 advanceClocks(98_ms);
Junxiao Shid5827ce2016-07-14 20:49:37 +0000186 BOOST_CHECK_EQUAL(nErrors, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700187 BOOST_CHECK_EQUAL(nCompletions, 0);
Junxiao Shid5827ce2016-07-14 20:49:37 +0000188 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Eric Newberrye345baa2018-05-23 18:17:07 -0700189 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800190
Davide Pesavento0f830802018-01-16 23:58:58 -0500191 advanceClocks(1_ms, 2);
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800192 BOOST_CHECK_EQUAL(nErrors, 1);
193 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::INTEREST_TIMEOUT));
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800194 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
195 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Eric Newberrye345baa2018-05-23 18:17:07 -0700196 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 1);
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700197}
198
Eric Newberrye345baa2018-05-23 18:17:07 -0700199BOOST_AUTO_TEST_CASE(BasicSingleSegment)
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700200{
Alexander Afanasyev6dfeffe2017-01-30 22:40:32 -0800201 DummyValidator acceptValidator;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700202 size_t nAfterSegmentReceived = 0;
203 size_t nAfterSegmentValidated = 0;
Eric Newberrye345baa2018-05-23 18:17:07 -0700204 size_t nAfterSegmentNacked = 0;
205 size_t nAfterSegmentTimedOut = 0;
206 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700207 acceptValidator);
208 connectSignals(fetcher);
209 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
210 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
Eric Newberrye345baa2018-05-23 18:17:07 -0700211 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
212 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500213
Davide Pesavento0f830802018-01-16 23:58:58 -0500214 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500215
Eric Newberrye345baa2018-05-23 18:17:07 -0700216 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500217
Davide Pesavento0f830802018-01-16 23:58:58 -0500218 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500219
220 BOOST_CHECK_EQUAL(nErrors, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700221 BOOST_CHECK_EQUAL(nCompletions, 1);
Eric Newberrye345baa2018-05-23 18:17:07 -0700222 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
223 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
224 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
225 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Eric Newberrycc910cd2018-05-06 17:01:40 -0700226}
227
Eric Newberrye345baa2018-05-23 18:17:07 -0700228BOOST_AUTO_TEST_CASE(ConstantCwnd)
229{
230 SegmentFetcher::Options options;
231 options.useConstantCwnd = true;
232 DummyValidator acceptValidator;
233 size_t nAfterSegmentReceived = 0;
234 size_t nAfterSegmentValidated = 0;
235 size_t nAfterSegmentNacked = 0;
236 size_t nAfterSegmentTimedOut = 0;
237 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
238 acceptValidator, options);
239 connectSignals(fetcher);
240 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
241 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
242 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
243 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
244
245 advanceClocks(10_ms);
246
247 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
248 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
249
250 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
251
252 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);
258 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
259
260 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);
266 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
267
268 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);
274 face.receive(*makeDataSegment("/hello/world/version0", 3, false));
275
276 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);
290 face.receive(*makeDataSegment("/hello/world/version0", 4, true));
291
292 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 size_t nAfterSegmentReceived = 0;
307 size_t nAfterSegmentValidated = 0;
308 size_t nAfterSegmentNacked = 0;
309 size_t nAfterSegmentTimedOut = 0;
310 nSegments = 401;
311 sendNackInsteadOfDropping = false;
312 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
313
314 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
315 acceptValidator);
316 connectSignals(fetcher);
317 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
318 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
319 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
320 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
321
322 face.processEvents(1_s);
323
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
333BOOST_AUTO_TEST_CASE(FirstSegmentNotZero)
334{
335 DummyValidator acceptValidator;
336 size_t nAfterSegmentReceived = 0;
337 size_t nAfterSegmentValidated = 0;
338 size_t nAfterSegmentNacked = 0;
339 size_t nAfterSegmentTimedOut = 0;
340 nSegments = 401;
341 sendNackInsteadOfDropping = false;
342 defaultSegmentToSend = 47;
343 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
344
345 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
346 acceptValidator);
347 connectSignals(fetcher);
348 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
349 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
350 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
351 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
352
353 face.processEvents(1_s);
354
355 BOOST_CHECK_EQUAL(nErrors, 0);
356 BOOST_CHECK_EQUAL(nCompletions, 1);
357 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
358 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
359 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
360 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
361 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
362}
363
364BOOST_AUTO_TEST_CASE(WindowSize)
365{
366 DummyValidator acceptValidator;
367 size_t nAfterSegmentReceived = 0;
368 size_t nAfterSegmentValidated = 0;
369 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
370 acceptValidator);
371 connectSignals(fetcher);
372 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
373 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
374
375 advanceClocks(10_ms); // T+10ms
376
377 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
378 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
379 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, 0);
380 BOOST_CHECK_EQUAL(fetcher->m_cwnd, 1.0);
381 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, std::numeric_limits<double>::max());
382 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, 1);
383 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
384 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 0);
385 BOOST_CHECK_EQUAL(fetcher->m_highInterest, 0);
386 BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
387 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
388 BOOST_CHECK_EQUAL(fetcher->m_nReceived, 0);
389 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 0);
390 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), 1);
391 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
392
393 double oldCwnd = fetcher->m_cwnd;
394 double oldSsthresh = fetcher->m_ssthresh;
395 uint64_t oldNextSegmentNum = fetcher->m_nextSegmentNum;
396
397 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
398
399 advanceClocks(10_ms); //T+20ms
400
401 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
402 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
403 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
404 // +2 below because m_nextSegmentNum will be incremented in the receive callback if segment 0 is
405 // the first received
406 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 2);
407 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
408 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
409 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd + fetcher->m_options.aiStep);
410 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
411 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 14);
412 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
413 BOOST_CHECK_EQUAL(fetcher->m_highData, 0);
414 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
415 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 1);
416 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
417 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1 + fetcher->m_cwnd);
418
419 oldCwnd = fetcher->m_cwnd;
420 oldNextSegmentNum = fetcher->m_nextSegmentNum;
421
422 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
423
424 advanceClocks(10_ms); //T+30ms
425
426 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
427 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
428 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
429 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
430 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
431 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
432 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
433 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
434 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 28);
435 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
436 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
437 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
438 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 2);
439 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
440 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2 + fetcher->m_cwnd);
441
442 oldCwnd = fetcher->m_cwnd;
443 oldNextSegmentNum = fetcher->m_nextSegmentNum;
444
445 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
446
447 advanceClocks(10_ms); //T+40ms
448
449 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 10_ms);
450 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 0);
451 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
452 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum + fetcher->m_options.aiStep + 1);
453 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd + fetcher->m_options.aiStep);
454 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldSsthresh);
455 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, fetcher->m_cwnd);
456 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
457 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
458 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
459 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
460 BOOST_CHECK_EQUAL(fetcher->m_recPoint, 0);
461 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
462 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), fetcher->m_cwnd);
463 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3 + fetcher->m_cwnd);
464
465 oldCwnd = fetcher->m_cwnd;
466 oldSsthresh = fetcher->m_ssthresh;
467 oldNextSegmentNum = fetcher->m_nextSegmentNum;
468 size_t oldSentInterestsSize = face.sentInterests.size();
469
470 nackLastInterest(lp::NackReason::CONGESTION); //T+50ms
471
472 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 20_ms);
473 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
474 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
475 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
476 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
477 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
478 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
479 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
480 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
481 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
482 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
483 BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
484 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
485 // The Nacked segment will remain in pendingSegments, so the size of the structure doesn't change
486 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
487 BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
488
489 advanceClocks(10_ms); //T+60ms
490
491 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 30_ms);
492 BOOST_CHECK_EQUAL(fetcher->m_retxQueue.size(), 1);
493 BOOST_CHECK_EQUAL(fetcher->m_versionedDataName, "/hello/world/version0");
494 BOOST_CHECK_EQUAL(fetcher->m_nextSegmentNum, oldNextSegmentNum);
495 BOOST_CHECK_EQUAL(fetcher->m_cwnd, oldCwnd / 2.0);
496 BOOST_CHECK_EQUAL(fetcher->m_ssthresh, oldCwnd / 2.0);
497 BOOST_CHECK_EQUAL(fetcher->m_nSegmentsInFlight, oldCwnd - 1);
498 BOOST_CHECK_EQUAL(fetcher->m_nSegments, 0);
499 BOOST_CHECK_EQUAL(fetcher->m_nBytesReceived, 42);
500 BOOST_CHECK_EQUAL(fetcher->m_highInterest, fetcher->m_nextSegmentNum - 1);
501 BOOST_CHECK_EQUAL(fetcher->m_highData, 2);
502 BOOST_CHECK_EQUAL(fetcher->m_recPoint, fetcher->m_nextSegmentNum - 1);
503 BOOST_CHECK_EQUAL(fetcher->m_receivedSegments.size(), 3);
504 BOOST_CHECK_EQUAL(fetcher->m_pendingSegments.size(), oldCwnd);
505 BOOST_CHECK_EQUAL(face.sentInterests.size(), oldSentInterestsSize);
506
507 // Properly end test case
508 lp::Nack nack = makeNack(face.sentInterests[face.sentInterests.size() - 2], lp::NackReason::NO_ROUTE);
509 face.receive(nack);
510 advanceClocks(10_ms); //T+70ms
511
512 BOOST_CHECK_EQUAL(nErrors, 1);
513 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::NACK_ERROR));
514 BOOST_CHECK_EQUAL(nCompletions, 0);
515}
516
517BOOST_AUTO_TEST_CASE(MissingSegmentNum)
518{
519 DummyValidator acceptValidator;
520 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700521 acceptValidator);
522 connectSignals(fetcher);
523
524 advanceClocks(10_ms);
525
526 const uint8_t buffer[] = "Hello, world!";
527 auto data = makeData("/hello/world/version0/no-segment");
528 data->setContent(buffer, sizeof(buffer));
529
530 face.receive(*data);
531 advanceClocks(10_ms);
532
533 BOOST_CHECK_EQUAL(nErrors, 1);
534 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::DATA_HAS_NO_SEGMENT));
535 BOOST_CHECK_EQUAL(nCompletions, 0);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500536}
537
Eric Newberrye345baa2018-05-23 18:17:07 -0700538BOOST_AUTO_TEST_CASE(MoreSegmentsThanNSegments)
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500539{
Eric Newberrycc910cd2018-05-06 17:01:40 -0700540 DummyValidator acceptValidator;
Eric Newberrye345baa2018-05-23 18:17:07 -0700541 size_t nAfterSegmentReceived = 0;
542 size_t nAfterSegmentValidated = 0;
543 size_t nAfterSegmentNacked = 0;
544 size_t nAfterSegmentTimedOut = 0;
545 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700546 acceptValidator);
547 connectSignals(fetcher);
Eric Newberrye345baa2018-05-23 18:17:07 -0700548 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
549 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
550 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
551 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
552
Davide Pesavento0f830802018-01-16 23:58:58 -0500553 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500554
Eric Newberrye345baa2018-05-23 18:17:07 -0700555 face.receive(*makeDataSegment("/hello/world/version0", 0, false));
Davide Pesavento0f830802018-01-16 23:58:58 -0500556 advanceClocks(10_ms);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500557
Eric Newberrye345baa2018-05-23 18:17:07 -0700558 BOOST_CHECK_EQUAL(nErrors, 0);
559 BOOST_CHECK_EQUAL(nCompletions, 0);
Muktadir R Chowdhuryf58f8f42015-09-02 11:56:49 -0500560
Eric Newberrye345baa2018-05-23 18:17:07 -0700561 face.receive(*makeDataSegment("/hello/world/version0", 1, false));
Davide Pesavento0f830802018-01-16 23:58:58 -0500562 advanceClocks(10_ms);
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500563
Eric Newberrye345baa2018-05-23 18:17:07 -0700564 BOOST_CHECK_EQUAL(nErrors, 0);
565 BOOST_CHECK_EQUAL(nCompletions, 0);
566
567 face.receive(*makeDataSegment("/hello/world/version0", 2, false));
568 advanceClocks(10_ms);
569
570 BOOST_CHECK_EQUAL(nErrors, 0);
571 BOOST_CHECK_EQUAL(nCompletions, 0);
572
573 face.receive(*makeDataSegment("/hello/world/version0", 3, false));
574 advanceClocks(10_ms);
575
576 BOOST_CHECK_EQUAL(nErrors, 0);
577 BOOST_CHECK_EQUAL(nCompletions, 0);
578
579 auto data4 = makeDataSegment("/hello/world/version0", 4, false);
580 data4->setFinalBlock(name::Component::fromSegment(2));
581 face.receive(*data4);
582 advanceClocks(10_ms);
583
584 BOOST_CHECK_EQUAL(nErrors, 0);
585 BOOST_CHECK_EQUAL(nCompletions, 1);
586 BOOST_CHECK_EQUAL(dataSize, 14 * 3);
587 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 5);
588 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 5);
589 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
590 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
Muktadir R Chowdhury2bc2df02016-04-05 16:55:41 -0500591}
592
Eric Newberrye345baa2018-05-23 18:17:07 -0700593BOOST_AUTO_TEST_CASE(DuplicateNack)
594{
595 DummyValidator acceptValidator;
596 size_t nAfterSegmentReceived = 0;
597 size_t nAfterSegmentValidated = 0;
598 size_t nAfterSegmentNacked = 0;
599 size_t nAfterSegmentTimedOut = 0;
600 nSegments = 401;
601 segmentsToDropOrNack.push(0);
602 segmentsToDropOrNack.push(200);
603 sendNackInsteadOfDropping = true;
604 nackReason = lp::NackReason::DUPLICATE;
605 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
606
607 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
608 acceptValidator);
609 connectSignals(fetcher);
610 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
611 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
612 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
613 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
614
615 face.processEvents(1_s);
616
617 BOOST_CHECK_EQUAL(nErrors, 0);
618 BOOST_CHECK_EQUAL(nCompletions, 1);
619 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
620 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
621 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
622 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
623 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
624}
625
626BOOST_AUTO_TEST_CASE(CongestionNack)
627{
628 DummyValidator acceptValidator;
629 size_t nAfterSegmentReceived = 0;
630 size_t nAfterSegmentValidated = 0;
631 size_t nAfterSegmentNacked = 0;
632 size_t nAfterSegmentTimedOut = 0;
633 nSegments = 401;
634 segmentsToDropOrNack.push(0);
635 segmentsToDropOrNack.push(200);
636 sendNackInsteadOfDropping = true;
637 nackReason = lp::NackReason::CONGESTION;
638 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
639
640 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
641 acceptValidator);
642 connectSignals(fetcher);
643 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
644 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
645 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
646 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
647
648 face.processEvents(1_s);
649
650 BOOST_CHECK_EQUAL(nErrors, 0);
651 BOOST_CHECK_EQUAL(nCompletions, 1);
652 BOOST_CHECK_EQUAL(dataSize, 14 * 401);
653 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 401);
654 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 401);
655 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 2);
656 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
657}
658
659BOOST_AUTO_TEST_CASE(OtherNackReason)
660{
661 DummyValidator acceptValidator;
662 size_t nAfterSegmentReceived = 0;
663 size_t nAfterSegmentValidated = 0;
664 size_t nAfterSegmentNacked = 0;
665 size_t nAfterSegmentTimedOut = 0;
666 segmentsToDropOrNack.push(0);
667 sendNackInsteadOfDropping = true;
668 nackReason = lp::NackReason::NO_ROUTE;
669 face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
670
671 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
672 acceptValidator);
673 connectSignals(fetcher);
674 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
675 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
676 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
677 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
678
679 face.processEvents(1_s);
680
681 BOOST_CHECK_EQUAL(nErrors, 1);
682 BOOST_CHECK_EQUAL(nCompletions, 0);
683 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
684 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
685 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 1);
686 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
687 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
688}
689
690BOOST_AUTO_TEST_CASE(ValidationFailure)
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000691{
692 DummyValidator validator;
Eric Newberrycc910cd2018-05-06 17:01:40 -0700693 validator.getPolicy().setResultCallback([] (const Name& name) {
694 return name.at(-1).toSegment() % 2 == 0;
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000695 });
Eric Newberrye345baa2018-05-23 18:17:07 -0700696 shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
Eric Newberrycc910cd2018-05-06 17:01:40 -0700697 validator);
698 connectSignals(fetcher);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000699
700 auto data1 = makeDataSegment("/hello/world", 0, false);
701 auto data2 = makeDataSegment("/hello/world", 1, true);
702
703 size_t nRecvSegments = 0;
704 fetcher->afterSegmentReceived.connect([&nRecvSegments] (const Data& receivedSegment) {
705 ++nRecvSegments;
706 });
707
708 size_t nValidatedSegments = 0;
709 fetcher->afterSegmentValidated.connect([&nValidatedSegments] (const Data& validatedSegment) {
710 ++nValidatedSegments;
711 });
712
Davide Pesavento0f830802018-01-16 23:58:58 -0500713 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000714
Eric Newberrye345baa2018-05-23 18:17:07 -0700715 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
716
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000717 face.receive(*data1);
718
Davide Pesavento0f830802018-01-16 23:58:58 -0500719 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000720
Eric Newberrye345baa2018-05-23 18:17:07 -0700721 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 100_ms);
722
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000723 face.receive(*data2);
724
Davide Pesavento0f830802018-01-16 23:58:58 -0500725 advanceClocks(10_ms, 10);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000726
Eric Newberrye345baa2018-05-23 18:17:07 -0700727 BOOST_CHECK_EQUAL(fetcher->m_timeLastSegmentReceived, time::steady_clock::now() - 200_ms);
Muktadir Chowdhury1c109b42018-01-10 08:36:00 +0000728 BOOST_CHECK_EQUAL(nRecvSegments, 2);
729 BOOST_CHECK_EQUAL(nValidatedSegments, 1);
730 BOOST_CHECK_EQUAL(nErrors, 1);
731}
732
Ashlesh Gawande679dbb02018-08-21 11:43:21 -0500733BOOST_AUTO_TEST_CASE(Stop)
734{
735 DummyValidator acceptValidator;
736
737 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
738 connectSignals(fetcher);
739 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
740
741 fetcher->stop();
742 advanceClocks(10_ms);
743 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
744
745 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
746 advanceClocks(10_ms);
747 BOOST_CHECK_EQUAL(nErrors, 0);
748 BOOST_CHECK_EQUAL(nCompletions, 0);
749
750 fetcher.reset();
751 BOOST_CHECK_EQUAL(fetcher.use_count(), 0);
752
753 // Make sure we can re-assign w/o any complains from ASan
754 fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
755 connectSignals(fetcher);
756 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
757
758 advanceClocks(10_ms);
759
760 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
761
762 advanceClocks(10_ms);
763 BOOST_CHECK_EQUAL(nErrors, 0);
764 BOOST_CHECK_EQUAL(nCompletions, 1);
765 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
766
767 // Stop from callback
768 bool fetcherStopped = false;
769
770 fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
771 fetcher->afterSegmentReceived.connect([&fetcher, &fetcherStopped] (const Data& data) {
772 fetcherStopped = true;
773 fetcher->stop();
774 });
775 BOOST_CHECK_EQUAL(fetcher.use_count(), 2);
776
777 advanceClocks(10_ms);
778
779 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
780
781 advanceClocks(10_ms);
782 BOOST_CHECK(fetcherStopped);
783 BOOST_CHECK_EQUAL(fetcher.use_count(), 1);
784}
785
786BOOST_AUTO_TEST_CASE(Lifetime)
787{
788 // BasicSingleSegment, but with scoped fetcher
789
790 DummyValidator acceptValidator;
791 size_t nAfterSegmentReceived = 0;
792 size_t nAfterSegmentValidated = 0;
793 size_t nAfterSegmentNacked = 0;
794 size_t nAfterSegmentTimedOut = 0;
795
796 weak_ptr<SegmentFetcher> weakFetcher;
797 {
798 auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator);
799 weakFetcher = fetcher;
800 connectSignals(fetcher);
801
802 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
803 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
804 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
805 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
806 }
807
808 advanceClocks(10_ms);
809 BOOST_CHECK_EQUAL(weakFetcher.expired(), false);
810
811 face.receive(*makeDataSegment("/hello/world/version0", 0, true));
812
813 advanceClocks(10_ms);
814
815 BOOST_CHECK_EQUAL(nErrors, 0);
816 BOOST_CHECK_EQUAL(nCompletions, 1);
817 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 1);
818 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 1);
819 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
820 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 0);
821 BOOST_CHECK_EQUAL(weakFetcher.expired(), true);
822}
823
824BOOST_AUTO_TEST_CASE(OutOfScopeTimeout)
825{
826 DummyValidator acceptValidator;
827 SegmentFetcher::Options options;
828 options.maxTimeout = 3000_ms;
829
830 size_t nAfterSegmentReceived = 0;
831 size_t nAfterSegmentValidated = 0;
832 size_t nAfterSegmentNacked = 0;
833 size_t nAfterSegmentTimedOut = 0;
834
835 weak_ptr<SegmentFetcher> weakFetcher;
836 {
837 auto fetcher = SegmentFetcher::start(face, Interest("/localhost/nfd/faces/list"),
838 acceptValidator, options);
839 weakFetcher = fetcher;
840 connectSignals(fetcher);
841 fetcher->afterSegmentReceived.connect(bind([&nAfterSegmentReceived] { ++nAfterSegmentReceived; }));
842 fetcher->afterSegmentValidated.connect(bind([&nAfterSegmentValidated] { ++nAfterSegmentValidated; }));
843 fetcher->afterSegmentNacked.connect(bind([&nAfterSegmentNacked] { ++nAfterSegmentNacked; }));
844 fetcher->afterSegmentTimedOut.connect(bind([&nAfterSegmentTimedOut] { ++nAfterSegmentTimedOut; }));
845 }
846
847 advanceClocks(500_ms, 7);
848 BOOST_CHECK_EQUAL(weakFetcher.expired(), true);
849
850 BOOST_CHECK_EQUAL(nErrors, 1);
851 BOOST_CHECK_EQUAL(nCompletions, 0);
852 BOOST_CHECK_EQUAL(nAfterSegmentReceived, 0);
853 BOOST_CHECK_EQUAL(nAfterSegmentValidated, 0);
854 BOOST_CHECK_EQUAL(nAfterSegmentNacked, 0);
855 BOOST_CHECK_EQUAL(nAfterSegmentTimedOut, 2);
856}
857
Junxiao Shid5827ce2016-07-14 20:49:37 +0000858BOOST_AUTO_TEST_SUITE_END() // TestSegmentFetcher
859BOOST_AUTO_TEST_SUITE_END() // Util
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -0700860
861} // namespace tests
862} // namespace util
863} // namespace ndn