blob: b42728bd80da75b4c0d981adabb9cc6c3aeaddd0 [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#include "tools/chunks/catchunks/options.hpp"
30
31#include "pipeline-interests-fixture.hpp"
32
33namespace ndn {
34namespace chunks {
Weiwei Liu245d7912016-07-28 00:04:25 -070035namespace tests {
36
37using namespace ndn::tests;
38
Klaus Schneider9e5122b2019-03-19 17:03:25 -070039class PipelineInterestCubicFixture : public PipelineInterestsFixture
Weiwei Liu245d7912016-07-28 00:04:25 -070040{
41public:
Klaus Schneider9e5122b2019-03-19 17:03:25 -070042 PipelineInterestCubicFixture()
Davide Pesaventof6991e12018-01-08 20:58:50 -050043 : opt(makePipelineOptions())
Weiwei Liu245d7912016-07-28 00:04:25 -070044 , rttEstimator(makeRttEstimatorOptions())
45 {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000046 createPipeline();
47 }
48
49 void
50 createPipeline()
51 {
Klaus Schneider9e5122b2019-03-19 17:03:25 -070052 auto pline = make_unique<PipelineInterestsCubic>(face, rttEstimator, opt);
schneiderklausd8197df2019-03-16 11:31:40 -070053 pipeline = pline.get();
Weiwei Liu245d7912016-07-28 00:04:25 -070054 setPipeline(std::move(pline));
55 }
56
57private:
Klaus Schneider9e5122b2019-03-19 17:03:25 -070058 static PipelineInterestsCubic::Options
Weiwei Liu245d7912016-07-28 00:04:25 -070059 makePipelineOptions()
60 {
Klaus Schneider9e5122b2019-03-19 17:03:25 -070061 PipelineInterestsCubic::Options pipelineOptions;
Davide Pesaventof6991e12018-01-08 20:58:50 -050062 pipelineOptions.isQuiet = true;
63 pipelineOptions.isVerbose = false;
Weiwei Liu245d7912016-07-28 00:04:25 -070064 pipelineOptions.disableCwa = false;
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000065 pipelineOptions.ignoreCongMarks = false;
Weiwei Liu245d7912016-07-28 00:04:25 -070066 pipelineOptions.resetCwndToInit = false;
67 pipelineOptions.initCwnd = 1.0;
68 pipelineOptions.aiStep = 1.0;
69 pipelineOptions.mdCoef = 0.5;
70 pipelineOptions.initSsthresh = std::numeric_limits<int>::max();
Klaus Schneider9e5122b2019-03-19 17:03:25 -070071 pipelineOptions.cubicBeta = 0.7;
72 pipelineOptions.enableFastConv = false;
Weiwei Liu245d7912016-07-28 00:04:25 -070073 return pipelineOptions;
74 }
75
76 static RttEstimator::Options
77 makeRttEstimatorOptions()
78 {
79 RttEstimator::Options rttOptions;
80 rttOptions.alpha = 0.125;
81 rttOptions.beta = 0.25;
Klaus Schneider9e5122b2019-03-19 17:03:25 -070082 rttOptions.k = 8;
Weiwei Liu245d7912016-07-28 00:04:25 -070083 rttOptions.minRto = Milliseconds(200);
84 rttOptions.maxRto = Milliseconds(4000);
85 return rttOptions;
86 }
87
88protected:
Klaus Schneider9e5122b2019-03-19 17:03:25 -070089 PipelineInterestsCubic::Options opt;
Weiwei Liu245d7912016-07-28 00:04:25 -070090 RttEstimator rttEstimator;
Klaus Schneider9e5122b2019-03-19 17:03:25 -070091 PipelineInterestsCubic* pipeline;
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000092 static constexpr double MARGIN = 0.01;
Weiwei Liu245d7912016-07-28 00:04:25 -070093};
94
Klaus Schneider9e5122b2019-03-19 17:03:25 -070095constexpr double PipelineInterestCubicFixture::MARGIN;
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000096
Weiwei Liu245d7912016-07-28 00:04:25 -070097BOOST_AUTO_TEST_SUITE(Chunks)
Klaus Schneider9e5122b2019-03-19 17:03:25 -070098BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsCubic, PipelineInterestCubicFixture)
Weiwei Liu245d7912016-07-28 00:04:25 -070099
100BOOST_AUTO_TEST_CASE(SlowStart)
101{
102 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700103 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -0700104
schneiderklausd8197df2019-03-16 11:31:40 -0700105 double preCwnd = pipeline->m_cwnd;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800106 run(name);
Weiwei Liu245d7912016-07-28 00:04:25 -0700107 advanceClocks(io, time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400108 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700109
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800110 for (uint64_t i = 0; i < nDataSegments - 1; ++i) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700111 face.receive(*makeDataWithSegment(i));
112 advanceClocks(io, time::nanoseconds(1));
schneiderklausd8197df2019-03-16 11:31:40 -0700113 BOOST_CHECK_CLOSE(pipeline->m_cwnd - preCwnd, 1, MARGIN);
114 preCwnd = pipeline->m_cwnd;
Weiwei Liu245d7912016-07-28 00:04:25 -0700115 }
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400116
117 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments - 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700118}
119
Weiwei Liu245d7912016-07-28 00:04:25 -0700120
121BOOST_AUTO_TEST_CASE(Timeout)
122{
123 nDataSegments = 8;
schneiderklausd8197df2019-03-16 11:31:40 -0700124 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -0700125
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800126 run(name);
Weiwei Liu245d7912016-07-28 00:04:25 -0700127 advanceClocks(io, time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400128 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700129
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800130 // receive segment 0, 1, and 2
131 for (uint64_t i = 0; i < 3; ++i) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700132 face.receive(*makeDataWithSegment(i));
133 advanceClocks(io, time::nanoseconds(1));
134 }
135
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400136 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 3);
schneiderklausd8197df2019-03-16 11:31:40 -0700137 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800138 BOOST_CHECK_EQUAL(face.sentInterests.size(), 7); // request for segment 7 has been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700139
140 advanceClocks(io, time::milliseconds(100));
141
142 // receive segment 4
143 face.receive(*makeDataWithSegment(4));
144 advanceClocks(io, time::nanoseconds(1));
145
146 // receive segment 5
147 face.receive(*makeDataWithSegment(5));
148 advanceClocks(io, time::nanoseconds(1));
149
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400150 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700151 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 6.0, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800152 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all the segment requests have been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700153
schneiderklausd8197df2019-03-16 11:31:40 -0700154 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 0);
155 BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 0);
156 BOOST_CHECK_EQUAL(pipeline->m_nMarkDecr, 0);
157 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 0);
158 BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
159 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 0);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700160
161 // timeout segment 3 & 6
Weiwei Liu245d7912016-07-28 00:04:25 -0700162 advanceClocks(io, time::milliseconds(150));
schneiderklausd8197df2019-03-16 11:31:40 -0700163 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 2);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700164 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700165 BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 1);
166 BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700167
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400168 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700169 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // window size drop to 0.7x of previous size
170 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700171
172 // receive segment 6, retransmit 3
173 face.receive(*makeDataWithSegment(6));
174 advanceClocks(io, time::nanoseconds(1));
175
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400176 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700177 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // congestion avoidance
schneiderklausd8197df2019-03-16 11:31:40 -0700178 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
179 BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700180
schneiderklausd8197df2019-03-16 11:31:40 -0700181 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 2);
182 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 2);
183 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts,
184 pipeline->m_nRetransmitted + pipeline->m_nSkippedRetx);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700185
Weiwei Liu245d7912016-07-28 00:04:25 -0700186}
187
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000188BOOST_AUTO_TEST_CASE(CongestionMarksWithCwa)
189{
190 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700191 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000192
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800193 run(name);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000194 advanceClocks(io, time::nanoseconds(1));
195 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
196
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800197 // receive segments 0 to 4
198 for (uint64_t i = 0; i < 5; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000199 face.receive(*makeDataWithSegment(i));
200 advanceClocks(io, time::nanoseconds(1));
201 }
202
203 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700204 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 6.0, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000205
206 // receive segment 5 with congestion mark
207 face.receive(*makeDataWithSegmentAndCongMark(5));
208 advanceClocks(io, time::nanoseconds(1));
209
210 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700211 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 -0800212 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000213
214 // receive the last segment with congestion mark
215 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
216 advanceClocks(io, time::nanoseconds(1));
217
218 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700219 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // conservative window adaption (window size should not decrease)
schneiderklausd8197df2019-03-16 11:31:40 -0700220 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000221
222 // make sure no interest is retransmitted for marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700223 BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
224 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000225
226 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700227 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000228}
229
230BOOST_AUTO_TEST_CASE(CongestionMarksWithoutCwa)
231{
232 opt.disableCwa = true;
233 createPipeline();
234
235 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700236 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000237
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800238 run(name);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000239 advanceClocks(io, time::nanoseconds(1));
240 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
241
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800242 // receive segments 0 to 4
243 for (uint64_t i = 0; i < 5; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000244 face.receive(*makeDataWithSegment(i));
245 advanceClocks(io, time::nanoseconds(1));
246 }
247
248 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700249 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 6.0, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000250
251 // receive segment 5 with congestion mark
252 face.receive(*makeDataWithSegmentAndCongMark(5));
253 advanceClocks(io, time::nanoseconds(1));
254
255 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700256 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 -0800257 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000258
259 // receive the last segment with congestion mark
260 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
261 advanceClocks(io, time::nanoseconds(1));
262
263 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700264 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.94,
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000265 MARGIN); // window size should decrease, as cwa is disabled
schneiderklausd8197df2019-03-16 11:31:40 -0700266 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000267
268 // make sure no interest is retransmitted for marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700269 BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
270 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000271
272 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700273 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000274}
275
276BOOST_AUTO_TEST_CASE(IgnoreCongestionMarks)
277{
278 opt.ignoreCongMarks = true;
279 createPipeline();
280
281 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700282 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000283
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800284 run(name);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000285 advanceClocks(io, time::nanoseconds(1));
286 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
287
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800288 // receive segments 0 to 5
289 for (uint64_t i = 0; i < 6; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000290 face.receive(*makeDataWithSegment(i));
291 advanceClocks(io, time::nanoseconds(1));
292 }
293
294 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700295 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 7.0, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800296 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000297
298 // receive the last segment with congestion mark
299 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
300 advanceClocks(io, time::nanoseconds(1));
301
302 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700303 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 8.0, MARGIN); // window size increases
schneiderklausd8197df2019-03-16 11:31:40 -0700304 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000305
306 // make sure no interest is retransmitted for marked data packet
schneiderklausd8197df2019-03-16 11:31:40 -0700307 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000308
309 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700310 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 1);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000311}
312
Weiwei Liu245d7912016-07-28 00:04:25 -0700313BOOST_AUTO_TEST_CASE(Nack)
314{
315 nDataSegments = 5;
schneiderklausd8197df2019-03-16 11:31:40 -0700316 pipeline->m_cwnd = 10.0;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800317 run(name);
318 advanceClocks(io, time::nanoseconds(1));
319
320 face.receive(*makeDataWithSegment(0));
Weiwei Liu245d7912016-07-28 00:04:25 -0700321 advanceClocks(io, time::nanoseconds(1));
322
323 face.receive(*makeDataWithSegment(1));
324 advanceClocks(io, time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400325
326 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800327 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 10);
Weiwei Liu245d7912016-07-28 00:04:25 -0700328
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800329 // receive a nack with NackReason::DUPLICATE for segment 1
Weiwei Liu245d7912016-07-28 00:04:25 -0700330 auto nack1 = makeNack(face.sentInterests[1], lp::NackReason::DUPLICATE);
331 face.receive(nack1);
332 advanceClocks(io, time::nanoseconds(1));
333
334 // nack1 is ignored
335 BOOST_CHECK_EQUAL(hasFailed, false);
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400336 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700337 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700338
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800339 // receive a nack with NackReason::CONGESTION for segment 2
Weiwei Liu245d7912016-07-28 00:04:25 -0700340 auto nack2 = makeNack(face.sentInterests[2], lp::NackReason::CONGESTION);
341 face.receive(nack2);
342 advanceClocks(io, time::nanoseconds(1));
343
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800344 // segment 2 is retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700345 BOOST_CHECK_EQUAL(pipeline->m_retxCount[2], 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700346
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800347 // receive a nack with NackReason::NONE for segment 3
Weiwei Liu245d7912016-07-28 00:04:25 -0700348 auto nack3 = makeNack(face.sentInterests[3], lp::NackReason::NONE);
349 face.receive(nack3);
350 advanceClocks(io, time::nanoseconds(1));
351
352 // Other types of Nack will trigger a failure
353 BOOST_CHECK_EQUAL(hasFailed, true);
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400354 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700355}
356
357BOOST_AUTO_TEST_CASE(FinalBlockIdNotSetAtBeginning)
358{
359 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700360 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800361 run(name);
Weiwei Liu245d7912016-07-28 00:04:25 -0700362 advanceClocks(io, time::nanoseconds(1));
363
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800364 // receive segment 0 without FinalBlockId
365 face.receive(*makeDataWithSegment(0, false));
Weiwei Liu245d7912016-07-28 00:04:25 -0700366 advanceClocks(io, time::nanoseconds(1));
367
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800368 // interests for segment 0 - 5 have been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700369 BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800370 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 1);
schneiderklausd8197df2019-03-16 11:31:40 -0700371 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, false);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800372 // pending interests: segment 1, 2, 3, 4, 5
Weiwei Liu245d7912016-07-28 00:04:25 -0700373 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 5);
374
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800375 // receive segment 1 with FinalBlockId
376 face.receive(*makeDataWithSegment(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700377 advanceClocks(io, time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800378 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700379 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
Weiwei Liu245d7912016-07-28 00:04:25 -0700380
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800381 // pending interests for segment 1, 4, 5 haven been removed
382 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700383}
384
385BOOST_AUTO_TEST_CASE(FailureBeforeFinalBlockIdReceived)
386{
387 // failed to retrieve segNo while the FinalBlockId has not yet been
388 // set, and later received a FinalBlockId >= segNo, i.e. segNo is
389 // part of the content.
390
391 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700392 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800393 run(name);
394 advanceClocks(io, time::nanoseconds(1));
395
396 // receive segment 0 without FinalBlockId
397 face.receive(*makeDataWithSegment(0, false));
Weiwei Liu245d7912016-07-28 00:04:25 -0700398 advanceClocks(io, time::nanoseconds(1));
399
400 // receive segment 1 without FinalBlockId
401 face.receive(*makeDataWithSegment(1, false));
402 advanceClocks(io, time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800403
404 // interests for segment 0 - 7 have been sent
405 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
Weiwei Liu245d7912016-07-28 00:04:25 -0700406
407 // receive nack with NackReason::NONE for segment 3
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800408 auto nack = makeNack(face.sentInterests[3], lp::NackReason::NONE);
Weiwei Liu245d7912016-07-28 00:04:25 -0700409 face.receive(nack);
410 advanceClocks(io, time::nanoseconds(1));
411
412 // error not triggered
413 // pending interests for segment > 3 haven been removed
414 BOOST_CHECK_EQUAL(hasFailed, false);
415 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 1);
416
417 // receive segment 2 with FinalBlockId
418 face.receive(*makeDataWithSegment(2));
419 advanceClocks(io, time::nanoseconds(1));
420
421 // error triggered since segment 3 is part of the content
422 BOOST_CHECK_EQUAL(hasFailed, true);
423}
424
425BOOST_AUTO_TEST_CASE(SpuriousFailureBeforeFinalBlockIdReceived)
426{
427 // failed to retrieve segNo while the FinalBlockId has not yet been
428 // set, and later received a FinalBlockId < segNo, i.e. segNo is
429 // not part of the content, and it was actually a spurious failure
430
431 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700432 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800433 run(name);
434 advanceClocks(io, time::nanoseconds(1));
435
436 // receive segment 0 without FinalBlockId
437 face.receive(*makeDataWithSegment(0, false));
Weiwei Liu245d7912016-07-28 00:04:25 -0700438 advanceClocks(io, time::nanoseconds(1));
439
440 // receive segment 1 without FinalBlockId
441 face.receive(*makeDataWithSegment(1, false));
442 advanceClocks(io, time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800443
444 // interests for segment 0 - 7 have been sent
445 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
Weiwei Liu245d7912016-07-28 00:04:25 -0700446
447 // receive nack with NackReason::NONE for segment 4
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800448 auto nack = makeNack(face.sentInterests[4], lp::NackReason::NONE);
Weiwei Liu245d7912016-07-28 00:04:25 -0700449 face.receive(nack);
450 advanceClocks(io, time::nanoseconds(1));
451
452 // error not triggered
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800453 // pending interests for segment > 3 have been removed
Weiwei Liu245d7912016-07-28 00:04:25 -0700454 BOOST_CHECK_EQUAL(hasFailed, false);
455 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
456
457 // receive segment 2 with FinalBlockId
458 face.receive(*makeDataWithSegment(2));
459 advanceClocks(io, time::nanoseconds(1));
460
461 // timeout segment 3
Davide Pesavento958896e2017-01-19 00:52:04 -0500462 advanceClocks(io, time::seconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700463
464 // segment 3 is retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700465 BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700466
467 // receive segment 3
468 face.receive(*makeDataWithSegment(3));
469 advanceClocks(io, time::nanoseconds(1));
470
471 BOOST_CHECK_EQUAL(hasFailed, false);
472}
473
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500474BOOST_AUTO_TEST_CASE(SegmentInfoMaintenance)
475{
476 // test that m_segmentInfo is properly maintained when
477 // a segment is received after two consecutive timeouts
478
479 nDataSegments = 3;
480
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800481 run(name);
482 advanceClocks(io, time::nanoseconds(1));
483
484 // receive segment 0
485 face.receive(*makeDataWithSegment(0));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500486 advanceClocks(io, time::nanoseconds(1));
487
488 // receive segment 1
489 face.receive(*makeDataWithSegment(1));
490 advanceClocks(io, time::nanoseconds(1));
491
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800492 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500493
494 // check if segment 2's state is FirstTimeSent
schneiderklausd8197df2019-03-16 11:31:40 -0700495 auto it = pipeline->m_segmentInfo.find(2);
496 BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500497 BOOST_CHECK(it->second.state == SegmentState::FirstTimeSent);
498
499 // timeout segment 2 twice
500 advanceClocks(io, time::milliseconds(400), 3);
501
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800502 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500503
504 // check if segment 2's state is Retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700505 it = pipeline->m_segmentInfo.find(2);
506 BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500507 BOOST_CHECK(it->second.state == SegmentState::Retransmitted);
508
509 // check if segment 2 was retransmitted twice
schneiderklausd8197df2019-03-16 11:31:40 -0700510 BOOST_CHECK_EQUAL(pipeline->m_retxCount.at(2), 2);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500511
512 // receive segment 2 the first time
513 face.receive(*makeDataWithSegment(2));
514 advanceClocks(io, time::nanoseconds(1));
515
516 // check if segment 2 was erased from m_segmentInfo
schneiderklausd8197df2019-03-16 11:31:40 -0700517 it = pipeline->m_segmentInfo.find(2);
518 BOOST_CHECK(it == pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500519
520 auto prevRtt = rttEstimator.getAvgRtt();
521 auto prevRto = rttEstimator.getEstimatedRto();
522
523 // receive segment 2 the second time
524 face.receive(*makeDataWithSegment(2));
525 advanceClocks(io, time::nanoseconds(1));
526
527 // nothing changed
schneiderklausd8197df2019-03-16 11:31:40 -0700528 it = pipeline->m_segmentInfo.find(2);
529 BOOST_CHECK(it == pipeline->m_segmentInfo.end());
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800530 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500531 BOOST_CHECK_EQUAL(rttEstimator.getAvgRtt(), prevRtt);
532 BOOST_CHECK_EQUAL(rttEstimator.getEstimatedRto(), prevRto);
533}
534
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400535BOOST_AUTO_TEST_CASE(PrintSummaryWithNoRttMeasurements)
536{
537 // test the console ouptut when no RTT measurement is available,
538 // to make sure a proper message will be printed out
539
540 std::stringstream ss;
541
542 // change the underlying buffer and save the old buffer
543 auto oldBuf = std::cerr.rdbuf(ss.rdbuf());
544
schneiderklausd8197df2019-03-16 11:31:40 -0700545 pipeline->printSummary();
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400546 std::string line;
547
548 bool found = false;
549 while (std::getline(ss, line)) {
550 if (line == "RTT stats unavailable") {
551 found = true;
552 break;
553 }
554 }
555 BOOST_CHECK(found);
556 std::cerr.rdbuf(oldBuf); // reset
557}
558
Ryan Wickman034f30f2018-06-06 11:11:11 -0500559BOOST_AUTO_TEST_CASE(StopsWhenFileSizeLessThanChunkSize)
560{
561 // test to see if the program doesn't hang,
562 // when transfer is complete, for files less than the chunk size
563 // (i.e. when only one segment is sent/received)
564
565 createPipeline();
566 nDataSegments = 1;
567
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800568 run(name);
Ryan Wickman034f30f2018-06-06 11:11:11 -0500569 advanceClocks(io, time::nanoseconds(1));
570
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800571 face.receive(*makeDataWithSegment(0));
Ryan Wickman034f30f2018-06-06 11:11:11 -0500572 advanceClocks(io, time::nanoseconds(1));
573
schneiderklausd8197df2019-03-16 11:31:40 -0700574 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
575 BOOST_CHECK_EQUAL(pipeline->m_segmentInfo.size(), 0);
Ryan Wickman034f30f2018-06-06 11:11:11 -0500576 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
577}
578
579
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700580BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterestsCubic
Weiwei Liu245d7912016-07-28 00:04:25 -0700581BOOST_AUTO_TEST_SUITE_END() // Chunks
582
583} // namespace tests
Weiwei Liu245d7912016-07-28 00:04:25 -0700584} // namespace chunks
585} // namespace ndn