blob: c78c8dff96e3bd8673e8723bff12096a566fe661 [file] [log] [blame]
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2011-2015 Regents of the University of California.
4 *
5 * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
6 * contributors.
7 *
8 * ndnSIM is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * ndnSIM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * ndnSIM, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 **/
19
20#include <ndn-cxx/face.hpp>
21#include <ndn-cxx/util/scheduler.hpp>
22#include <ndn-cxx/util/scheduler-scoped-event-id.hpp>
23
24#include "ns3/ndnSIM/helper/ndn-app-helper.hpp"
25
26#include "../tests-common.hpp"
27
28namespace ns3 {
29namespace ndn {
30
31class NndCxxFaceFixture : public ScenarioHelperWithCleanupFixture
32{
33public:
34 NndCxxFaceFixture()
35 : hasFired(false)
36 {
37 Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("10Mbps"));
38 Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("10ms"));
39 Config::SetDefault("ns3::DropTailQueue::MaxPackets", StringValue("20"));
40
41 createTopology({{"A", "B"}});
42 addRoutes({{"A", "B", "/test", 1}});
43 }
44
45protected:
46 bool hasFired;
47};
48
49BOOST_FIXTURE_TEST_SUITE(NdnCxxFace, NndCxxFaceFixture)
50
51class BaseTesterApp
52{
53public:
54 typedef std::function<void(const Name&)> NameCallback;
55 typedef std::function<void()> VoidCallback;
56
57protected:
58 ::ndn::Face m_face;
59};
60
61/////////////////////////////////////////////////////////////////////
62/////////////////////////////////////////////////////////////////////
63/////////////////////////////////////////////////////////////////////
64
65class BasicProducer : public BaseTesterApp
66{
67public:
68 BasicProducer(const Name& name, const NameCallback& onInterest, const VoidCallback& onFail)
69 {
70 m_face.setInterestFilter(name,
71 [this, onInterest] (const ::ndn::InterestFilter& filter, const Interest& interest) {
72 auto data = make_shared<Data>(Name(interest.getName()));
73 StackHelper::getKeyChain().sign(*data);
74 m_face.put(*data);
75 onInterest(interest.getName());
76 },
77 std::bind(onFail));
78 }
79};
80
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -070081BOOST_AUTO_TEST_CASE(SetInterestFilter)
82{
83 FactoryCallbackApp::Install(getNode("B"), [this] () -> shared_ptr<void> {
84 return make_shared<BasicProducer>("/test", [this] (const Name& interest) {
85 BOOST_CHECK_EQUAL(interest, "/test/prefix/%FE%00");
86 this->hasFired = true;
87 },
88 [] {
89 BOOST_ERROR("Unexpected failure to set interest filter");
90 });
91 })
92 .Start(Seconds(0.01));
93
94 addApps({{"A", "ns3::ndn::ConsumerBatches",
95 {{"Prefix", "/test/prefix"}, {"Batches", "0s 1"}}, "1s", "5.1s"}});
96
97 Simulator::Stop(Seconds(20));
98 Simulator::Run();
99
100 BOOST_CHECK(hasFired);
101}
102
103/////////////////////////////////////////////////////////////////////
104/////////////////////////////////////////////////////////////////////
105/////////////////////////////////////////////////////////////////////
106
107class SingleInterest : public BaseTesterApp
108{
109public:
110 SingleInterest(const Name& name, const NameCallback& onData, const VoidCallback& onTimeout)
111 {
112 m_face.expressInterest(name, std::bind([onData] (const Data& data) {
113 onData(data.getName());
114 }, _2),
115 std::bind(onTimeout));
116 }
117};
118
119
120
121BOOST_AUTO_TEST_CASE(ExpressInterestLocalhost)
122{
123 // Retrieve data from remote
124 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
125 return make_shared<SingleInterest>("/localhost", [this] (const Name& data) {
126 BOOST_CHECK(Name("/localhost").isPrefixOf(data));
127 this->hasFired = true;
128 BOOST_CHECK_LE(Simulator::Now().ToDouble(Time::S), 1.01);
129 },
130 [] {
131 BOOST_ERROR("Unexpected timeout");
132 });
133 })
134 .Start(Seconds(1.01));
135
136 Simulator::Stop(Seconds(20));
137 Simulator::Run();
138
139 BOOST_CHECK(hasFired);
140}
141
142BOOST_AUTO_TEST_CASE(ExpressInterestRemote)
143{
144 addApps({{"B", "ns3::ndn::Producer", {{"Prefix", "/test"}}, "0s", "100s"}});
145
146 // Retrieve data from remote
147 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
148 return make_shared<SingleInterest>("/test/prefix", [this] (const Name& data) {
149 BOOST_CHECK_EQUAL(data, "/test/prefix");
150 this->hasFired = true;
151 BOOST_CHECK_LE(Simulator::Now().ToDouble(Time::S), 2.0);
152 },
153 [] {
154 BOOST_ERROR("Unexpected timeout");
155 });
156 })
157 .Start(Seconds(1.01));
158
159 Simulator::Stop(Seconds(20));
160 Simulator::Run();
161
162 BOOST_CHECK(hasFired);
163}
164
165BOOST_AUTO_TEST_CASE(ExpressInterestTimeout)
166{
167 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
168 return make_shared<SingleInterest>("/test/prefix", [] (const Name&) {
169 BOOST_ERROR("Unexpected data");
170 },
171 [this] {
172 BOOST_CHECK_GT(Simulator::Now().ToDouble(Time::S), 6.0);
173 this->hasFired = true;
174 });
175 })
176 .Start(Seconds(2.01));
177
178 Simulator::Stop(Seconds(20));
179 Simulator::Run();
180
181 BOOST_CHECK(hasFired);
182}
183
184// Expected failure until issue #3121 is resolved
185BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(ExpressInterestWithRib, 2);
186BOOST_AUTO_TEST_CASE(ExpressInterestWithRib)
187{
188 addApps({{"A", "ns3::ndn::Producer", {{"Prefix", "/"}}, "0s", "100s"}});
189
190 // Retrieve data from remote
191 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
192 return make_shared<SingleInterest>("/test/prefix", [this] (const Name& data) {
193 BOOST_CHECK_EQUAL(data, "/test/prefix");
194 this->hasFired = true;
195 BOOST_CHECK_LE(Simulator::Now().ToDouble(Time::S), 2.0);
196 },
197 [] {
198 BOOST_ERROR("Unexpected timeout");
199 });
200 })
201 .Start(Seconds(1.01));
202
203 Simulator::Stop(Seconds(20));
204 Simulator::Run();
205
206 BOOST_CHECK(hasFired);
207}
208
209/////////////////////////////////////////////////////////////////////
210/////////////////////////////////////////////////////////////////////
211/////////////////////////////////////////////////////////////////////
212
213class MultipleInterest : public BaseTesterApp
214{
215public:
216 MultipleInterest(const Name& name, const NameCallback& onData, const VoidCallback& onTimeout)
217 : m_scheduler(m_face.getIoService())
218 , m_event(m_scheduler)
219 {
220 expressNextInterest(name, 0, onData, onTimeout);
221 }
222
223private:
224 void
225 expressNextInterest(const Name& name, uint32_t seqNo, const NameCallback& onData, const VoidCallback& onTimeout)
226 {
227 m_face.expressInterest(Name(name).appendSegment(seqNo), std::bind([=] (const Data& data) {
228 onData(data.getName());
229
230 m_event = m_scheduler.scheduleEvent(time::seconds(1),
231 std::bind(&MultipleInterest::expressNextInterest, this,
232 name, seqNo + 1, onData, onTimeout));
233 }, _2),
234 std::bind(onTimeout));
235 }
236
237private:
238 ::ndn::Scheduler m_scheduler;
239 ::ndn::util::scheduler::ScopedEventId m_event;
240};
241
242BOOST_AUTO_TEST_CASE(ExpressMultipleInterests)
243{
244 addApps({{"B", "ns3::ndn::Producer", {{"Prefix", "/test"}}, "0s", "100s"}});
245
246 size_t recvCount = 0;
247
248 // Retrieve data from remote
249 FactoryCallbackApp::Install(getNode("A"), [this, &recvCount] () -> shared_ptr<void> {
250 return make_shared<MultipleInterest>("/test/prefix", [this, &recvCount] (const Name& data) {
251 BOOST_CHECK_EQUAL(data, Name("/test/prefix").appendSegment(recvCount));
252 ++recvCount;
253 },
254 [] {
255 BOOST_ERROR("Unexpected timeout");
256 });
257 })
258 .Start(Seconds(1.01));
259
260 Simulator::Stop(Seconds(10.9)); // this test case also checks that apps stops properly
261 Simulator::Run();
262
263 BOOST_CHECK_EQUAL(recvCount, 10);
264}
265
266class SingleInterestWithFaceShutdown : public BaseTesterApp
267{
268public:
269 SingleInterestWithFaceShutdown()
270 {
271 m_face.expressInterest(Name("/interest/to/timeout"),
272 std::bind([] {
273 BOOST_ERROR("Unexpected response");
274 }),
275 std::bind([this] {
276 m_face.shutdown();
277 }));
278 }
279};
280
281BOOST_AUTO_TEST_CASE(FaceShutdownFromTimeoutCallback)
282{
283 // This test case to check if Face.shutdown from an onTimeout callback doesn't cause segfaults
284
285 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
286 return make_shared<SingleInterestWithFaceShutdown>();
287 })
288 .Start(Seconds(1.01));
289
290 Simulator::Stop(Seconds(20));
291 Simulator::Run();
292}
293
294BOOST_AUTO_TEST_SUITE_END()
295
296} // namespace ndn
297} // namespace ns3