blob: 040dc457eec8b218246eb3f6b020b0e5dd5a1306 [file] [log] [blame]
Eric Newberrya98bf932015-09-21 00:58:47 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Spencer Leed5fe0cf2016-02-06 03:55:24 -07003 * Copyright (c) 2014-2016, Regents of the University of California,
Eric Newberrya98bf932015-09-21 00:58:47 -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
Junxiao Shicde37ad2015-12-24 01:02:05 -070026#include "face/tcp-channel.hpp"
27
Spencer Leed5fe0cf2016-02-06 03:55:24 -070028#include "tests/limited-io.hpp"
Junxiao Shicde37ad2015-12-24 01:02:05 -070029#include "tests/test-common.hpp"
Eric Newberrya98bf932015-09-21 00:58:47 -070030
Spencer Leed5fe0cf2016-02-06 03:55:24 -070031#include <boost/mpl/vector.hpp>
32
Eric Newberrya98bf932015-09-21 00:58:47 -070033namespace nfd {
Junxiao Shicde37ad2015-12-24 01:02:05 -070034namespace tests {
Eric Newberrya98bf932015-09-21 00:58:47 -070035
Junxiao Shicde37ad2015-12-24 01:02:05 -070036BOOST_AUTO_TEST_SUITE(Face)
Eric Newberrya98bf932015-09-21 00:58:47 -070037
Spencer Leed5fe0cf2016-02-06 03:55:24 -070038using nfd::Face;
39namespace ip = boost::asio::ip;
40
41typedef boost::mpl::vector<ip::address_v4,
42 ip::address_v6> AddressTypes;
43
44class TcpChannelFixture : public BaseFixture
45{
46protected:
47 TcpChannelFixture()
48 : nextPort(7050)
49 {
50 }
51
52 unique_ptr<TcpChannel>
53 makeChannel(const ip::address& addr, uint16_t port = 0)
54 {
55 if (port == 0)
56 port = nextPort++;
57
58 return make_unique<TcpChannel>(tcp::Endpoint(addr, port));
59 }
60
61 void
62 listen(const ip::address& addr)
63 {
64 listenerEp = tcp::Endpoint(addr, 7030);
65 listenerChannel = makeChannel(addr, 7030);
66 listenerChannel->listen(
67 [this] (const shared_ptr<Face>& newFace) {
68 BOOST_REQUIRE(newFace != nullptr);
69 connectFaceClosedSignal(*newFace, [this] { limitedIo.afterOp(); });
70 listenerFaces.push_back(newFace);
71 limitedIo.afterOp();
72 },
73 [this] (const std::string& reason) {
74 BOOST_FAIL(reason);
75 limitedIo.afterOp();
76 });
77 }
78
79 void
80 connect(TcpChannel& channel)
81 {
82 channel.connect(listenerEp,
83 [this] (const shared_ptr<Face>& newFace) {
84 BOOST_REQUIRE(newFace != nullptr);
85 connectFaceClosedSignal(*newFace, [this] { limitedIo.afterOp(); });
86 clientFaces.push_back(newFace);
87 limitedIo.afterOp();
88 },
89 [this] (const std::string& reason) {
90 BOOST_FAIL(reason);
91 limitedIo.afterOp();
92 });
93 }
94
95protected:
96 LimitedIo limitedIo;
97 tcp::Endpoint listenerEp;
98 unique_ptr<TcpChannel> listenerChannel;
99 std::vector<shared_ptr<Face>> listenerFaces;
100 std::vector<shared_ptr<Face>> clientFaces;
101
102private:
103 uint16_t nextPort;
104};
105
106BOOST_FIXTURE_TEST_SUITE(TestTcpChannel, TcpChannelFixture)
107
108BOOST_AUTO_TEST_CASE_TEMPLATE(Uri, A, AddressTypes)
109{
110 tcp::Endpoint ep(A::loopback(), 7050);
111 auto channel = makeChannel(ep.address(), ep.port());
112 BOOST_CHECK_EQUAL(channel->getUri(), FaceUri(ep));
113}
114
115BOOST_AUTO_TEST_CASE(Listen)
116{
117 auto channel = makeChannel(ip::address_v4());
118 BOOST_CHECK_EQUAL(channel->isListening(), false);
119
120 channel->listen(nullptr, nullptr);
121 BOOST_CHECK_EQUAL(channel->isListening(), true);
122
123 // listen() is idempotent
124 BOOST_CHECK_NO_THROW(channel->listen(nullptr, nullptr));
125 BOOST_CHECK_EQUAL(channel->isListening(), true);
126}
127
128BOOST_AUTO_TEST_CASE_TEMPLATE(MultipleAccepts, A, AddressTypes)
129{
130 this->listen(A::loopback());
131
132 BOOST_CHECK_EQUAL(listenerChannel->isListening(), true);
133 BOOST_CHECK_EQUAL(listenerChannel->size(), 0);
134
135 auto ch1 = makeChannel(A());
136 this->connect(*ch1);
137
138 BOOST_CHECK(limitedIo.run(2, time::seconds(1)) == LimitedIo::EXCEED_OPS);
139
140 BOOST_CHECK_EQUAL(listenerChannel->size(), 1);
141 BOOST_CHECK_EQUAL(ch1->size(), 1);
142 BOOST_CHECK_EQUAL(ch1->isListening(), false);
143
144 auto ch2 = makeChannel(A());
145 auto ch3 = makeChannel(A());
146 this->connect(*ch2);
147 this->connect(*ch3);
148
149 BOOST_CHECK(limitedIo.run(4, time::seconds(1)) == LimitedIo::EXCEED_OPS);
150
151 BOOST_CHECK_EQUAL(listenerChannel->size(), 3);
152 BOOST_CHECK_EQUAL(ch1->size(), 1);
153 BOOST_CHECK_EQUAL(ch2->size(), 1);
154 BOOST_CHECK_EQUAL(ch3->size(), 1);
155 BOOST_CHECK_EQUAL(clientFaces.size(), 3);
156
157 // check face persistency
158 for (const auto& face : listenerFaces) {
159 BOOST_CHECK_EQUAL(face->getPersistency(), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
160 }
161 for (const auto& face : clientFaces) {
162 BOOST_CHECK_EQUAL(face->getPersistency(), ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
163 }
164
165 // connect twice to the same endpoint
166 this->connect(*ch3);
167
168 BOOST_CHECK_EQUAL(listenerChannel->size(), 3);
169 BOOST_CHECK_EQUAL(ch1->size(), 1);
170 BOOST_CHECK_EQUAL(ch2->size(), 1);
171 BOOST_CHECK_EQUAL(ch3->size(), 1);
172 BOOST_CHECK_EQUAL(clientFaces.size(), 4);
173 BOOST_CHECK_EQUAL(clientFaces.at(2), clientFaces.at(3));
174}
175
176BOOST_AUTO_TEST_CASE_TEMPLATE(ConnectTimeout, A, AddressTypes)
177{
178 auto channel = makeChannel(A());
179
180 channel->connect(tcp::Endpoint(A::loopback(), 7040),
181 [this] (const shared_ptr<Face>&) {
182 BOOST_FAIL("Connect succeeded when it should have failed");
183 this->limitedIo.afterOp();
184 },
185 [this] (const std::string& reason) {
186 BOOST_CHECK_EQUAL(reason.empty(), false);
187 this->limitedIo.afterOp();
188 },
189 time::seconds(1));
190
191 BOOST_CHECK(limitedIo.run(1, time::seconds(2)) == LimitedIo::EXCEED_OPS);
192 BOOST_CHECK_EQUAL(channel->size(), 0);
193}
194
195BOOST_AUTO_TEST_CASE(FaceClosure)
196{
197 this->listen(ip::address_v4::loopback());
198
199 auto clientChannel = makeChannel(ip::address_v4());
200 this->connect(*clientChannel);
201
202 BOOST_CHECK(limitedIo.run(2, time::seconds(1)) == LimitedIo::EXCEED_OPS);
203
204 BOOST_CHECK_EQUAL(listenerChannel->size(), 1);
205 BOOST_CHECK_EQUAL(clientChannel->size(), 1);
206
207 clientFaces.at(0)->close();
208
209 BOOST_CHECK(limitedIo.run(2, time::seconds(1)) == LimitedIo::EXCEED_OPS);
210
211 BOOST_CHECK_EQUAL(listenerChannel->size(), 0);
212 BOOST_CHECK_EQUAL(clientChannel->size(), 0);
213}
Junxiao Shicde37ad2015-12-24 01:02:05 -0700214
215BOOST_AUTO_TEST_SUITE_END() // TestTcpChannel
216BOOST_AUTO_TEST_SUITE_END() // Face
217
218} // namespace tests
Eric Newberrya98bf932015-09-21 00:58:47 -0700219} // namespace nfd