blob: ff5dc508822c7eb461b3158d55e7153b4b47c8f7 [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
Alexander Afanasyev0eb70652014-02-27 18:35:07 -08007#include "face/tcp-factory.hpp"
Junxiao Shi96dc0c42014-01-30 23:51:59 -07008#include "core/scheduler.hpp"
Junxiao Shi96dc0c42014-01-30 23:51:59 -07009#include <ndn-cpp-dev/security/key-chain.hpp>
10
Junxiao Shid9ee45c2014-02-27 15:38:11 -070011#include "tests/test-common.hpp"
Junxiao Shi96dc0c42014-01-30 23:51:59 -070012
13namespace nfd {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070014namespace tests {
Junxiao Shi96dc0c42014-01-30 23:51:59 -070015
Junxiao Shid9ee45c2014-02-27 15:38:11 -070016BOOST_FIXTURE_TEST_SUITE(FaceTcp, BaseFixture)
Junxiao Shi96dc0c42014-01-30 23:51:59 -070017
18BOOST_AUTO_TEST_CASE(ChannelMap)
19{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080020 TcpFactory factory;
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -080021
Alexander Afanasyevd6655302014-02-28 08:41:28 -080022 shared_ptr<TcpChannel> channel1 = factory.createChannel("127.0.0.1", "20070");
23 shared_ptr<TcpChannel> channel1a = factory.createChannel("127.0.0.1", "20070");
Junxiao Shi96dc0c42014-01-30 23:51:59 -070024 BOOST_CHECK_EQUAL(channel1, channel1a);
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -080025
Alexander Afanasyevd6655302014-02-28 08:41:28 -080026 shared_ptr<TcpChannel> channel2 = factory.createChannel("127.0.0.1", "20071");
Junxiao Shi96dc0c42014-01-30 23:51:59 -070027 BOOST_CHECK_NE(channel1, channel2);
28}
29
Junxiao Shid9ee45c2014-02-27 15:38:11 -070030class EndToEndFixture : protected BaseFixture
Junxiao Shi96dc0c42014-01-30 23:51:59 -070031{
32public:
33 void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080034 channel1_onFaceCreated(const shared_ptr<Face>& newFace)
Junxiao Shi96dc0c42014-01-30 23:51:59 -070035 {
36 BOOST_CHECK(!static_cast<bool>(m_face1));
37 m_face1 = newFace;
38 m_face1->onReceiveInterest +=
39 bind(&EndToEndFixture::face1_onReceiveInterest, this, _1);
40 m_face1->onReceiveData +=
41 bind(&EndToEndFixture::face1_onReceiveData, this, _1);
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -080042 m_face1->onFail +=
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080043 bind(&EndToEndFixture::face1_onFail, this);
Junxiao Shi96dc0c42014-01-30 23:51:59 -070044
45 this->afterIo();
46 }
47
48 void
49 channel1_onConnectFailed(const std::string& reason)
50 {
51 BOOST_CHECK_MESSAGE(false, reason);
52
53 this->afterIo();
54 }
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -080055
Junxiao Shi96dc0c42014-01-30 23:51:59 -070056 void
57 face1_onReceiveInterest(const Interest& interest)
58 {
59 m_face1_receivedInterests.push_back(interest);
60
61 this->afterIo();
62 }
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -080063
Junxiao Shi96dc0c42014-01-30 23:51:59 -070064 void
65 face1_onReceiveData(const Data& data)
66 {
67 m_face1_receivedDatas.push_back(data);
68
69 this->afterIo();
70 }
71
72 void
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080073 face1_onFail()
74 {
75 m_face1.reset();
76 this->afterIo();
77 }
78
79 void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080080 channel2_onFaceCreated(const shared_ptr<Face>& newFace)
Junxiao Shi96dc0c42014-01-30 23:51:59 -070081 {
82 BOOST_CHECK(!static_cast<bool>(m_face2));
83 m_face2 = newFace;
84 m_face2->onReceiveInterest +=
85 bind(&EndToEndFixture::face2_onReceiveInterest, this, _1);
86 m_face2->onReceiveData +=
87 bind(&EndToEndFixture::face2_onReceiveData, this, _1);
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -080088 m_face2->onFail +=
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -080089 bind(&EndToEndFixture::face2_onFail, this);
Junxiao Shi96dc0c42014-01-30 23:51:59 -070090
91 this->afterIo();
92 }
93
94 void
95 channel2_onConnectFailed(const std::string& reason)
96 {
97 BOOST_CHECK_MESSAGE(false, reason);
98
99 this->afterIo();
100 }
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800101
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700102 void
103 face2_onReceiveInterest(const Interest& interest)
104 {
105 m_face2_receivedInterests.push_back(interest);
106
107 this->afterIo();
108 }
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800109
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700110 void
111 face2_onReceiveData(const Data& data)
112 {
113 m_face2_receivedDatas.push_back(data);
114
115 this->afterIo();
116 }
117
118 void
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800119 face2_onFail()
120 {
121 m_face2.reset();
122 this->afterIo();
123 }
124
125 void
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800126 channel_onFaceCreated(const shared_ptr<Face>& newFace)
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800127 {
128 m_faces.push_back(newFace);
129 this->afterIo();
130 }
131
132 void
133 channel_onConnectFailed(const std::string& reason)
134 {
135 BOOST_CHECK_MESSAGE(false, reason);
136
137 this->afterIo();
138 }
139
140 void
141 checkFaceList(size_t shouldBe)
142 {
143 BOOST_CHECK_EQUAL(m_faces.size(), shouldBe);
144 }
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800145
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800146 void
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700147 abortTestCase(const std::string& message)
148 {
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800149 g_io.stop();
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700150 BOOST_FAIL(message);
151 }
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800152
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700153private:
154 void
155 afterIo()
156 {
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800157 if (--m_ioRemaining <= 0)
158 g_io.stop();
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700159 }
160
161public:
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700162 int m_ioRemaining;
163
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800164 shared_ptr<Face> m_face1;
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700165 std::vector<Interest> m_face1_receivedInterests;
166 std::vector<Data> m_face1_receivedDatas;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800167 shared_ptr<Face> m_face2;
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700168 std::vector<Interest> m_face2_receivedInterests;
169 std::vector<Data> m_face2_receivedDatas;
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800170
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800171 std::list< shared_ptr<Face> > m_faces;
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700172};
173
174
175BOOST_FIXTURE_TEST_CASE(EndToEnd, EndToEndFixture)
176{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -0800177 TcpFactory factory;
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700178
179 EventId abortEvent =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800180 scheduler::schedule(time::seconds(10),
181 bind(&EndToEndFixture::abortTestCase, this,
182 "TcpChannel error: cannot connect or cannot accept connection"));
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800183
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800184 shared_ptr<TcpChannel> channel1 = factory.createChannel("127.0.0.1", "20070");
185 shared_ptr<TcpChannel> channel2 = factory.createChannel("127.0.0.1", "20071");
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800186
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700187 channel1->listen(bind(&EndToEndFixture::channel1_onFaceCreated, this, _1),
188 bind(&EndToEndFixture::channel1_onConnectFailed, this, _1));
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800189
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700190 channel2->connect("127.0.0.1", "20070",
191 bind(&EndToEndFixture::channel2_onFaceCreated, this, _1),
192 bind(&EndToEndFixture::channel2_onConnectFailed, this, _1),
Alexander Afanasyevc1e2ee02014-02-25 17:02:07 -0800193 time::seconds(4));
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700194
195 m_ioRemaining = 2;
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800196 g_io.run();
197 g_io.reset();
198 scheduler::cancel(abortEvent);
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700199
200 BOOST_REQUIRE(static_cast<bool>(m_face1));
201 BOOST_REQUIRE(static_cast<bool>(m_face2));
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800202
203 BOOST_CHECK_EQUAL(m_face1->isLocal(), true);
204 BOOST_CHECK_EQUAL(m_face2->isLocal(), true);
205
206 BOOST_CHECK_EQUAL(static_cast<bool>(dynamic_pointer_cast<LocalFace>(m_face1)), true);
207 BOOST_CHECK_EQUAL(static_cast<bool>(dynamic_pointer_cast<LocalFace>(m_face2)), true);
208
209 // integrated tests needs to check that TcpFace for non-loopback fails these tests...
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800210
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700211 abortEvent =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800212 scheduler::schedule(time::seconds(10),
213 bind(&EndToEndFixture::abortTestCase, this,
214 "TcpChannel error: cannot send or receive Interest/Data packets"));
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700215
216 Interest interest1("ndn:/TpnzGvW9R");
217 Data data1 ("ndn:/KfczhUqVix");
218 data1.setContent(0, 0);
219 Interest interest2("ndn:/QWiIMfj5sL");
220 Data data2 ("ndn:/XNBV796f");
221 data2.setContent(0, 0);
222
223 ndn::SignatureSha256WithRsa fakeSignature;
224 fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue, reinterpret_cast<const uint8_t*>(0), 0));
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800225
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700226 // set fake signature on data1 and data2
227 data1.setSignature(fakeSignature);
228 data2.setSignature(fakeSignature);
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800229
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700230 m_face1->sendInterest(interest1);
231 m_face1->sendData (data1 );
232 m_face2->sendInterest(interest2);
233 m_face2->sendData (data2 );
234
235 m_ioRemaining = 4;
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800236 g_io.run();
237 g_io.reset();
238 scheduler::cancel(abortEvent);
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700239
240 BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
241 BOOST_REQUIRE_EQUAL(m_face1_receivedDatas .size(), 1);
242 BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
243 BOOST_REQUIRE_EQUAL(m_face2_receivedDatas .size(), 1);
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800244
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700245 BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getName(), interest2.getName());
246 BOOST_CHECK_EQUAL(m_face1_receivedDatas [0].getName(), data2.getName());
247 BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getName(), interest1.getName());
248 BOOST_CHECK_EQUAL(m_face2_receivedDatas [0].getName(), data1.getName());
249}
250
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800251BOOST_FIXTURE_TEST_CASE(MultipleAccepts, EndToEndFixture)
252{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -0800253 TcpFactory factory;
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800254
255 EventId abortEvent =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800256 scheduler::schedule(time::seconds(10),
257 bind(&EndToEndFixture::abortTestCase, this,
258 "TcpChannel error: cannot connect or cannot accept connection"));
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800259
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800260 shared_ptr<TcpChannel> channel1 = factory.createChannel("127.0.0.1", "20070");
261 shared_ptr<TcpChannel> channel2 = factory.createChannel("127.0.0.1", "20071");
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800262
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800263 channel1->listen(bind(&EndToEndFixture::channel_onFaceCreated, this, _1),
264 bind(&EndToEndFixture::channel_onConnectFailed, this, _1));
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800265
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800266 channel2->connect("127.0.0.1", "20070",
267 bind(&EndToEndFixture::channel_onFaceCreated, this, _1),
268 bind(&EndToEndFixture::channel_onConnectFailed, this, _1),
Alexander Afanasyevc1e2ee02014-02-25 17:02:07 -0800269 time::seconds(4)); // very short timeout
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800270
271 m_ioRemaining = 2;
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800272 g_io.run();
273 g_io.reset();
274 scheduler::cancel(abortEvent);
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800275
276 BOOST_CHECK_EQUAL(m_faces.size(), 2);
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800277
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800278 shared_ptr<TcpChannel> channel3 = factory.createChannel("127.0.0.1", "20072");
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800279 channel3->connect("127.0.0.1", "20070",
280 bind(&EndToEndFixture::channel_onFaceCreated, this, _1),
281 bind(&EndToEndFixture::channel_onConnectFailed, this, _1),
Alexander Afanasyevc1e2ee02014-02-25 17:02:07 -0800282 time::seconds(4)); // very short timeout
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800283
284
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800285 shared_ptr<TcpChannel> channel4 = factory.createChannel("127.0.0.1", "20073");
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800286
287 BOOST_CHECK_NE(channel3, channel4);
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800288
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800289 scheduler
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800290 ::schedule
Alexander Afanasyevc1e2ee02014-02-25 17:02:07 -0800291 (time::seconds(1),
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800292 bind(&TcpChannel::connect, channel4,
293 "127.0.0.1", "20070",
294 // does not work without static_cast
295 static_cast<TcpChannel::FaceCreatedCallback>(bind(&EndToEndFixture::
296 channel_onFaceCreated, this, _1)),
297 static_cast<TcpChannel::ConnectFailedCallback>(bind(&EndToEndFixture::
298 channel_onConnectFailed, this, _1)),
Alexander Afanasyevc1e2ee02014-02-25 17:02:07 -0800299 time::seconds(4)));
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800300
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800301 m_ioRemaining = 4; // 2 connects and 2 accepts
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800302 abortEvent =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800303 scheduler::schedule(time::seconds(10),
304 bind(&EndToEndFixture::abortTestCase, this,
305 "TcpChannel error: cannot connect or cannot accept multiple connections"));
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800306
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800307 scheduler::schedule(time::seconds(0.5),
308 bind(&EndToEndFixture::checkFaceList, this, 4));
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800309
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800310 g_io.run();
311 g_io.reset();
312 scheduler::cancel(abortEvent);
313
Alexander Afanasyeva16abd22014-01-31 18:12:29 -0800314 BOOST_CHECK_EQUAL(m_faces.size(), 6);
315}
316
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800317
318BOOST_FIXTURE_TEST_CASE(FaceClosing, EndToEndFixture)
319{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -0800320 TcpFactory factory;
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800321
322 EventId abortEvent =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800323 scheduler::schedule(time::seconds(10),
324 bind(&EndToEndFixture::abortTestCase, this,
325 "TcpChannel error: cannot connect or cannot accept connection"));
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800326
Alexander Afanasyevd6655302014-02-28 08:41:28 -0800327 shared_ptr<TcpChannel> channel1 = factory.createChannel("127.0.0.1", "20070");
328 shared_ptr<TcpChannel> channel2 = factory.createChannel("127.0.0.1", "20071");
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800329
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800330 channel1->listen(bind(&EndToEndFixture::channel1_onFaceCreated, this, _1),
331 bind(&EndToEndFixture::channel1_onConnectFailed, this, _1));
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800332
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800333 channel2->connect("127.0.0.1", "20070",
334 bind(&EndToEndFixture::channel2_onFaceCreated, this, _1),
335 bind(&EndToEndFixture::channel2_onConnectFailed, this, _1),
Alexander Afanasyevc1e2ee02014-02-25 17:02:07 -0800336 time::seconds(4)); // very short timeout
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800337
338 m_ioRemaining = 2;
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800339 g_io.run();
340 // BOOST_REQUIRE_NO_THROW(g_io.run());
341 g_io.reset();
342 scheduler::cancel(abortEvent);
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800343
344 BOOST_CHECK_EQUAL(channel1->size(), 1);
345 BOOST_CHECK_EQUAL(channel2->size(), 1);
346
347 abortEvent =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800348 scheduler::schedule(time::seconds(10),
349 bind(&EndToEndFixture::abortTestCase, this,
350 "FaceClosing error: cannot properly close faces"));
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800351
352 BOOST_REQUIRE(static_cast<bool>(m_face1));
353 BOOST_CHECK(static_cast<bool>(m_face2));
354
355 m_ioRemaining = 2;
356 // just double check that we are calling the virtual method
357 static_pointer_cast<Face>(m_face1)->close();
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800358
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800359 BOOST_REQUIRE_NO_THROW(g_io.run());
360 g_io.reset();
361 scheduler::cancel(abortEvent);
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800362
363 // both faces should get closed
364 BOOST_CHECK(!static_cast<bool>(m_face1));
365 BOOST_CHECK(!static_cast<bool>(m_face2));
Alexander Afanasyev5f1ec252014-02-28 10:59:17 -0800366
Alexander Afanasyeva0a10fb2014-02-13 19:56:15 -0800367 BOOST_CHECK_EQUAL(channel1->size(), 0);
368 BOOST_CHECK_EQUAL(channel2->size(), 0);
369}
370
371
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700372BOOST_AUTO_TEST_SUITE_END()
373
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700374} // namespace tests
Junxiao Shi96dc0c42014-01-30 23:51:59 -0700375} // namespace nfd