blob: fee58278a95a162a7cacb2e543c9f19a5fae6771 [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
7#include "face/unix-stream-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
14using namespace boost::asio::local;
15
16namespace nfd {
17
18BOOST_AUTO_TEST_SUITE(FaceUnixStream)
19
20BOOST_AUTO_TEST_CASE(ChannelMap)
21{
22 boost::asio::io_service io;
23 UnixStreamChannelFactory factory(io);
24
25 shared_ptr<UnixStreamChannel> channel1 = factory.create("foo");
26 shared_ptr<UnixStreamChannel> channel1a = factory.create("foo");
27 BOOST_CHECK_EQUAL(channel1, channel1a);
28
29 shared_ptr<UnixStreamChannel> channel2 = factory.create("bar");
30 BOOST_CHECK_NE(channel1, channel2);
31}
32
33class EndToEndFixture
34{
35public:
36 void
37 client_onConnect(const boost::system::error_code& error)
38 {
39 BOOST_CHECK_MESSAGE(!error, error.message());
40
41 this->afterIo();
42 }
43
44 void
45 channel1_onFaceCreated(const shared_ptr<UnixStreamFace>& newFace)
46 {
47 BOOST_CHECK(!static_cast<bool>(m_face1));
48 m_face1 = newFace;
49 m_face1->onReceiveInterest +=
50 bind(&EndToEndFixture::face1_onReceiveInterest, this, _1);
51 m_face1->onReceiveData +=
52 bind(&EndToEndFixture::face1_onReceiveData, this, _1);
53
54 this->afterIo();
55 }
56
57 void
58 channel1_onConnectFailed(const std::string& reason)
59 {
60 BOOST_CHECK_MESSAGE(false, reason);
61
62 this->afterIo();
63 }
64
65 void
66 face1_onReceiveInterest(const Interest& interest)
67 {
68 m_face1_receivedInterests.push_back(interest);
69
70 this->afterIo();
71 }
72
73 void
74 face1_onReceiveData(const Data& data)
75 {
76 m_face1_receivedDatas.push_back(data);
77
78 this->afterIo();
79 }
80
81 void
82 face2_onReceiveInterest(const Interest& interest)
83 {
84 m_face2_receivedInterests.push_back(interest);
85
86 this->afterIo();
87 }
88
89 void
90 face2_onReceiveData(const Data& data)
91 {
92 m_face2_receivedDatas.push_back(data);
93
94 this->afterIo();
95 }
96
97 void
98 channel_onFaceCreated(const shared_ptr<UnixStreamFace>& newFace)
99 {
100 m_faces.push_back(newFace);
101
102 this->afterIo();
103 }
104
105 void
106 channel_onConnectFailed(const std::string& reason)
107 {
108 BOOST_CHECK_MESSAGE(false, reason);
109
110 this->afterIo();
111 }
112
113 void
114 abortTestCase(const std::string& message)
115 {
116 m_ioService.stop();
117 BOOST_FAIL(message);
118 }
119
120private:
121 void
122 afterIo()
123 {
124 if (--m_ioRemaining <= 0)
125 m_ioService.stop();
126 }
127
128protected:
129 boost::asio::io_service m_ioService;
130
131 int m_ioRemaining;
132
133 shared_ptr<UnixStreamFace> m_face1;
134 std::vector<Interest> m_face1_receivedInterests;
135 std::vector<Data> m_face1_receivedDatas;
136 shared_ptr<UnixStreamFace> m_face2;
137 std::vector<Interest> m_face2_receivedInterests;
138 std::vector<Data> m_face2_receivedDatas;
139
140 std::list< shared_ptr<UnixStreamFace> > m_faces;
141};
142
143
144BOOST_FIXTURE_TEST_CASE(EndToEnd, EndToEndFixture)
145{
146 UnixStreamChannelFactory factory(m_ioService);
147 Scheduler scheduler(m_ioService); // to limit the amount of time the test may take
148
149 EventId abortEvent =
150 scheduler.scheduleEvent(time::seconds(1),
151 bind(&EndToEndFixture::abortTestCase, this,
152 "UnixStreamChannel error: cannot connect or cannot accept connection"));
153
154 shared_ptr<UnixStreamChannel> channel1 = factory.create("foo");
155 channel1->listen(bind(&EndToEndFixture::channel1_onFaceCreated, this, _1),
156 bind(&EndToEndFixture::channel1_onConnectFailed, this, _1));
157
158 shared_ptr<stream_protocol::socket> client =
159 make_shared<stream_protocol::socket>(boost::ref(m_ioService));
160 client->async_connect(stream_protocol::endpoint("foo"),
161 bind(&EndToEndFixture::client_onConnect, this, _1));
162
163 m_ioRemaining = 2;
164 m_ioService.run();
165 m_ioService.reset();
166 scheduler.cancelEvent(abortEvent);
167
168 BOOST_REQUIRE(static_cast<bool>(m_face1));
169
170 abortEvent =
171 scheduler.scheduleEvent(time::seconds(1),
172 bind(&EndToEndFixture::abortTestCase, this,
173 "UnixStreamChannel error: cannot send or receive Interest/Data packets"));
174
175 m_face2 = make_shared<UnixStreamFace>(client);
176 m_face2->onReceiveInterest +=
177 bind(&EndToEndFixture::face2_onReceiveInterest, this, _1);
178 m_face2->onReceiveData +=
179 bind(&EndToEndFixture::face2_onReceiveData, this, _1);
180
181 Interest interest1("ndn:/TpnzGvW9R");
182 Data data1 ("ndn:/KfczhUqVix");
183 data1.setContent(0, 0);
184 Interest interest2("ndn:/QWiIMfj5sL");
185 Data data2 ("ndn:/XNBV796f");
186 data2.setContent(0, 0);
187
188 ndn::SignatureSha256WithRsa fakeSignature;
189 fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue, reinterpret_cast<const uint8_t*>(0), 0));
190
191 // set fake signature on data1 and data2
192 data1.setSignature(fakeSignature);
193 data2.setSignature(fakeSignature);
194
195 m_face1->sendInterest(interest1);
196 m_face1->sendData (data1 );
197 m_face2->sendInterest(interest2);
198 m_face2->sendData (data2 );
199
200 m_ioRemaining = 4;
201 m_ioService.run();
202 m_ioService.reset();
203
204 BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
205 BOOST_REQUIRE_EQUAL(m_face1_receivedDatas .size(), 1);
206 BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
207 BOOST_REQUIRE_EQUAL(m_face2_receivedDatas .size(), 1);
208
209 BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getName(), interest2.getName());
210 BOOST_CHECK_EQUAL(m_face1_receivedDatas [0].getName(), data2.getName());
211 BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getName(), interest1.getName());
212 BOOST_CHECK_EQUAL(m_face2_receivedDatas [0].getName(), data1.getName());
213}
214
215BOOST_FIXTURE_TEST_CASE(MultipleAccepts, EndToEndFixture)
216{
217 UnixStreamChannelFactory factory(m_ioService);
218 Scheduler scheduler(m_ioService); // to limit the amount of time the test may take
219
220 EventId abortEvent =
221 scheduler.scheduleEvent(time::seconds(1),
222 bind(&EndToEndFixture::abortTestCase, this,
223 "UnixStreamChannel error: cannot connect or cannot accept connection"));
224
225 shared_ptr<UnixStreamChannel> channel = factory.create("foo");
226 channel->listen(bind(&EndToEndFixture::channel_onFaceCreated, this, _1),
227 bind(&EndToEndFixture::channel_onConnectFailed, this, _1));
228
229 shared_ptr<stream_protocol::socket> client1 =
230 make_shared<stream_protocol::socket>(boost::ref(m_ioService));
231 client1->async_connect(stream_protocol::endpoint("foo"),
232 bind(&EndToEndFixture::client_onConnect, this, _1));
233
234 m_ioRemaining = 2;
235 m_ioService.run();
236 m_ioService.reset();
237 scheduler.cancelEvent(abortEvent);
238
239 BOOST_CHECK_EQUAL(m_faces.size(), 1);
240
241 abortEvent =
242 scheduler.scheduleEvent(time::seconds(1),
243 bind(&EndToEndFixture::abortTestCase, this,
244 "UnixStreamChannel error: cannot accept multiple connections"));
245
246 shared_ptr<stream_protocol::socket> client2 =
247 make_shared<stream_protocol::socket>(boost::ref(m_ioService));
248 client2->async_connect(stream_protocol::endpoint("foo"),
249 bind(&EndToEndFixture::client_onConnect, this, _1));
250
251 m_ioRemaining = 2;
252 m_ioService.run();
253 m_ioService.reset();
254 scheduler.cancelEvent(abortEvent);
255
256 BOOST_CHECK_EQUAL(m_faces.size(), 2);
257
258 // now close one of the faces
259 m_faces.front()->close();
260
261 // we should still be able to send/receive with the other one
262 m_face1 = m_faces.back();
263 m_face1->onReceiveInterest +=
264 bind(&EndToEndFixture::face1_onReceiveInterest, this, _1);
265 m_face1->onReceiveData +=
266 bind(&EndToEndFixture::face1_onReceiveData, this, _1);
267
268 m_face2 = make_shared<UnixStreamFace>(client2);
269 m_face2->onReceiveInterest +=
270 bind(&EndToEndFixture::face2_onReceiveInterest, this, _1);
271 m_face2->onReceiveData +=
272 bind(&EndToEndFixture::face2_onReceiveData, this, _1);
273
274 abortEvent =
275 scheduler.scheduleEvent(time::seconds(1),
276 bind(&EndToEndFixture::abortTestCase, this,
277 "UnixStreamChannel error: cannot send or receive Interest/Data packets"));
278
279 Interest interest1("ndn:/TpnzGvW9R");
280 Data data1 ("ndn:/KfczhUqVix");
281 data1.setContent(0, 0);
282 Interest interest2("ndn:/QWiIMfj5sL");
283 Data data2 ("ndn:/XNBV796f");
284 data2.setContent(0, 0);
285
286 ndn::SignatureSha256WithRsa fakeSignature;
287 fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue, reinterpret_cast<const uint8_t*>(0), 0));
288
289 // set fake signature on data1 and data2
290 data1.setSignature(fakeSignature);
291 data2.setSignature(fakeSignature);
292
293 m_face1->sendInterest(interest1);
294 m_face1->sendData (data1 );
295 m_face2->sendInterest(interest2);
296 m_face2->sendData (data2 );
297
298 m_ioRemaining = 4;
299 m_ioService.run();
300 m_ioService.reset();
301
302 BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
303 BOOST_REQUIRE_EQUAL(m_face1_receivedDatas .size(), 1);
304 BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
305 BOOST_REQUIRE_EQUAL(m_face2_receivedDatas .size(), 1);
306
307 BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getName(), interest2.getName());
308 BOOST_CHECK_EQUAL(m_face1_receivedDatas [0].getName(), data2.getName());
309 BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getName(), interest1.getName());
310 BOOST_CHECK_EQUAL(m_face2_receivedDatas [0].getName(), data1.getName());
311}
312
313BOOST_AUTO_TEST_SUITE_END()
314
315} // namespace nfd