blob: d64d1cefebe7ccf1c26a4b3e98e5e3fcfdb5a6f2 [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
35 channel1_onFaceCreated(const shared_ptr<TcpFace>& newFace)
36 {
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
Junxiao Shi96dc0c42014-01-30 23:51:59 -070081 channel2_onFaceCreated(const shared_ptr<TcpFace>& newFace)
82 {
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 Afanasyeva16abd22014-01-31 18:12:29 -0800127 channel_onFaceCreated(const shared_ptr<TcpFace>& newFace)
128 {
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
166 shared_ptr<TcpFace> m_face1;
167 std::vector<Interest> m_face1_receivedInterests;
168 std::vector<Data> m_face1_receivedDatas;
169 shared_ptr<TcpFace> m_face2;
170 std::vector<Interest> m_face2_receivedInterests;
171 std::vector<Data> m_face2_receivedDatas;
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800172
173 std::list< shared_ptr<TcpFace> > 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));
205
206 abortEvent =
207 scheduler.scheduleEvent(time::seconds(1),
208 bind(&EndToEndFixture::abortTestCase, this,
209 "TcpChannel error: cannot send or receive Interest/Data packets"));
210
211 Interest interest1("ndn:/TpnzGvW9R");
212 Data data1 ("ndn:/KfczhUqVix");
213 data1.setContent(0, 0);
214 Interest interest2("ndn:/QWiIMfj5sL");
215 Data data2 ("ndn:/XNBV796f");
216 data2.setContent(0, 0);
217
218 ndn::SignatureSha256WithRsa fakeSignature;
219 fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue, reinterpret_cast<const uint8_t*>(0), 0));
220
221 // set fake signature on data1 and data2
222 data1.setSignature(fakeSignature);
223 data2.setSignature(fakeSignature);
224
225 m_face1->sendInterest(interest1);
226 m_face1->sendData (data1 );
227 m_face2->sendInterest(interest2);
228 m_face2->sendData (data2 );
229
230 m_ioRemaining = 4;
231 m_ioService.run();
232 m_ioService.reset();
233
234 BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
235 BOOST_REQUIRE_EQUAL(m_face1_receivedDatas .size(), 1);
236 BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
237 BOOST_REQUIRE_EQUAL(m_face2_receivedDatas .size(), 1);
238
239 BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getName(), interest2.getName());
240 BOOST_CHECK_EQUAL(m_face1_receivedDatas [0].getName(), data2.getName());
241 BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getName(), interest1.getName());
242 BOOST_CHECK_EQUAL(m_face2_receivedDatas [0].getName(), data1.getName());
243}
244
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800245BOOST_FIXTURE_TEST_CASE(MultipleAccepts, EndToEndFixture)
246{
247 TcpChannelFactory factory(m_ioService);
248 Scheduler scheduler(m_ioService); // to limit the amount of time the test may take
249
250 EventId abortEvent =
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800251 scheduler.scheduleEvent(time::seconds(4),
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800252 bind(&EndToEndFixture::abortTestCase, this,
253 "TcpChannel error: cannot connect or cannot accept connection"));
254
255 shared_ptr<TcpChannel> channel1 = factory.create("127.0.0.1", "20070");
256 shared_ptr<TcpChannel> channel2 = factory.create("127.0.0.1", "20071");
257
258 channel1->listen(bind(&EndToEndFixture::channel_onFaceCreated, this, _1),
259 bind(&EndToEndFixture::channel_onConnectFailed, this, _1));
260
261 channel2->connect("127.0.0.1", "20070",
262 bind(&EndToEndFixture::channel_onFaceCreated, this, _1),
263 bind(&EndToEndFixture::channel_onConnectFailed, this, _1),
264 time::milliseconds(100)); // very short timeout
265
266 m_ioRemaining = 2;
267 m_ioService.run();
268 m_ioService.reset();
269 scheduler.cancelEvent(abortEvent);
270
271 BOOST_CHECK_EQUAL(m_faces.size(), 2);
272
273 shared_ptr<TcpChannel> channel3 = factory.create("127.0.0.1", "20072");
274 channel3->connect("127.0.0.1", "20070",
275 bind(&EndToEndFixture::channel_onFaceCreated, this, _1),
276 bind(&EndToEndFixture::channel_onConnectFailed, this, _1),
277 time::milliseconds(100)); // very short timeout
278
279
280 shared_ptr<TcpChannel> channel4 = factory.create("127.0.0.1", "20073");
281
282 BOOST_CHECK_NE(channel3, channel4);
283
284 scheduler
285 .scheduleEvent
286 (time::seconds(0.5),
287 bind(&TcpChannel::connect, channel4,
288 "127.0.0.1", "20070",
289 // does not work without static_cast
290 static_cast<TcpChannel::FaceCreatedCallback>(bind(&EndToEndFixture::
291 channel_onFaceCreated, this, _1)),
292 static_cast<TcpChannel::ConnectFailedCallback>(bind(&EndToEndFixture::
293 channel_onConnectFailed, this, _1)),
294 time::milliseconds(100)));
295
296 m_ioRemaining = 4; // 2 connects and 2 accepts
297 abortEvent =
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800298 scheduler.scheduleEvent(time::seconds(4),
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800299 bind(&EndToEndFixture::abortTestCase, this,
300 "TcpChannel error: cannot connect or cannot accept multiple connections"));
301
302 scheduler.scheduleEvent(time::seconds(0.4),
303 bind(&EndToEndFixture::checkFaceList, this, 4));
304
305 m_ioService.run();
306 m_ioService.reset();
307
308 BOOST_CHECK_EQUAL(m_faces.size(), 6);
309}
310
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800311
312BOOST_FIXTURE_TEST_CASE(FaceClosing, EndToEndFixture)
313{
314 TcpChannelFactory factory(m_ioService);
315 Scheduler scheduler(m_ioService); // to limit the amount of time the test may take
316
317 EventId abortEvent =
318 scheduler.scheduleEvent(time::seconds(4),
319 bind(&EndToEndFixture::abortTestCase, this,
320 "TcpChannel error: cannot connect or cannot accept connection"));
321
322 shared_ptr<TcpChannel> channel1 = factory.create("127.0.0.1", "20070");
323 shared_ptr<TcpChannel> channel2 = factory.create("127.0.0.1", "20071");
324
325 channel1->listen(bind(&EndToEndFixture::channel1_onFaceCreated, this, _1),
326 bind(&EndToEndFixture::channel1_onConnectFailed, this, _1));
327
328 channel2->connect("127.0.0.1", "20070",
329 bind(&EndToEndFixture::channel2_onFaceCreated, this, _1),
330 bind(&EndToEndFixture::channel2_onConnectFailed, this, _1),
331 time::milliseconds(100)); // very short timeout
332
333 m_ioRemaining = 2;
334 BOOST_REQUIRE_NO_THROW(m_ioService.run());
335 m_ioService.reset();
336 scheduler.cancelEvent(abortEvent);
337
338 BOOST_CHECK_EQUAL(channel1->size(), 1);
339 BOOST_CHECK_EQUAL(channel2->size(), 1);
340
341 abortEvent =
342 scheduler.scheduleEvent(time::seconds(4),
343 bind(&EndToEndFixture::abortTestCase, this,
344 "FaceClosing error: cannot properly close faces"));
345
346 BOOST_REQUIRE(static_cast<bool>(m_face1));
347 BOOST_CHECK(static_cast<bool>(m_face2));
348
349 m_ioRemaining = 2;
350 // just double check that we are calling the virtual method
351 static_pointer_cast<Face>(m_face1)->close();
352
353 BOOST_REQUIRE_NO_THROW(m_ioService.run());
354 m_ioService.reset();
355 scheduler.cancelEvent(abortEvent);
356
357 // both faces should get closed
358 BOOST_CHECK(!static_cast<bool>(m_face1));
359 BOOST_CHECK(!static_cast<bool>(m_face2));
360
361 BOOST_CHECK_EQUAL(channel1->size(), 0);
362 BOOST_CHECK_EQUAL(channel2->size(), 0);
363}
364
365
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700366BOOST_AUTO_TEST_SUITE_END()
367
368} // namespace nfd