blob: c7cec872ec8d4d88aad7e034e6a292c786620993 [file] [log] [blame]
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +01001/* -*- 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/unix-stream-factory.hpp"
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +01008#include "core/scheduler.hpp"
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +01009#include <ndn-cpp-dev/security/key-chain.hpp>
10
Junxiao Shid9ee45c2014-02-27 15:38:11 -070011#include "tests/test-common.hpp"
12
13namespace nfd {
14namespace tests {
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010015
16using namespace boost::asio::local;
17
Junxiao Shid9ee45c2014-02-27 15:38:11 -070018BOOST_FIXTURE_TEST_SUITE(FaceUnixStream, BaseFixture)
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010019
20BOOST_AUTO_TEST_CASE(ChannelMap)
21{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080022 UnixStreamFactory factory;
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010023
24 shared_ptr<UnixStreamChannel> channel1 = factory.create("foo");
25 shared_ptr<UnixStreamChannel> channel1a = factory.create("foo");
26 BOOST_CHECK_EQUAL(channel1, channel1a);
27
28 shared_ptr<UnixStreamChannel> channel2 = factory.create("bar");
29 BOOST_CHECK_NE(channel1, channel2);
30}
31
Junxiao Shid9ee45c2014-02-27 15:38:11 -070032class EndToEndFixture : protected BaseFixture
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010033{
34public:
35 void
36 client_onConnect(const boost::system::error_code& error)
37 {
38 BOOST_CHECK_MESSAGE(!error, error.message());
39
40 this->afterIo();
41 }
42
43 void
44 channel1_onFaceCreated(const shared_ptr<UnixStreamFace>& newFace)
45 {
46 BOOST_CHECK(!static_cast<bool>(m_face1));
47 m_face1 = newFace;
48 m_face1->onReceiveInterest +=
49 bind(&EndToEndFixture::face1_onReceiveInterest, this, _1);
50 m_face1->onReceiveData +=
51 bind(&EndToEndFixture::face1_onReceiveData, this, _1);
52
53 this->afterIo();
54 }
55
56 void
57 channel1_onConnectFailed(const std::string& reason)
58 {
59 BOOST_CHECK_MESSAGE(false, reason);
60
61 this->afterIo();
62 }
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080063
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010064 void
65 face1_onReceiveInterest(const Interest& interest)
66 {
67 m_face1_receivedInterests.push_back(interest);
68
69 this->afterIo();
70 }
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080071
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010072 void
73 face1_onReceiveData(const Data& data)
74 {
75 m_face1_receivedDatas.push_back(data);
76
77 this->afterIo();
78 }
79
80 void
81 face2_onReceiveInterest(const Interest& interest)
82 {
83 m_face2_receivedInterests.push_back(interest);
84
85 this->afterIo();
86 }
Alexander Afanasyevbd220a02014-02-20 00:29:56 -080087
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +010088 void
89 face2_onReceiveData(const Data& data)
90 {
91 m_face2_receivedDatas.push_back(data);
92
93 this->afterIo();
94 }
95
96 void
97 channel_onFaceCreated(const shared_ptr<UnixStreamFace>& newFace)
98 {
99 m_faces.push_back(newFace);
100
101 this->afterIo();
102 }
103
104 void
105 channel_onConnectFailed(const std::string& reason)
106 {
107 BOOST_CHECK_MESSAGE(false, reason);
108
109 this->afterIo();
110 }
111
112 void
113 abortTestCase(const std::string& message)
114 {
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800115 g_io.stop();
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100116 BOOST_FAIL(message);
117 }
118
119private:
120 void
121 afterIo()
122 {
123 if (--m_ioRemaining <= 0)
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800124 g_io.stop();
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100125 }
126
127protected:
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100128 int m_ioRemaining;
129
130 shared_ptr<UnixStreamFace> m_face1;
131 std::vector<Interest> m_face1_receivedInterests;
132 std::vector<Data> m_face1_receivedDatas;
133 shared_ptr<UnixStreamFace> m_face2;
134 std::vector<Interest> m_face2_receivedInterests;
135 std::vector<Data> m_face2_receivedDatas;
136
137 std::list< shared_ptr<UnixStreamFace> > m_faces;
138};
139
140
141BOOST_FIXTURE_TEST_CASE(EndToEnd, EndToEndFixture)
142{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -0800143 UnixStreamFactory factory;
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100144
145 EventId abortEvent =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800146 scheduler::schedule(time::seconds(1),
147 bind(&EndToEndFixture::abortTestCase, this,
148 "UnixStreamChannel error: cannot connect or cannot accept connection"));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100149
150 shared_ptr<UnixStreamChannel> channel1 = factory.create("foo");
151 channel1->listen(bind(&EndToEndFixture::channel1_onFaceCreated, this, _1),
152 bind(&EndToEndFixture::channel1_onConnectFailed, this, _1));
153
154 shared_ptr<stream_protocol::socket> client =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800155 make_shared<stream_protocol::socket>(boost::ref(g_io));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100156 client->async_connect(stream_protocol::endpoint("foo"),
157 bind(&EndToEndFixture::client_onConnect, this, _1));
158
159 m_ioRemaining = 2;
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800160 g_io.run();
161 g_io.reset();
162 scheduler::cancel(abortEvent);
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100163
164 BOOST_REQUIRE(static_cast<bool>(m_face1));
165
166 abortEvent =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800167 scheduler::schedule(time::seconds(1),
168 bind(&EndToEndFixture::abortTestCase, this,
169 "UnixStreamChannel error: cannot send or receive Interest/Data packets"));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100170
171 m_face2 = make_shared<UnixStreamFace>(client);
172 m_face2->onReceiveInterest +=
173 bind(&EndToEndFixture::face2_onReceiveInterest, this, _1);
174 m_face2->onReceiveData +=
175 bind(&EndToEndFixture::face2_onReceiveData, this, _1);
176
177 Interest interest1("ndn:/TpnzGvW9R");
178 Data data1 ("ndn:/KfczhUqVix");
179 data1.setContent(0, 0);
180 Interest interest2("ndn:/QWiIMfj5sL");
181 Data data2 ("ndn:/XNBV796f");
182 data2.setContent(0, 0);
183
184 ndn::SignatureSha256WithRsa fakeSignature;
185 fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue, reinterpret_cast<const uint8_t*>(0), 0));
186
187 // set fake signature on data1 and data2
188 data1.setSignature(fakeSignature);
189 data2.setSignature(fakeSignature);
190
191 m_face1->sendInterest(interest1);
192 m_face1->sendData (data1 );
193 m_face2->sendInterest(interest2);
194 m_face2->sendData (data2 );
195
196 m_ioRemaining = 4;
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800197 g_io.run();
198 g_io.reset();
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100199
200 BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
201 BOOST_REQUIRE_EQUAL(m_face1_receivedDatas .size(), 1);
202 BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
203 BOOST_REQUIRE_EQUAL(m_face2_receivedDatas .size(), 1);
204
205 BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getName(), interest2.getName());
206 BOOST_CHECK_EQUAL(m_face1_receivedDatas [0].getName(), data2.getName());
207 BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getName(), interest1.getName());
208 BOOST_CHECK_EQUAL(m_face2_receivedDatas [0].getName(), data1.getName());
209}
210
211BOOST_FIXTURE_TEST_CASE(MultipleAccepts, EndToEndFixture)
212{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -0800213 UnixStreamFactory factory;
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100214
215 EventId abortEvent =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800216 scheduler::schedule(time::seconds(1),
217 bind(&EndToEndFixture::abortTestCase, this,
218 "UnixStreamChannel error: cannot connect or cannot accept connection"));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100219
220 shared_ptr<UnixStreamChannel> channel = factory.create("foo");
221 channel->listen(bind(&EndToEndFixture::channel_onFaceCreated, this, _1),
222 bind(&EndToEndFixture::channel_onConnectFailed, this, _1));
223
224 shared_ptr<stream_protocol::socket> client1 =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800225 make_shared<stream_protocol::socket>(boost::ref(g_io));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100226 client1->async_connect(stream_protocol::endpoint("foo"),
227 bind(&EndToEndFixture::client_onConnect, this, _1));
228
229 m_ioRemaining = 2;
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800230 g_io.run();
231 g_io.reset();
232 scheduler::cancel(abortEvent);
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100233
234 BOOST_CHECK_EQUAL(m_faces.size(), 1);
235
236 abortEvent =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800237 scheduler::schedule(time::seconds(1),
238 bind(&EndToEndFixture::abortTestCase, this,
239 "UnixStreamChannel error: cannot accept multiple connections"));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100240
241 shared_ptr<stream_protocol::socket> client2 =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800242 make_shared<stream_protocol::socket>(boost::ref(g_io));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100243 client2->async_connect(stream_protocol::endpoint("foo"),
244 bind(&EndToEndFixture::client_onConnect, this, _1));
245
246 m_ioRemaining = 2;
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800247 g_io.run();
248 g_io.reset();
249 scheduler::cancel(abortEvent);
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100250
251 BOOST_CHECK_EQUAL(m_faces.size(), 2);
252
253 // now close one of the faces
254 m_faces.front()->close();
255
256 // we should still be able to send/receive with the other one
257 m_face1 = m_faces.back();
258 m_face1->onReceiveInterest +=
259 bind(&EndToEndFixture::face1_onReceiveInterest, this, _1);
260 m_face1->onReceiveData +=
261 bind(&EndToEndFixture::face1_onReceiveData, this, _1);
262
263 m_face2 = make_shared<UnixStreamFace>(client2);
264 m_face2->onReceiveInterest +=
265 bind(&EndToEndFixture::face2_onReceiveInterest, this, _1);
266 m_face2->onReceiveData +=
267 bind(&EndToEndFixture::face2_onReceiveData, this, _1);
268
269 abortEvent =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800270 scheduler::schedule(time::seconds(1),
271 bind(&EndToEndFixture::abortTestCase, this,
272 "UnixStreamChannel error: cannot send or receive Interest/Data packets"));
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100273
274 Interest interest1("ndn:/TpnzGvW9R");
275 Data data1 ("ndn:/KfczhUqVix");
276 data1.setContent(0, 0);
277 Interest interest2("ndn:/QWiIMfj5sL");
278 Data data2 ("ndn:/XNBV796f");
279 data2.setContent(0, 0);
280
281 ndn::SignatureSha256WithRsa fakeSignature;
282 fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue, reinterpret_cast<const uint8_t*>(0), 0));
283
284 // set fake signature on data1 and data2
285 data1.setSignature(fakeSignature);
286 data2.setSignature(fakeSignature);
287
288 m_face1->sendInterest(interest1);
289 m_face1->sendData (data1 );
290 m_face2->sendInterest(interest2);
291 m_face2->sendData (data2 );
292
293 m_ioRemaining = 4;
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800294 g_io.run();
295 g_io.reset();
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100296
297 BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
298 BOOST_REQUIRE_EQUAL(m_face1_receivedDatas .size(), 1);
299 BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
300 BOOST_REQUIRE_EQUAL(m_face2_receivedDatas .size(), 1);
301
302 BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getName(), interest2.getName());
303 BOOST_CHECK_EQUAL(m_face1_receivedDatas [0].getName(), data2.getName());
304 BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getName(), interest1.getName());
305 BOOST_CHECK_EQUAL(m_face2_receivedDatas [0].getName(), data1.getName());
306}
307
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800308static inline void
309noOp()
310{
311}
312
313BOOST_FIXTURE_TEST_CASE(UnixStreamFaceLocalControlHeader, EndToEndFixture)
314{
Alexander Afanasyev0eb70652014-02-27 18:35:07 -0800315 UnixStreamFactory factory;
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800316
317 EventId abortEvent =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800318 scheduler::schedule(time::seconds(1),
319 bind(&EndToEndFixture::abortTestCase, this,
320 "UnixStreamChannel error: cannot connect or cannot accept connection"));
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800321
322 shared_ptr<UnixStreamChannel> channel1 = factory.create("foo");
323 channel1->listen(bind(&EndToEndFixture::channel1_onFaceCreated, this, _1),
324 bind(&EndToEndFixture::channel1_onConnectFailed, this, _1));
325
326 shared_ptr<stream_protocol::socket> client =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800327 make_shared<stream_protocol::socket>(boost::ref(g_io));
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800328 client->async_connect(stream_protocol::endpoint("foo"),
329 bind(&EndToEndFixture::client_onConnect, this, _1));
330
331 m_ioRemaining = 2;
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800332 g_io.run();
333 g_io.reset();
334 scheduler::cancel(abortEvent);
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800335
336 BOOST_REQUIRE(static_cast<bool>(m_face1));
337
338 abortEvent =
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800339 scheduler::schedule(time::seconds(1),
340 bind(&EndToEndFixture::abortTestCase, this,
341 "UnixStreamChannel error: cannot send or receive Interest/Data packets"));
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800342
343 m_face2 = make_shared<UnixStreamFace>(client);
344 m_face2->onReceiveInterest +=
345 bind(&EndToEndFixture::face2_onReceiveInterest, this, _1);
346 m_face2->onReceiveData +=
347 bind(&EndToEndFixture::face2_onReceiveData, this, _1);
348
349 Interest interest1("ndn:/TpnzGvW9R");
350 Data data1 ("ndn:/KfczhUqVix");
351 data1.setContent(0, 0);
352 Interest interest2("ndn:/QWiIMfj5sL");
353 Data data2 ("ndn:/XNBV796f");
354 data2.setContent(0, 0);
355
356 ndn::SignatureSha256WithRsa fakeSignature;
357 fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue, reinterpret_cast<const uint8_t*>(0), 0));
358
359 // set fake signature on data1 and data2
360 data1.setSignature(fakeSignature);
361 data2.setSignature(fakeSignature);
362
363 m_face1->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID);
364 m_face1->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID);
365
366 BOOST_CHECK(m_face1->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID));
367 BOOST_CHECK(m_face1->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
368
369 m_face2->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID);
370 m_face2->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID);
371
372 BOOST_CHECK(m_face2->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID));
373 BOOST_CHECK(m_face2->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
374
375 ////////////////////////////////////////////////////////
376
377 interest1.setIncomingFaceId(11);
378 interest1.setNextHopFaceId(111);
379
380 m_face1->sendInterest(interest1);
381
382 data1.setIncomingFaceId(22);
383 data1.getLocalControlHeader().setNextHopFaceId(222);
384
385 m_face1->sendData (data1);
386
387 //
388
389 m_ioRemaining = 2;
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800390 g_io.run();
391 g_io.reset();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800392
393 BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
394 BOOST_REQUIRE_EQUAL(m_face2_receivedDatas .size(), 1);
395
396 // sending allows only IncomingFaceId, receiving allows only NextHopFaceId
397 BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getLocalControlHeader().hasIncomingFaceId(), false);
398 BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getLocalControlHeader().hasNextHopFaceId(), false);
399
400 BOOST_CHECK_EQUAL(m_face2_receivedDatas[0].getLocalControlHeader().hasIncomingFaceId(), false);
401 BOOST_CHECK_EQUAL(m_face2_receivedDatas[0].getLocalControlHeader().hasNextHopFaceId(), false);
402
403 ////////////////////////////////////////////////////////
404
405 using namespace boost::asio;
406
407 std::vector<const_buffer> interestWithHeader;
408 Block iHeader = interest1.getLocalControlHeader().wireEncode(interest1, true, true);
409 Block iPayload = interest1.wireEncode();
410 interestWithHeader.push_back(buffer(iHeader.wire(), iHeader.size()));
411 interestWithHeader.push_back(buffer(iPayload.wire(), iPayload.size()));
412
413 std::vector<const_buffer> dataWithHeader;
414 Block dHeader = data1.getLocalControlHeader().wireEncode(data1, true, true);
415 Block dPayload = data1.wireEncode();
416 dataWithHeader.push_back(buffer(dHeader.wire(), dHeader.size()));
417 dataWithHeader.push_back(buffer(dPayload.wire(), dPayload.size()));
418
419 //
420
421 client->async_send(interestWithHeader, bind(&noOp));
422 client->async_send(dataWithHeader, bind(&noOp));
423
424 m_ioRemaining = 2;
Alexander Afanasyev7329e022014-02-27 14:47:22 -0800425 g_io.run();
426 g_io.reset();
Alexander Afanasyevbd220a02014-02-20 00:29:56 -0800427
428 BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
429 BOOST_REQUIRE_EQUAL(m_face1_receivedDatas .size(), 1);
430
431 BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getLocalControlHeader().hasIncomingFaceId(), false);
432 BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getLocalControlHeader().hasNextHopFaceId(), true);
433 BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getNextHopFaceId(), 111);
434
435 BOOST_CHECK_EQUAL(m_face1_receivedDatas[0].getLocalControlHeader().hasIncomingFaceId(), false);
436 BOOST_CHECK_EQUAL(m_face1_receivedDatas[0].getLocalControlHeader().hasNextHopFaceId(), false);
437}
438
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100439BOOST_AUTO_TEST_SUITE_END()
440
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700441} // namespace tests
Davide Pesaventobc4dd8c2014-02-14 20:01:01 +0100442} // namespace nfd