blob: 8014f52c53760504a20f09871b988331e1575a1d [file] [log] [blame]
Junxiao Shi96dc0c42014-01-30 23:51:59 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (C) 2014 Named Data Networking Project
4 * See COPYING for copyright and distribution information.
5 */
6
7#include "face/tcp-channel-factory.hpp"
8#include "core/scheduler.hpp"
9
10#include <ndn-cpp-dev/security/key-chain.hpp>
11
12#include <boost/test/unit_test.hpp>
13
14namespace nfd {
15
16BOOST_AUTO_TEST_SUITE(FaceTcp)
17
18BOOST_AUTO_TEST_CASE(ChannelMap)
19{
20 boost::asio::io_service io;
21 TcpChannelFactory factory(io);
22
23 shared_ptr<TcpChannel> channel1 = factory.create("127.0.0.1", "20070");
24 shared_ptr<TcpChannel> channel1a = factory.create("127.0.0.1", "20070");
25 BOOST_CHECK_EQUAL(channel1, channel1a);
26
27 shared_ptr<TcpChannel> channel2 = factory.create("127.0.0.1", "20071");
28 BOOST_CHECK_NE(channel1, channel2);
29}
30
31class EndToEndFixture
32{
33public:
34 void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080035 channel1_onFaceCreated(const shared_ptr<Face>& newFace)
Junxiao Shi96dc0c42014-01-30 23:51:59 -070036 {
37 BOOST_CHECK(!static_cast<bool>(m_face1));
38 m_face1 = newFace;
39 m_face1->onReceiveInterest +=
40 bind(&EndToEndFixture::face1_onReceiveInterest, this, _1);
41 m_face1->onReceiveData +=
42 bind(&EndToEndFixture::face1_onReceiveData, this, _1);
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080043 m_face1->onFail +=
44 bind(&EndToEndFixture::face1_onFail, this);
Junxiao Shi96dc0c42014-01-30 23:51:59 -070045
46 this->afterIo();
47 }
48
49 void
50 channel1_onConnectFailed(const std::string& reason)
51 {
52 BOOST_CHECK_MESSAGE(false, reason);
53
54 this->afterIo();
55 }
56
57 void
58 face1_onReceiveInterest(const Interest& interest)
59 {
60 m_face1_receivedInterests.push_back(interest);
61
62 this->afterIo();
63 }
64
65 void
66 face1_onReceiveData(const Data& data)
67 {
68 m_face1_receivedDatas.push_back(data);
69
70 this->afterIo();
71 }
72
73 void
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080074 face1_onFail()
75 {
76 m_face1.reset();
77 this->afterIo();
78 }
79
80 void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080081 channel2_onFaceCreated(const shared_ptr<Face>& newFace)
Junxiao Shi96dc0c42014-01-30 23:51:59 -070082 {
83 BOOST_CHECK(!static_cast<bool>(m_face2));
84 m_face2 = newFace;
85 m_face2->onReceiveInterest +=
86 bind(&EndToEndFixture::face2_onReceiveInterest, this, _1);
87 m_face2->onReceiveData +=
88 bind(&EndToEndFixture::face2_onReceiveData, this, _1);
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080089 m_face2->onFail +=
90 bind(&EndToEndFixture::face2_onFail, this);
Junxiao Shi96dc0c42014-01-30 23:51:59 -070091
92 this->afterIo();
93 }
94
95 void
96 channel2_onConnectFailed(const std::string& reason)
97 {
98 BOOST_CHECK_MESSAGE(false, reason);
99
100 this->afterIo();
101 }
102
103 void
104 face2_onReceiveInterest(const Interest& interest)
105 {
106 m_face2_receivedInterests.push_back(interest);
107
108 this->afterIo();
109 }
110
111 void
112 face2_onReceiveData(const Data& data)
113 {
114 m_face2_receivedDatas.push_back(data);
115
116 this->afterIo();
117 }
118
119 void
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800120 face2_onFail()
121 {
122 m_face2.reset();
123 this->afterIo();
124 }
125
126 void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800127 channel_onFaceCreated(const shared_ptr<Face>& newFace)
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800128 {
129 m_faces.push_back(newFace);
130 this->afterIo();
131 }
132
133 void
134 channel_onConnectFailed(const std::string& reason)
135 {
136 BOOST_CHECK_MESSAGE(false, reason);
137
138 this->afterIo();
139 }
140
141 void
142 checkFaceList(size_t shouldBe)
143 {
144 BOOST_CHECK_EQUAL(m_faces.size(), shouldBe);
145 }
146
147 void
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700148 abortTestCase(const std::string& message)
149 {
150 m_ioService.stop();
151 BOOST_FAIL(message);
152 }
153
154private:
155 void
156 afterIo()
157 {
158 if (--m_ioRemaining <= 0) m_ioService.stop();
159 }
160
161public:
162 boost::asio::io_service m_ioService;
163
164 int m_ioRemaining;
165
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800166 shared_ptr<Face> m_face1;
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700167 std::vector<Interest> m_face1_receivedInterests;
168 std::vector<Data> m_face1_receivedDatas;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800169 shared_ptr<Face> m_face2;
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700170 std::vector<Interest> m_face2_receivedInterests;
171 std::vector<Data> m_face2_receivedDatas;
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800172
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800173 std::list< shared_ptr<Face> > m_faces;
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700174};
175
176
177BOOST_FIXTURE_TEST_CASE(EndToEnd, EndToEndFixture)
178{
179 TcpChannelFactory factory(m_ioService);
180 Scheduler scheduler(m_ioService); // to limit the amount of time the test may take
181
182 EventId abortEvent =
183 scheduler.scheduleEvent(time::seconds(1),
184 bind(&EndToEndFixture::abortTestCase, this,
185 "TcpChannel error: cannot connect or cannot accept connection"));
186
187 shared_ptr<TcpChannel> channel1 = factory.create("127.0.0.1", "20070");
188 shared_ptr<TcpChannel> channel2 = factory.create("127.0.0.1", "20071");
189
190 channel1->listen(bind(&EndToEndFixture::channel1_onFaceCreated, this, _1),
191 bind(&EndToEndFixture::channel1_onConnectFailed, this, _1));
192
193 channel2->connect("127.0.0.1", "20070",
194 bind(&EndToEndFixture::channel2_onFaceCreated, this, _1),
195 bind(&EndToEndFixture::channel2_onConnectFailed, this, _1),
196 time::milliseconds(100)); // very short timeout
197
198 m_ioRemaining = 2;
199 m_ioService.run();
200 m_ioService.reset();
201 scheduler.cancelEvent(abortEvent);
202
203 BOOST_REQUIRE(static_cast<bool>(m_face1));
204 BOOST_REQUIRE(static_cast<bool>(m_face2));
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800205
206 BOOST_CHECK_EQUAL(m_face1->isLocal(), true);
207 BOOST_CHECK_EQUAL(m_face2->isLocal(), true);
208
209 BOOST_CHECK_EQUAL(static_cast<bool>(dynamic_pointer_cast<LocalFace>(m_face1)), true);
210 BOOST_CHECK_EQUAL(static_cast<bool>(dynamic_pointer_cast<LocalFace>(m_face2)), true);
211
212 // integrated tests needs to check that TcpFace for non-loopback fails these tests...
213
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700214 abortEvent =
215 scheduler.scheduleEvent(time::seconds(1),
216 bind(&EndToEndFixture::abortTestCase, this,
217 "TcpChannel error: cannot send or receive Interest/Data packets"));
218
219 Interest interest1("ndn:/TpnzGvW9R");
220 Data data1 ("ndn:/KfczhUqVix");
221 data1.setContent(0, 0);
222 Interest interest2("ndn:/QWiIMfj5sL");
223 Data data2 ("ndn:/XNBV796f");
224 data2.setContent(0, 0);
225
226 ndn::SignatureSha256WithRsa fakeSignature;
227 fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue, reinterpret_cast<const uint8_t*>(0), 0));
228
229 // set fake signature on data1 and data2
230 data1.setSignature(fakeSignature);
231 data2.setSignature(fakeSignature);
232
233 m_face1->sendInterest(interest1);
234 m_face1->sendData (data1 );
235 m_face2->sendInterest(interest2);
236 m_face2->sendData (data2 );
237
238 m_ioRemaining = 4;
239 m_ioService.run();
240 m_ioService.reset();
241
242 BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
243 BOOST_REQUIRE_EQUAL(m_face1_receivedDatas .size(), 1);
244 BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
245 BOOST_REQUIRE_EQUAL(m_face2_receivedDatas .size(), 1);
246
247 BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getName(), interest2.getName());
248 BOOST_CHECK_EQUAL(m_face1_receivedDatas [0].getName(), data2.getName());
249 BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getName(), interest1.getName());
250 BOOST_CHECK_EQUAL(m_face2_receivedDatas [0].getName(), data1.getName());
251}
252
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800253BOOST_FIXTURE_TEST_CASE(MultipleAccepts, EndToEndFixture)
254{
255 TcpChannelFactory factory(m_ioService);
256 Scheduler scheduler(m_ioService); // to limit the amount of time the test may take
257
258 EventId abortEvent =
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800259 scheduler.scheduleEvent(time::seconds(4),
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800260 bind(&EndToEndFixture::abortTestCase, this,
261 "TcpChannel error: cannot connect or cannot accept connection"));
262
263 shared_ptr<TcpChannel> channel1 = factory.create("127.0.0.1", "20070");
264 shared_ptr<TcpChannel> channel2 = factory.create("127.0.0.1", "20071");
265
266 channel1->listen(bind(&EndToEndFixture::channel_onFaceCreated, this, _1),
267 bind(&EndToEndFixture::channel_onConnectFailed, this, _1));
268
269 channel2->connect("127.0.0.1", "20070",
270 bind(&EndToEndFixture::channel_onFaceCreated, this, _1),
271 bind(&EndToEndFixture::channel_onConnectFailed, this, _1),
272 time::milliseconds(100)); // very short timeout
273
274 m_ioRemaining = 2;
275 m_ioService.run();
276 m_ioService.reset();
277 scheduler.cancelEvent(abortEvent);
278
279 BOOST_CHECK_EQUAL(m_faces.size(), 2);
280
281 shared_ptr<TcpChannel> channel3 = factory.create("127.0.0.1", "20072");
282 channel3->connect("127.0.0.1", "20070",
283 bind(&EndToEndFixture::channel_onFaceCreated, this, _1),
284 bind(&EndToEndFixture::channel_onConnectFailed, this, _1),
285 time::milliseconds(100)); // very short timeout
286
287
288 shared_ptr<TcpChannel> channel4 = factory.create("127.0.0.1", "20073");
289
290 BOOST_CHECK_NE(channel3, channel4);
291
292 scheduler
293 .scheduleEvent
294 (time::seconds(0.5),
295 bind(&TcpChannel::connect, channel4,
296 "127.0.0.1", "20070",
297 // does not work without static_cast
298 static_cast<TcpChannel::FaceCreatedCallback>(bind(&EndToEndFixture::
299 channel_onFaceCreated, this, _1)),
300 static_cast<TcpChannel::ConnectFailedCallback>(bind(&EndToEndFixture::
301 channel_onConnectFailed, this, _1)),
302 time::milliseconds(100)));
303
304 m_ioRemaining = 4; // 2 connects and 2 accepts
305 abortEvent =
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800306 scheduler.scheduleEvent(time::seconds(4),
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800307 bind(&EndToEndFixture::abortTestCase, this,
308 "TcpChannel error: cannot connect or cannot accept multiple connections"));
309
310 scheduler.scheduleEvent(time::seconds(0.4),
311 bind(&EndToEndFixture::checkFaceList, this, 4));
312
313 m_ioService.run();
314 m_ioService.reset();
315
316 BOOST_CHECK_EQUAL(m_faces.size(), 6);
317}
318
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800319
320BOOST_FIXTURE_TEST_CASE(FaceClosing, EndToEndFixture)
321{
322 TcpChannelFactory factory(m_ioService);
323 Scheduler scheduler(m_ioService); // to limit the amount of time the test may take
324
325 EventId abortEvent =
326 scheduler.scheduleEvent(time::seconds(4),
327 bind(&EndToEndFixture::abortTestCase, this,
328 "TcpChannel error: cannot connect or cannot accept connection"));
329
330 shared_ptr<TcpChannel> channel1 = factory.create("127.0.0.1", "20070");
331 shared_ptr<TcpChannel> channel2 = factory.create("127.0.0.1", "20071");
332
333 channel1->listen(bind(&EndToEndFixture::channel1_onFaceCreated, this, _1),
334 bind(&EndToEndFixture::channel1_onConnectFailed, this, _1));
335
336 channel2->connect("127.0.0.1", "20070",
337 bind(&EndToEndFixture::channel2_onFaceCreated, this, _1),
338 bind(&EndToEndFixture::channel2_onConnectFailed, this, _1),
339 time::milliseconds(100)); // very short timeout
340
341 m_ioRemaining = 2;
342 BOOST_REQUIRE_NO_THROW(m_ioService.run());
343 m_ioService.reset();
344 scheduler.cancelEvent(abortEvent);
345
346 BOOST_CHECK_EQUAL(channel1->size(), 1);
347 BOOST_CHECK_EQUAL(channel2->size(), 1);
348
349 abortEvent =
350 scheduler.scheduleEvent(time::seconds(4),
351 bind(&EndToEndFixture::abortTestCase, this,
352 "FaceClosing error: cannot properly close faces"));
353
354 BOOST_REQUIRE(static_cast<bool>(m_face1));
355 BOOST_CHECK(static_cast<bool>(m_face2));
356
357 m_ioRemaining = 2;
358 // just double check that we are calling the virtual method
359 static_pointer_cast<Face>(m_face1)->close();
360
361 BOOST_REQUIRE_NO_THROW(m_ioService.run());
362 m_ioService.reset();
363 scheduler.cancelEvent(abortEvent);
364
365 // both faces should get closed
366 BOOST_CHECK(!static_cast<bool>(m_face1));
367 BOOST_CHECK(!static_cast<bool>(m_face2));
368
369 BOOST_CHECK_EQUAL(channel1->size(), 0);
370 BOOST_CHECK_EQUAL(channel2->size(), 0);
371}
372
373
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700374BOOST_AUTO_TEST_SUITE_END()
375
376} // namespace nfd