blob: d50f8a998fae760cc7c8c679654d16afe892a27a [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
81BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(SetInterestFilter, 2);
82BOOST_AUTO_TEST_CASE(SetInterestFilter)
83{
84 FactoryCallbackApp::Install(getNode("B"), [this] () -> shared_ptr<void> {
85 return make_shared<BasicProducer>("/test", [this] (const Name& interest) {
86 BOOST_CHECK_EQUAL(interest, "/test/prefix/%FE%00");
87 this->hasFired = true;
88 },
89 [] {
90 BOOST_ERROR("Unexpected failure to set interest filter");
91 });
92 })
93 .Start(Seconds(0.01));
94
95 addApps({{"A", "ns3::ndn::ConsumerBatches",
96 {{"Prefix", "/test/prefix"}, {"Batches", "0s 1"}}, "1s", "5.1s"}});
97
98 Simulator::Stop(Seconds(20));
99 Simulator::Run();
100
101 BOOST_CHECK(hasFired);
102}
103
104/////////////////////////////////////////////////////////////////////
105/////////////////////////////////////////////////////////////////////
106/////////////////////////////////////////////////////////////////////
107
108class SingleInterest : public BaseTesterApp
109{
110public:
111 SingleInterest(const Name& name, const NameCallback& onData, const VoidCallback& onTimeout)
112 {
113 m_face.expressInterest(name, std::bind([onData] (const Data& data) {
114 onData(data.getName());
115 }, _2),
116 std::bind(onTimeout));
117 }
118};
119
120
121
122BOOST_AUTO_TEST_CASE(ExpressInterestLocalhost)
123{
124 // Retrieve data from remote
125 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
126 return make_shared<SingleInterest>("/localhost", [this] (const Name& data) {
127 BOOST_CHECK(Name("/localhost").isPrefixOf(data));
128 this->hasFired = true;
129 BOOST_CHECK_LE(Simulator::Now().ToDouble(Time::S), 1.01);
130 },
131 [] {
132 BOOST_ERROR("Unexpected timeout");
133 });
134 })
135 .Start(Seconds(1.01));
136
137 Simulator::Stop(Seconds(20));
138 Simulator::Run();
139
140 BOOST_CHECK(hasFired);
141}
142
143BOOST_AUTO_TEST_CASE(ExpressInterestRemote)
144{
145 addApps({{"B", "ns3::ndn::Producer", {{"Prefix", "/test"}}, "0s", "100s"}});
146
147 // Retrieve data from remote
148 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
149 return make_shared<SingleInterest>("/test/prefix", [this] (const Name& data) {
150 BOOST_CHECK_EQUAL(data, "/test/prefix");
151 this->hasFired = true;
152 BOOST_CHECK_LE(Simulator::Now().ToDouble(Time::S), 2.0);
153 },
154 [] {
155 BOOST_ERROR("Unexpected timeout");
156 });
157 })
158 .Start(Seconds(1.01));
159
160 Simulator::Stop(Seconds(20));
161 Simulator::Run();
162
163 BOOST_CHECK(hasFired);
164}
165
166BOOST_AUTO_TEST_CASE(ExpressInterestTimeout)
167{
168 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
169 return make_shared<SingleInterest>("/test/prefix", [] (const Name&) {
170 BOOST_ERROR("Unexpected data");
171 },
172 [this] {
173 BOOST_CHECK_GT(Simulator::Now().ToDouble(Time::S), 6.0);
174 this->hasFired = true;
175 });
176 })
177 .Start(Seconds(2.01));
178
179 Simulator::Stop(Seconds(20));
180 Simulator::Run();
181
182 BOOST_CHECK(hasFired);
183}
184
185// Expected failure until issue #3121 is resolved
186BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(ExpressInterestWithRib, 2);
187BOOST_AUTO_TEST_CASE(ExpressInterestWithRib)
188{
189 addApps({{"A", "ns3::ndn::Producer", {{"Prefix", "/"}}, "0s", "100s"}});
190
191 // Retrieve data from remote
192 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
193 return make_shared<SingleInterest>("/test/prefix", [this] (const Name& data) {
194 BOOST_CHECK_EQUAL(data, "/test/prefix");
195 this->hasFired = true;
196 BOOST_CHECK_LE(Simulator::Now().ToDouble(Time::S), 2.0);
197 },
198 [] {
199 BOOST_ERROR("Unexpected timeout");
200 });
201 })
202 .Start(Seconds(1.01));
203
204 Simulator::Stop(Seconds(20));
205 Simulator::Run();
206
207 BOOST_CHECK(hasFired);
208}
209
210/////////////////////////////////////////////////////////////////////
211/////////////////////////////////////////////////////////////////////
212/////////////////////////////////////////////////////////////////////
213
214class MultipleInterest : public BaseTesterApp
215{
216public:
217 MultipleInterest(const Name& name, const NameCallback& onData, const VoidCallback& onTimeout)
218 : m_scheduler(m_face.getIoService())
219 , m_event(m_scheduler)
220 {
221 expressNextInterest(name, 0, onData, onTimeout);
222 }
223
224private:
225 void
226 expressNextInterest(const Name& name, uint32_t seqNo, const NameCallback& onData, const VoidCallback& onTimeout)
227 {
228 m_face.expressInterest(Name(name).appendSegment(seqNo), std::bind([=] (const Data& data) {
229 onData(data.getName());
230
231 m_event = m_scheduler.scheduleEvent(time::seconds(1),
232 std::bind(&MultipleInterest::expressNextInterest, this,
233 name, seqNo + 1, onData, onTimeout));
234 }, _2),
235 std::bind(onTimeout));
236 }
237
238private:
239 ::ndn::Scheduler m_scheduler;
240 ::ndn::util::scheduler::ScopedEventId m_event;
241};
242
243BOOST_AUTO_TEST_CASE(ExpressMultipleInterests)
244{
245 addApps({{"B", "ns3::ndn::Producer", {{"Prefix", "/test"}}, "0s", "100s"}});
246
247 size_t recvCount = 0;
248
249 // Retrieve data from remote
250 FactoryCallbackApp::Install(getNode("A"), [this, &recvCount] () -> shared_ptr<void> {
251 return make_shared<MultipleInterest>("/test/prefix", [this, &recvCount] (const Name& data) {
252 BOOST_CHECK_EQUAL(data, Name("/test/prefix").appendSegment(recvCount));
253 ++recvCount;
254 },
255 [] {
256 BOOST_ERROR("Unexpected timeout");
257 });
258 })
259 .Start(Seconds(1.01));
260
261 Simulator::Stop(Seconds(10.9)); // this test case also checks that apps stops properly
262 Simulator::Run();
263
264 BOOST_CHECK_EQUAL(recvCount, 10);
265}
266
267class SingleInterestWithFaceShutdown : public BaseTesterApp
268{
269public:
270 SingleInterestWithFaceShutdown()
271 {
272 m_face.expressInterest(Name("/interest/to/timeout"),
273 std::bind([] {
274 BOOST_ERROR("Unexpected response");
275 }),
276 std::bind([this] {
277 m_face.shutdown();
278 }));
279 }
280};
281
282BOOST_AUTO_TEST_CASE(FaceShutdownFromTimeoutCallback)
283{
284 // This test case to check if Face.shutdown from an onTimeout callback doesn't cause segfaults
285
286 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
287 return make_shared<SingleInterestWithFaceShutdown>();
288 })
289 .Start(Seconds(1.01));
290
291 Simulator::Stop(Seconds(20));
292 Simulator::Run();
293}
294
295BOOST_AUTO_TEST_SUITE_END()
296
297} // namespace ndn
298} // namespace ns3