blob: 5ebcc7631764b95b28660ef7ffca9723f2acb7ba [file] [log] [blame]
Yukai Tu16aabbc2015-10-06 05:08:42 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi84d62cb2017-07-12 16:15:18 +00002/*
Davide Pesavento32065652017-01-15 01:52:21 -05003 * Copyright (c) 2014-2017, Regents of the University of California,
Yukai Tu16aabbc2015-10-06 05:08:42 -07004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
Eric Newberry65caf202015-12-17 15:08:16 -070026#include "transport-test-common.hpp"
27
Eric Newberryf68f3782015-12-11 00:31:32 -070028#include "tcp-transport-fixture.hpp"
Yukai Tu16aabbc2015-10-06 05:08:42 -070029
Davide Pesavento22fba352017-10-17 15:53:51 -040030#include <boost/mpl/vector.hpp>
31
Yukai Tu16aabbc2015-10-06 05:08:42 -070032namespace nfd {
33namespace face {
34namespace tests {
35
Yukai Tu16aabbc2015-10-06 05:08:42 -070036BOOST_AUTO_TEST_SUITE(Face)
Davide Pesavento22fba352017-10-17 15:53:51 -040037BOOST_FIXTURE_TEST_SUITE(TestTcpTransport, IpTransportFixture<TcpTransportFixture>)
Eric Newberry8717e872015-11-23 12:41:50 -070038
Davide Pesavento22fba352017-10-17 15:53:51 -040039using TcpTransportFixtures = boost::mpl::vector<
40 GENERATE_IP_TRANSPORT_FIXTURE_INSTANTIATIONS(TcpTransportFixture)
41>;
42
43BOOST_FIXTURE_TEST_CASE_TEMPLATE(StaticProperties, T, TcpTransportFixtures, T)
Eric Newberry8717e872015-11-23 12:41:50 -070044{
Davide Pesavento22fba352017-10-17 15:53:51 -040045 TRANSPORT_TEST_INIT();
Eric Newberry8717e872015-11-23 12:41:50 -070046
Davide Pesavento22fba352017-10-17 15:53:51 -040047 checkStaticPropertiesInitialized(*this->transport);
Eric Newberry8717e872015-11-23 12:41:50 -070048
Davide Pesavento22fba352017-10-17 15:53:51 -040049 BOOST_CHECK_EQUAL(this->transport->getLocalUri(), FaceUri(tcp::endpoint(this->address, this->localEp.port())));
50 BOOST_CHECK_EQUAL(this->transport->getRemoteUri(), FaceUri(tcp::endpoint(this->address, 7070)));
51 BOOST_CHECK_EQUAL(this->transport->getScope(),
52 this->addressScope == AddressScope::Loopback ? ndn::nfd::FACE_SCOPE_LOCAL
53 : ndn::nfd::FACE_SCOPE_NON_LOCAL);
54 BOOST_CHECK_EQUAL(this->transport->getPersistency(), ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
55 BOOST_CHECK_EQUAL(this->transport->getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
56 BOOST_CHECK_EQUAL(this->transport->getMtu(), MTU_UNLIMITED);
Eric Newberry8717e872015-11-23 12:41:50 -070057}
58
Davide Pesavento32065652017-01-15 01:52:21 -050059BOOST_AUTO_TEST_CASE(PersistencyChange)
60{
Davide Pesavento22fba352017-10-17 15:53:51 -040061 TRANSPORT_TEST_INIT();
Davide Pesavento32065652017-01-15 01:52:21 -050062
63 BOOST_CHECK_EQUAL(transport->canChangePersistencyTo(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND), true);
64 BOOST_CHECK_EQUAL(transport->canChangePersistencyTo(ndn::nfd::FACE_PERSISTENCY_PERSISTENT), true);
65 BOOST_CHECK_EQUAL(transport->canChangePersistencyTo(ndn::nfd::FACE_PERSISTENCY_PERMANENT), true);
66}
67
Weiwei Liudcdf6212016-08-31 14:34:22 -070068BOOST_AUTO_TEST_CASE(ChangePersistencyFromPermanentWhenDown)
69{
70 // when persistency is changed out of permanent while transport is DOWN,
71 // the transport immediately goes into FAILED state
72
Davide Pesavento22fba352017-10-17 15:53:51 -040073 TRANSPORT_TEST_INIT(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
Weiwei Liudcdf6212016-08-31 14:34:22 -070074
Davide Pesavento22fba352017-10-17 15:53:51 -040075 transport->afterStateChange.connectSingleShot(
76 [this] (TransportState oldState, TransportState newState) {
77 BOOST_CHECK_EQUAL(oldState, TransportState::UP);
78 BOOST_CHECK_EQUAL(newState, TransportState::DOWN);
79 limitedIo.afterOp();
80 });
Weiwei Liudcdf6212016-08-31 14:34:22 -070081 remoteSocket.close();
82 BOOST_REQUIRE_EQUAL(limitedIo.run(1, time::seconds(1)), LimitedIo::EXCEED_OPS);
83
84 bool didStateChange = false;
85 transport->afterStateChange.connectSingleShot(
Davide Pesaventoac238f22017-09-12 15:19:40 -040086 [&didStateChange] (TransportState oldState, TransportState newState) {
Weiwei Liudcdf6212016-08-31 14:34:22 -070087 didStateChange = true;
88 BOOST_CHECK_EQUAL(oldState, TransportState::DOWN);
89 BOOST_CHECK_EQUAL(newState, TransportState::FAILED);
90 });
91 transport->setPersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
92 BOOST_CHECK(didStateChange);
93}
94
Davide Pesavento22fba352017-10-17 15:53:51 -040095BOOST_FIXTURE_TEST_CASE_TEMPLATE(PermanentReconnect, T, TcpTransportFixtures, T)
96{
97 TRANSPORT_TEST_INIT(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
98
99 this->transport->afterStateChange.connectSingleShot(
100 [this] (TransportState oldState, TransportState newState) {
101 BOOST_CHECK_EQUAL(oldState, TransportState::UP);
102 BOOST_CHECK_EQUAL(newState, TransportState::DOWN);
103 this->limitedIo.afterOp();
104 });
105 this->remoteSocket.close();
106 BOOST_REQUIRE_EQUAL(this->limitedIo.run(1, time::seconds(1)), LimitedIo::EXCEED_OPS);
107
108 this->transport->afterStateChange.connectSingleShot(
109 [this] (TransportState oldState, TransportState newState) {
110 BOOST_CHECK_EQUAL(oldState, TransportState::DOWN);
111 BOOST_CHECK_EQUAL(newState, TransportState::UP);
112 this->limitedIo.afterOp();
113 });
114 BOOST_REQUIRE_EQUAL(this->limitedIo.run(1, time::seconds(1)), LimitedIo::EXCEED_OPS);
115}
116
Weiwei Liudcdf6212016-08-31 14:34:22 -0700117class PermanentTcpTransportReconnectObserver : public TcpTransport
118{
119public:
120 PermanentTcpTransportReconnectObserver(protocol::socket&& socket, LimitedIo& io)
121 : TcpTransport(std::move(socket), ndn::nfd::FACE_PERSISTENCY_PERMANENT)
122 , m_io(io)
123 {
124 }
125
126protected:
127 void
128 reconnect() final
129 {
130 TcpTransport::reconnect();
131 m_io.afterOp();
132 }
133
134 void
135 handleReconnect(const boost::system::error_code& error) final
136 {
137 TcpTransport::handleReconnect(error);
138 m_io.afterOp();
139 }
140
141 void
142 handleReconnectTimeout() final
143 {
144 TcpTransport::handleReconnectTimeout();
145 m_io.afterOp();
146 }
147
148private:
149 LimitedIo& m_io;
150};
151
152static double
153asFloatMilliseconds(const time::nanoseconds& t)
154{
155 return static_cast<double>(t.count()) / 1000000.0;
156}
157
Davide Pesavento22fba352017-10-17 15:53:51 -0400158BOOST_FIXTURE_TEST_CASE_TEMPLATE(PermanentReconnectWithExponentialBackoff, T, TcpTransportFixtures, T)
Weiwei Liudcdf6212016-08-31 14:34:22 -0700159{
Davide Pesavento22fba352017-10-17 15:53:51 -0400160 TRANSPORT_TEST_CHECK_PRECONDITIONS();
161 // do not initialize
Weiwei Liudcdf6212016-08-31 14:34:22 -0700162
Davide Pesavento22fba352017-10-17 15:53:51 -0400163 tcp::endpoint remoteEp(this->address, 7070);
164 this->startAccept(remoteEp);
Weiwei Liudcdf6212016-08-31 14:34:22 -0700165
Davide Pesavento22fba352017-10-17 15:53:51 -0400166 tcp::socket sock(this->g_io);
Weiwei Liudcdf6212016-08-31 14:34:22 -0700167 sock.async_connect(remoteEp, [this] (const boost::system::error_code& error) {
168 BOOST_REQUIRE_EQUAL(error, boost::system::errc::success);
Davide Pesavento22fba352017-10-17 15:53:51 -0400169 this->limitedIo.afterOp();
Weiwei Liudcdf6212016-08-31 14:34:22 -0700170 });
Davide Pesavento22fba352017-10-17 15:53:51 -0400171 BOOST_REQUIRE_EQUAL(this->limitedIo.run(2, time::seconds(1)), LimitedIo::EXCEED_OPS);
Weiwei Liudcdf6212016-08-31 14:34:22 -0700172
Davide Pesavento22fba352017-10-17 15:53:51 -0400173 auto transportObserver =
174 make_unique<PermanentTcpTransportReconnectObserver>(std::move(sock), std::ref(this->limitedIo));
Weiwei Liudcdf6212016-08-31 14:34:22 -0700175 BOOST_REQUIRE_EQUAL(transportObserver->getState(), TransportState::UP);
176
177 // break the TCP connection
Davide Pesavento22fba352017-10-17 15:53:51 -0400178 this->stopAccept();
179 this->remoteSocket.close();
Weiwei Liudcdf6212016-08-31 14:34:22 -0700180
181 // measure retry intervals
Davide Pesavento22fba352017-10-17 15:53:51 -0400182 BOOST_REQUIRE_EQUAL(this->limitedIo.run(2, time::seconds(5)), LimitedIo::EXCEED_OPS);
Weiwei Liudcdf6212016-08-31 14:34:22 -0700183 auto retryTime1 = time::steady_clock::now();
184 BOOST_CHECK_EQUAL(transportObserver->getState(), TransportState::DOWN);
185
Davide Pesavento22fba352017-10-17 15:53:51 -0400186 BOOST_REQUIRE_EQUAL(this->limitedIo.run(2, time::seconds(5)), LimitedIo::EXCEED_OPS);
Weiwei Liudcdf6212016-08-31 14:34:22 -0700187 auto retryTime2 = time::steady_clock::now();
188 BOOST_CHECK_EQUAL(transportObserver->getState(), TransportState::DOWN);
189
Davide Pesavento22fba352017-10-17 15:53:51 -0400190 BOOST_REQUIRE_EQUAL(this->limitedIo.run(2, time::seconds(5)), LimitedIo::EXCEED_OPS);
Weiwei Liudcdf6212016-08-31 14:34:22 -0700191 auto retryTime3 = time::steady_clock::now();
192 BOOST_CHECK_EQUAL(transportObserver->getState(), TransportState::DOWN);
193
194 // check that the backoff algorithm works
195 BOOST_CHECK_CLOSE(asFloatMilliseconds(retryTime2 - retryTime1),
196 asFloatMilliseconds(TcpTransport::s_initialReconnectWait),
197 10.0);
198 BOOST_CHECK_CLOSE(asFloatMilliseconds(retryTime3 - retryTime2),
199 asFloatMilliseconds(TcpTransport::s_initialReconnectWait) * TcpTransport::s_reconnectWaitMultiplier,
200 10.0);
201
202 // reestablish the TCP connection
Davide Pesavento22fba352017-10-17 15:53:51 -0400203 this->startAccept(remoteEp);
Weiwei Liudcdf6212016-08-31 14:34:22 -0700204
Davide Pesavento22fba352017-10-17 15:53:51 -0400205 BOOST_REQUIRE_EQUAL(this->limitedIo.run(3, time::seconds(10)), LimitedIo::EXCEED_OPS);
Weiwei Liudcdf6212016-08-31 14:34:22 -0700206 BOOST_CHECK_EQUAL(transportObserver->getState(), TransportState::UP);
207
208 // break the TCP connection again
Davide Pesavento22fba352017-10-17 15:53:51 -0400209 this->stopAccept();
210 this->remoteSocket.close();
Weiwei Liudcdf6212016-08-31 14:34:22 -0700211
212 // measure retry intervals
Davide Pesavento22fba352017-10-17 15:53:51 -0400213 BOOST_REQUIRE_EQUAL(this->limitedIo.run(2, time::seconds(5)), LimitedIo::EXCEED_OPS);
Weiwei Liudcdf6212016-08-31 14:34:22 -0700214 auto retryTime4 = time::steady_clock::now();
215 BOOST_CHECK_EQUAL(transportObserver->getState(), TransportState::DOWN);
216
Davide Pesavento22fba352017-10-17 15:53:51 -0400217 BOOST_REQUIRE_EQUAL(this->limitedIo.run(2, time::seconds(5)), LimitedIo::EXCEED_OPS);
Weiwei Liudcdf6212016-08-31 14:34:22 -0700218 auto retryTime5 = time::steady_clock::now();
219 BOOST_CHECK_EQUAL(transportObserver->getState(), TransportState::DOWN);
220
221 // check that the timeout restarts from the initial value after a successful reconnection
222 BOOST_CHECK_CLOSE(asFloatMilliseconds(retryTime5 - retryTime4),
223 asFloatMilliseconds(TcpTransport::s_initialReconnectWait),
224 10.0);
225}
226
Yukai Tu16aabbc2015-10-06 05:08:42 -0700227BOOST_AUTO_TEST_SUITE_END() // TestTcpTransport
228BOOST_AUTO_TEST_SUITE_END() // Face
229
230} // namespace tests
231} // namespace face
232} // namespace nfd