blob: 01fe4f843229bd4900ed8b21cb2cfd4767f4ad1b [file] [log] [blame]
Davide Pesavento4ad933a2019-06-02 21:15:42 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2016-2019, Regents of the University of California,
4 * Colorado State University,
5 * University Pierre & Marie Curie, Sorbonne University.
6 *
7 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
8 *
9 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU Lesser General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later version.
12 *
13 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16 *
17 * You should have received copies of the GNU General Public License and GNU Lesser
18 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
19 * <http://www.gnu.org/licenses/>.
20 *
21 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
22 */
23
24#include "ndn-cxx/util/rtt-estimator.hpp"
25
26#include "tests/boost-test.hpp"
27
28#include <cmath>
29
30namespace ndn {
31namespace util {
32namespace tests {
33
34BOOST_AUTO_TEST_SUITE(Util)
35BOOST_AUTO_TEST_SUITE(TestRttEstimator)
36
37using Millis = RttEstimator::MillisecondsDouble;
38
39BOOST_AUTO_TEST_CASE(MinAvgMaxRtt)
40{
41 RttEstimator rttEstimator;
42
43 // check initial values
44 BOOST_CHECK_CLOSE(rttEstimator.getMinRtt().count(), std::numeric_limits<double>::max(), 0.001);
45 BOOST_CHECK_CLOSE(rttEstimator.getAvgRtt().count(), 0.0, 0.001);
46 BOOST_CHECK_CLOSE(rttEstimator.getMaxRtt().count(), std::numeric_limits<double>::min(), 0.001);
47
48 // start with three samples
49 rttEstimator.addMeasurement(Millis(100), 1);
50 rttEstimator.addMeasurement(Millis(400), 1);
51 rttEstimator.addMeasurement(Millis(250), 1);
52
53 BOOST_CHECK_CLOSE(rttEstimator.getMinRtt().count(), 100.0, 0.001);
54 BOOST_CHECK_CLOSE(rttEstimator.getAvgRtt().count(), 250.0, 0.001);
55 BOOST_CHECK_CLOSE(rttEstimator.getMaxRtt().count(), 400.0, 0.001);
56
57 // add another sample (new minimum)
58 rttEstimator.addMeasurement(Millis(50), 2);
59 BOOST_CHECK_CLOSE(rttEstimator.getMinRtt().count(), 50.0, 0.001);
60 BOOST_CHECK_CLOSE(rttEstimator.getAvgRtt().count(), 200.0, 0.001);
61 BOOST_CHECK_CLOSE(rttEstimator.getMaxRtt().count(), 400.0, 0.001);
62
63 // add another sample (new maximum)
64 rttEstimator.addMeasurement(Millis(700), 1);
65 BOOST_CHECK_CLOSE(rttEstimator.getMinRtt().count(), 50.0, 0.001);
66 BOOST_CHECK_CLOSE(rttEstimator.getAvgRtt().count(), 300.0, 0.001);
67 BOOST_CHECK_CLOSE(rttEstimator.getMaxRtt().count(), 700.0, 0.001);
68}
69
70BOOST_AUTO_TEST_CASE(EstimatedRto)
71{
72 RttEstimator::Options opts;
73 opts.initialRto = Millis(1000);
74 opts.maxRto = Millis(4000);
75 RttEstimator rttEstimator(opts);
76
77 // check initial values
78 BOOST_CHECK(std::isnan(rttEstimator.m_sRtt.count()));
79 BOOST_CHECK(std::isnan(rttEstimator.m_rttVar.count()));
80 BOOST_CHECK_CLOSE(rttEstimator.getEstimatedRto().count(), 1000.0, 0.001);
81
82 // first measurement
83 rttEstimator.addMeasurement(Millis(100), 1);
84
85 BOOST_CHECK_CLOSE(rttEstimator.m_sRtt.count(), 100.0, 0.001);
86 BOOST_CHECK_CLOSE(rttEstimator.m_rttVar.count(), 50.0, 0.001);
87 BOOST_CHECK_CLOSE(rttEstimator.getEstimatedRto().count(), 300.0, 0.001);
88
89 rttEstimator.m_sRtt = Millis(500);
90 rttEstimator.m_rttVar = Millis(100);
91 rttEstimator.m_rto = Millis(900);
92
93 rttEstimator.addMeasurement(Millis(100), 1);
94
95 BOOST_CHECK_CLOSE(rttEstimator.m_sRtt.count(), 450.0, 0.001);
96 BOOST_CHECK_CLOSE(rttEstimator.m_rttVar.count(), 175.0, 0.001);
97 BOOST_CHECK_CLOSE(rttEstimator.getEstimatedRto().count(), 1150.0, 0.001);
98
99 // expected samples larger than 1
100 rttEstimator.addMeasurement(Millis(100), 5);
101
102 BOOST_CHECK_CLOSE(rttEstimator.m_sRtt.count(), 441.25, 0.001);
103 BOOST_CHECK_CLOSE(rttEstimator.m_rttVar.count(), 183.75, 0.001);
104 BOOST_CHECK_CLOSE(rttEstimator.getEstimatedRto().count(), 1176.25, 0.001);
105
106 rttEstimator.m_sRtt = Millis(100.0);
107 rttEstimator.m_rttVar = Millis(30.0);
108 rttEstimator.m_rto = Millis(220.0);
109
110 // check if minRto works
111 rttEstimator.addMeasurement(Millis(100), 1);
112
113 BOOST_CHECK_CLOSE(rttEstimator.m_sRtt.count(), 100.0, 0.001);
114 BOOST_CHECK_CLOSE(rttEstimator.m_rttVar.count(), 22.5, 0.001);
115 BOOST_CHECK_CLOSE(rttEstimator.getEstimatedRto().count(), 200.0, 0.001);
116
117 rttEstimator.m_sRtt = Millis(2000);
118 rttEstimator.m_rttVar = Millis(400);
119 rttEstimator.m_rto = Millis(3600);
120
121 // check if maxRto works
122 rttEstimator.addMeasurement(Millis(100), 1);
123
124 BOOST_CHECK_CLOSE(rttEstimator.m_sRtt.count(), 1762.5, 0.001);
125 BOOST_CHECK_CLOSE(rttEstimator.m_rttVar.count(), 775.0, 0.001);
126 BOOST_CHECK_CLOSE(rttEstimator.getEstimatedRto().count(), 4000.0, 0.001);
127}
128
129BOOST_AUTO_TEST_CASE(BackoffRto)
130{
131 RttEstimator::Options opts;
132 opts.initialRto = Millis(500);
133 opts.maxRto = Millis(4000);
134 RttEstimator rttEstimator(opts);
135
136 rttEstimator.backoffRto();
137 BOOST_CHECK_CLOSE(rttEstimator.getEstimatedRto().count(), 1000.0, 0.001);
138
139 // check if minRto works
140 rttEstimator.m_rto = Millis(10);
141 rttEstimator.backoffRto();
142 BOOST_CHECK_CLOSE(rttEstimator.getEstimatedRto().count(), 200.0, 0.001);
143
144 // check if maxRto works
145 rttEstimator.m_rto = Millis(3000);
146 rttEstimator.backoffRto();
147 BOOST_CHECK_CLOSE(rttEstimator.getEstimatedRto().count(), 4000.0, 0.001);
148}
149
150BOOST_AUTO_TEST_CASE(AfterMeasurement)
151{
152 RttEstimator rttEstimator;
153
154 int nHandlerInvocations = 0;
155 rttEstimator.afterMeasurement.connectSingleShot([&nHandlerInvocations] (const auto& sample) {
156 ++nHandlerInvocations;
157 BOOST_CHECK_CLOSE(sample.rtt.count(), 80.0, 0.001);
158 BOOST_CHECK_CLOSE(sample.sRtt.count(), 80.0, 0.001);
159 BOOST_CHECK_CLOSE(sample.rttVar.count(), 40.0, 0.001);
160 BOOST_CHECK_CLOSE(sample.rto.count(), 240.0, 0.001);
161 BOOST_CHECK(!sample.segNum.has_value());
162 });
163 rttEstimator.addMeasurement(Millis(80), 1);
164 BOOST_CHECK_EQUAL(nHandlerInvocations, 1);
165
166 rttEstimator.afterMeasurement.connectSingleShot([&nHandlerInvocations] (const auto& sample) {
167 ++nHandlerInvocations;
168 BOOST_CHECK_CLOSE(sample.rtt.count(), 40.0, 0.001);
169 BOOST_CHECK_CLOSE(sample.sRtt.count(), 75.0, 0.001);
170 BOOST_CHECK_CLOSE(sample.rttVar.count(), 40.0, 0.001);
171 BOOST_CHECK_CLOSE(sample.rto.count(), 235.0, 0.001);
172 BOOST_CHECK(sample.segNum == 42U);
173 });
174 rttEstimator.addMeasurement(Millis(40), 1, 42);
175 BOOST_CHECK_EQUAL(nHandlerInvocations, 2);
176}
177
178BOOST_AUTO_TEST_SUITE_END() // TestRttEstimator
179BOOST_AUTO_TEST_SUITE_END() // Util
180
181} // namespace tests
182} // namespace util
183} // namespace ndn