blob: 6cfa23e93e62c4e36861ff0b0dd66b64d2357cf0 [file] [log] [blame]
Weiwei Liu245d7912016-07-28 00:04:25 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoe9c69852017-11-04 18:08:37 -04002/*
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -08003 * Copyright (c) 2016-2019, Regents of the University of California,
Davide Pesavento958896e2017-01-19 00:52:04 -05004 * Colorado State University,
5 * University Pierre & Marie Curie, Sorbonne University.
Weiwei Liu245d7912016-07-28 00:04:25 -07006 *
7 * This file is part of ndn-tools (Named Data Networking Essential Tools).
8 * See AUTHORS.md for complete list of ndn-tools authors and contributors.
9 *
10 * ndn-tools is free software: you can redistribute it and/or modify it under the terms
11 * of the GNU General Public License as published by the Free Software Foundation,
12 * either version 3 of the License, or (at your option) any later version.
13 *
14 * ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 * PURPOSE. See the GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
20 *
21 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
22 *
23 * @author Weiwei Liu
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000024 * @author Chavoosh Ghasemi
schneiderklausd8197df2019-03-16 11:31:40 -070025 * @author Klaus Schneider
Weiwei Liu245d7912016-07-28 00:04:25 -070026 */
27
Klaus Schneider9e5122b2019-03-19 17:03:25 -070028#include "tools/chunks/catchunks/pipeline-interests-cubic.hpp"
Weiwei Liu245d7912016-07-28 00:04:25 -070029
30#include "pipeline-interests-fixture.hpp"
31
32namespace ndn {
33namespace chunks {
Weiwei Liu245d7912016-07-28 00:04:25 -070034namespace tests {
35
36using namespace ndn::tests;
37
Klaus Schneider9e5122b2019-03-19 17:03:25 -070038class PipelineInterestCubicFixture : public PipelineInterestsFixture
Weiwei Liu245d7912016-07-28 00:04:25 -070039{
40public:
Klaus Schneider9e5122b2019-03-19 17:03:25 -070041 PipelineInterestCubicFixture()
Davide Pesavento97a33b22019-10-17 22:10:47 -040042 : rttEstimator(makeRttEstimatorOptions())
Weiwei Liu245d7912016-07-28 00:04:25 -070043 {
Davide Pesavento97a33b22019-10-17 22:10:47 -040044 opt.isQuiet = true;
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000045 createPipeline();
46 }
47
48 void
49 createPipeline()
50 {
Klaus Schneider9e5122b2019-03-19 17:03:25 -070051 auto pline = make_unique<PipelineInterestsCubic>(face, rttEstimator, opt);
schneiderklausd8197df2019-03-16 11:31:40 -070052 pipeline = pline.get();
Weiwei Liu245d7912016-07-28 00:04:25 -070053 setPipeline(std::move(pline));
54 }
55
56private:
Davide Pesavento5e3773d2019-08-22 15:35:08 -040057 static shared_ptr<RttEstimatorWithStats::Options>
Weiwei Liu245d7912016-07-28 00:04:25 -070058 makeRttEstimatorOptions()
59 {
Davide Pesavento5e3773d2019-08-22 15:35:08 -040060 auto rttOptions = make_shared<RttEstimatorWithStats::Options>();
61 rttOptions->alpha = 0.125;
62 rttOptions->beta = 0.25;
63 rttOptions->k = 8;
64 rttOptions->initialRto = 1_s;
65 rttOptions->minRto = 200_ms;
66 rttOptions->maxRto = 4_s;
67 rttOptions->rtoBackoffMultiplier = 2;
Weiwei Liu245d7912016-07-28 00:04:25 -070068 return rttOptions;
69 }
70
71protected:
Davide Pesavento97a33b22019-10-17 22:10:47 -040072 Options opt;
Davide Pesavento5e3773d2019-08-22 15:35:08 -040073 RttEstimatorWithStats rttEstimator;
Klaus Schneider9e5122b2019-03-19 17:03:25 -070074 PipelineInterestsCubic* pipeline;
Davide Pesaventoba560662019-06-26 22:45:44 -040075 static constexpr double MARGIN = 0.001;
Weiwei Liu245d7912016-07-28 00:04:25 -070076};
77
Klaus Schneider9e5122b2019-03-19 17:03:25 -070078constexpr double PipelineInterestCubicFixture::MARGIN;
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000079
Weiwei Liu245d7912016-07-28 00:04:25 -070080BOOST_AUTO_TEST_SUITE(Chunks)
Klaus Schneider9e5122b2019-03-19 17:03:25 -070081BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsCubic, PipelineInterestCubicFixture)
Weiwei Liu245d7912016-07-28 00:04:25 -070082
83BOOST_AUTO_TEST_CASE(SlowStart)
84{
85 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -070086 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -070087
schneiderklausd8197df2019-03-16 11:31:40 -070088 double preCwnd = pipeline->m_cwnd;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080089 run(name);
Weiwei Liu245d7912016-07-28 00:04:25 -070090 advanceClocks(io, time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -040091 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
Weiwei Liu245d7912016-07-28 00:04:25 -070092
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080093 for (uint64_t i = 0; i < nDataSegments - 1; ++i) {
Weiwei Liu245d7912016-07-28 00:04:25 -070094 face.receive(*makeDataWithSegment(i));
95 advanceClocks(io, time::nanoseconds(1));
schneiderklausd8197df2019-03-16 11:31:40 -070096 BOOST_CHECK_CLOSE(pipeline->m_cwnd - preCwnd, 1, MARGIN);
97 preCwnd = pipeline->m_cwnd;
Weiwei Liu245d7912016-07-28 00:04:25 -070098 }
Davide Pesaventoe9c69852017-11-04 18:08:37 -040099
100 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments - 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700101}
102
Weiwei Liu245d7912016-07-28 00:04:25 -0700103
104BOOST_AUTO_TEST_CASE(Timeout)
105{
106 nDataSegments = 8;
schneiderklausd8197df2019-03-16 11:31:40 -0700107 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -0700108
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800109 run(name);
Weiwei Liu245d7912016-07-28 00:04:25 -0700110 advanceClocks(io, time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400111 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700112
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800113 // receive segment 0, 1, and 2
114 for (uint64_t i = 0; i < 3; ++i) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700115 face.receive(*makeDataWithSegment(i));
116 advanceClocks(io, time::nanoseconds(1));
117 }
118
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400119 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 3);
schneiderklausd8197df2019-03-16 11:31:40 -0700120 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800121 BOOST_CHECK_EQUAL(face.sentInterests.size(), 7); // request for segment 7 has been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700122
123 advanceClocks(io, time::milliseconds(100));
124
125 // receive segment 4
126 face.receive(*makeDataWithSegment(4));
127 advanceClocks(io, time::nanoseconds(1));
128
129 // receive segment 5
130 face.receive(*makeDataWithSegment(5));
131 advanceClocks(io, time::nanoseconds(1));
132
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400133 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700134 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 6.0, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800135 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all the segment requests have been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700136
schneiderklausd8197df2019-03-16 11:31:40 -0700137 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 0);
138 BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 0);
139 BOOST_CHECK_EQUAL(pipeline->m_nMarkDecr, 0);
140 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 0);
141 BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
142 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 0);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700143
144 // timeout segment 3 & 6
Weiwei Liu245d7912016-07-28 00:04:25 -0700145 advanceClocks(io, time::milliseconds(150));
schneiderklausd8197df2019-03-16 11:31:40 -0700146 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 2);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700147 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700148 BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 1);
149 BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700150
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400151 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700152 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // window size drop to 0.7x of previous size
153 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700154
155 // receive segment 6, retransmit 3
156 face.receive(*makeDataWithSegment(6));
157 advanceClocks(io, time::nanoseconds(1));
158
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400159 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700160 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // congestion avoidance
schneiderklausd8197df2019-03-16 11:31:40 -0700161 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
162 BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700163
schneiderklausd8197df2019-03-16 11:31:40 -0700164 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 2);
165 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 2);
166 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts,
167 pipeline->m_nRetransmitted + pipeline->m_nSkippedRetx);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700168
Weiwei Liu245d7912016-07-28 00:04:25 -0700169}
170
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000171BOOST_AUTO_TEST_CASE(CongestionMarksWithCwa)
172{
173 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700174 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000175
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800176 run(name);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000177 advanceClocks(io, time::nanoseconds(1));
178 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
179
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800180 // receive segments 0 to 4
181 for (uint64_t i = 0; i < 5; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000182 face.receive(*makeDataWithSegment(i));
183 advanceClocks(io, time::nanoseconds(1));
184 }
185
186 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700187 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 6.0, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000188
189 // receive segment 5 with congestion mark
190 face.receive(*makeDataWithSegmentAndCongMark(5));
191 advanceClocks(io, time::nanoseconds(1));
192
193 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700194 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // window size drops to 1/2 of previous size
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800195 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000196
197 // receive the last segment with congestion mark
198 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
199 advanceClocks(io, time::nanoseconds(1));
200
201 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700202 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // conservative window adaption (window size should not decrease)
schneiderklausd8197df2019-03-16 11:31:40 -0700203 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000204
205 // make sure no interest is retransmitted for marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700206 BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
207 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000208
209 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700210 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000211}
212
213BOOST_AUTO_TEST_CASE(CongestionMarksWithoutCwa)
214{
215 opt.disableCwa = true;
216 createPipeline();
217
218 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700219 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000220
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800221 run(name);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000222 advanceClocks(io, time::nanoseconds(1));
223 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
224
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800225 // receive segments 0 to 4
226 for (uint64_t i = 0; i < 5; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000227 face.receive(*makeDataWithSegment(i));
228 advanceClocks(io, time::nanoseconds(1));
229 }
230
231 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700232 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 6.0, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000233
234 // receive segment 5 with congestion mark
235 face.receive(*makeDataWithSegmentAndCongMark(5));
236 advanceClocks(io, time::nanoseconds(1));
237
238 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700239 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // window size drops to 1/2 of previous size
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800240 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000241
242 // receive the last segment with congestion mark
243 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
244 advanceClocks(io, time::nanoseconds(1));
245
246 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700247 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.94,
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000248 MARGIN); // window size should decrease, as cwa is disabled
schneiderklausd8197df2019-03-16 11:31:40 -0700249 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000250
251 // make sure no interest is retransmitted for marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700252 BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
253 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000254
255 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700256 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000257}
258
259BOOST_AUTO_TEST_CASE(IgnoreCongestionMarks)
260{
261 opt.ignoreCongMarks = true;
262 createPipeline();
263
264 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700265 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000266
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800267 run(name);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000268 advanceClocks(io, time::nanoseconds(1));
269 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
270
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800271 // receive segments 0 to 5
272 for (uint64_t i = 0; i < 6; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000273 face.receive(*makeDataWithSegment(i));
274 advanceClocks(io, time::nanoseconds(1));
275 }
276
277 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700278 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 7.0, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800279 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000280
281 // receive the last segment with congestion mark
282 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
283 advanceClocks(io, time::nanoseconds(1));
284
285 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700286 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 8.0, MARGIN); // window size increases
schneiderklausd8197df2019-03-16 11:31:40 -0700287 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000288
289 // make sure no interest is retransmitted for marked data packet
schneiderklausd8197df2019-03-16 11:31:40 -0700290 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000291
292 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700293 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 1);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000294}
295
Weiwei Liu245d7912016-07-28 00:04:25 -0700296BOOST_AUTO_TEST_CASE(Nack)
297{
298 nDataSegments = 5;
schneiderklausd8197df2019-03-16 11:31:40 -0700299 pipeline->m_cwnd = 10.0;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800300 run(name);
301 advanceClocks(io, time::nanoseconds(1));
302
303 face.receive(*makeDataWithSegment(0));
Weiwei Liu245d7912016-07-28 00:04:25 -0700304 advanceClocks(io, time::nanoseconds(1));
305
306 face.receive(*makeDataWithSegment(1));
307 advanceClocks(io, time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400308
309 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800310 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 10);
Weiwei Liu245d7912016-07-28 00:04:25 -0700311
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800312 // receive a nack with NackReason::DUPLICATE for segment 1
Weiwei Liu245d7912016-07-28 00:04:25 -0700313 auto nack1 = makeNack(face.sentInterests[1], lp::NackReason::DUPLICATE);
314 face.receive(nack1);
315 advanceClocks(io, time::nanoseconds(1));
316
317 // nack1 is ignored
318 BOOST_CHECK_EQUAL(hasFailed, false);
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400319 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700320 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700321
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800322 // receive a nack with NackReason::CONGESTION for segment 2
Weiwei Liu245d7912016-07-28 00:04:25 -0700323 auto nack2 = makeNack(face.sentInterests[2], lp::NackReason::CONGESTION);
324 face.receive(nack2);
325 advanceClocks(io, time::nanoseconds(1));
326
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800327 // segment 2 is retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700328 BOOST_CHECK_EQUAL(pipeline->m_retxCount[2], 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700329
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800330 // receive a nack with NackReason::NONE for segment 3
Weiwei Liu245d7912016-07-28 00:04:25 -0700331 auto nack3 = makeNack(face.sentInterests[3], lp::NackReason::NONE);
332 face.receive(nack3);
333 advanceClocks(io, time::nanoseconds(1));
334
335 // Other types of Nack will trigger a failure
336 BOOST_CHECK_EQUAL(hasFailed, true);
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400337 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700338}
339
340BOOST_AUTO_TEST_CASE(FinalBlockIdNotSetAtBeginning)
341{
342 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700343 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800344 run(name);
Weiwei Liu245d7912016-07-28 00:04:25 -0700345 advanceClocks(io, time::nanoseconds(1));
346
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800347 // receive segment 0 without FinalBlockId
348 face.receive(*makeDataWithSegment(0, false));
Weiwei Liu245d7912016-07-28 00:04:25 -0700349 advanceClocks(io, time::nanoseconds(1));
350
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800351 // interests for segment 0 - 5 have been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700352 BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800353 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 1);
schneiderklausd8197df2019-03-16 11:31:40 -0700354 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, false);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800355 // pending interests: segment 1, 2, 3, 4, 5
Weiwei Liu245d7912016-07-28 00:04:25 -0700356 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 5);
357
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800358 // receive segment 1 with FinalBlockId
359 face.receive(*makeDataWithSegment(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700360 advanceClocks(io, time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800361 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700362 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
Weiwei Liu245d7912016-07-28 00:04:25 -0700363
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800364 // pending interests for segment 1, 4, 5 haven been removed
365 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700366}
367
368BOOST_AUTO_TEST_CASE(FailureBeforeFinalBlockIdReceived)
369{
370 // failed to retrieve segNo while the FinalBlockId has not yet been
371 // set, and later received a FinalBlockId >= segNo, i.e. segNo is
372 // part of the content.
373
374 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700375 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800376 run(name);
377 advanceClocks(io, time::nanoseconds(1));
378
379 // receive segment 0 without FinalBlockId
380 face.receive(*makeDataWithSegment(0, false));
Weiwei Liu245d7912016-07-28 00:04:25 -0700381 advanceClocks(io, time::nanoseconds(1));
382
383 // receive segment 1 without FinalBlockId
384 face.receive(*makeDataWithSegment(1, false));
385 advanceClocks(io, time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800386
387 // interests for segment 0 - 7 have been sent
388 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
Weiwei Liu245d7912016-07-28 00:04:25 -0700389
390 // receive nack with NackReason::NONE for segment 3
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800391 auto nack = makeNack(face.sentInterests[3], lp::NackReason::NONE);
Weiwei Liu245d7912016-07-28 00:04:25 -0700392 face.receive(nack);
393 advanceClocks(io, time::nanoseconds(1));
394
395 // error not triggered
396 // pending interests for segment > 3 haven been removed
397 BOOST_CHECK_EQUAL(hasFailed, false);
398 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 1);
399
400 // receive segment 2 with FinalBlockId
401 face.receive(*makeDataWithSegment(2));
402 advanceClocks(io, time::nanoseconds(1));
403
404 // error triggered since segment 3 is part of the content
405 BOOST_CHECK_EQUAL(hasFailed, true);
406}
407
408BOOST_AUTO_TEST_CASE(SpuriousFailureBeforeFinalBlockIdReceived)
409{
410 // failed to retrieve segNo while the FinalBlockId has not yet been
411 // set, and later received a FinalBlockId < segNo, i.e. segNo is
412 // not part of the content, and it was actually a spurious failure
413
414 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700415 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800416 run(name);
417 advanceClocks(io, time::nanoseconds(1));
418
419 // receive segment 0 without FinalBlockId
420 face.receive(*makeDataWithSegment(0, false));
Weiwei Liu245d7912016-07-28 00:04:25 -0700421 advanceClocks(io, time::nanoseconds(1));
422
423 // receive segment 1 without FinalBlockId
424 face.receive(*makeDataWithSegment(1, false));
425 advanceClocks(io, time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800426
427 // interests for segment 0 - 7 have been sent
428 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
Weiwei Liu245d7912016-07-28 00:04:25 -0700429
430 // receive nack with NackReason::NONE for segment 4
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800431 auto nack = makeNack(face.sentInterests[4], lp::NackReason::NONE);
Weiwei Liu245d7912016-07-28 00:04:25 -0700432 face.receive(nack);
433 advanceClocks(io, time::nanoseconds(1));
434
435 // error not triggered
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800436 // pending interests for segment > 3 have been removed
Weiwei Liu245d7912016-07-28 00:04:25 -0700437 BOOST_CHECK_EQUAL(hasFailed, false);
438 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
439
440 // receive segment 2 with FinalBlockId
441 face.receive(*makeDataWithSegment(2));
442 advanceClocks(io, time::nanoseconds(1));
443
444 // timeout segment 3
Davide Pesavento958896e2017-01-19 00:52:04 -0500445 advanceClocks(io, time::seconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700446
447 // segment 3 is retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700448 BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700449
450 // receive segment 3
451 face.receive(*makeDataWithSegment(3));
452 advanceClocks(io, time::nanoseconds(1));
453
454 BOOST_CHECK_EQUAL(hasFailed, false);
455}
456
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500457BOOST_AUTO_TEST_CASE(SegmentInfoMaintenance)
458{
459 // test that m_segmentInfo is properly maintained when
460 // a segment is received after two consecutive timeouts
461
462 nDataSegments = 3;
463
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800464 run(name);
465 advanceClocks(io, time::nanoseconds(1));
466
467 // receive segment 0
468 face.receive(*makeDataWithSegment(0));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500469 advanceClocks(io, time::nanoseconds(1));
470
471 // receive segment 1
472 face.receive(*makeDataWithSegment(1));
473 advanceClocks(io, time::nanoseconds(1));
474
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800475 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500476
477 // check if segment 2's state is FirstTimeSent
schneiderklausd8197df2019-03-16 11:31:40 -0700478 auto it = pipeline->m_segmentInfo.find(2);
479 BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500480 BOOST_CHECK(it->second.state == SegmentState::FirstTimeSent);
481
482 // timeout segment 2 twice
483 advanceClocks(io, time::milliseconds(400), 3);
484
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800485 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500486
487 // check if segment 2's state is Retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700488 it = pipeline->m_segmentInfo.find(2);
489 BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500490 BOOST_CHECK(it->second.state == SegmentState::Retransmitted);
491
492 // check if segment 2 was retransmitted twice
schneiderklausd8197df2019-03-16 11:31:40 -0700493 BOOST_CHECK_EQUAL(pipeline->m_retxCount.at(2), 2);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500494
495 // receive segment 2 the first time
496 face.receive(*makeDataWithSegment(2));
497 advanceClocks(io, time::nanoseconds(1));
498
499 // check if segment 2 was erased from m_segmentInfo
schneiderklausd8197df2019-03-16 11:31:40 -0700500 it = pipeline->m_segmentInfo.find(2);
501 BOOST_CHECK(it == pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500502
503 auto prevRtt = rttEstimator.getAvgRtt();
504 auto prevRto = rttEstimator.getEstimatedRto();
505
506 // receive segment 2 the second time
507 face.receive(*makeDataWithSegment(2));
508 advanceClocks(io, time::nanoseconds(1));
509
510 // nothing changed
schneiderklausd8197df2019-03-16 11:31:40 -0700511 it = pipeline->m_segmentInfo.find(2);
512 BOOST_CHECK(it == pipeline->m_segmentInfo.end());
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800513 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500514 BOOST_CHECK_EQUAL(rttEstimator.getAvgRtt(), prevRtt);
515 BOOST_CHECK_EQUAL(rttEstimator.getEstimatedRto(), prevRto);
516}
517
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400518BOOST_AUTO_TEST_CASE(PrintSummaryWithNoRttMeasurements)
519{
520 // test the console ouptut when no RTT measurement is available,
521 // to make sure a proper message will be printed out
522
523 std::stringstream ss;
524
525 // change the underlying buffer and save the old buffer
526 auto oldBuf = std::cerr.rdbuf(ss.rdbuf());
527
schneiderklausd8197df2019-03-16 11:31:40 -0700528 pipeline->printSummary();
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400529 std::string line;
530
531 bool found = false;
532 while (std::getline(ss, line)) {
533 if (line == "RTT stats unavailable") {
534 found = true;
535 break;
536 }
537 }
538 BOOST_CHECK(found);
539 std::cerr.rdbuf(oldBuf); // reset
540}
541
Ryan Wickman034f30f2018-06-06 11:11:11 -0500542BOOST_AUTO_TEST_CASE(StopsWhenFileSizeLessThanChunkSize)
543{
544 // test to see if the program doesn't hang,
545 // when transfer is complete, for files less than the chunk size
546 // (i.e. when only one segment is sent/received)
547
548 createPipeline();
549 nDataSegments = 1;
550
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800551 run(name);
Ryan Wickman034f30f2018-06-06 11:11:11 -0500552 advanceClocks(io, time::nanoseconds(1));
553
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800554 face.receive(*makeDataWithSegment(0));
Ryan Wickman034f30f2018-06-06 11:11:11 -0500555 advanceClocks(io, time::nanoseconds(1));
556
schneiderklausd8197df2019-03-16 11:31:40 -0700557 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
558 BOOST_CHECK_EQUAL(pipeline->m_segmentInfo.size(), 0);
Ryan Wickman034f30f2018-06-06 11:11:11 -0500559 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
560}
561
562
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700563BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterestsCubic
Weiwei Liu245d7912016-07-28 00:04:25 -0700564BOOST_AUTO_TEST_SUITE_END() // Chunks
565
566} // namespace tests
Weiwei Liu245d7912016-07-28 00:04:25 -0700567} // namespace chunks
568} // namespace ndn