blob: 459b33a9d5fa325b7c6dbfa7fde31b716cecbf53 [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>
Alexander Afanasyev09703402017-02-08 20:18:17 -080023#include <ndn-cxx/lp/tags.hpp>
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -070024
25#include "ns3/ndnSIM/helper/ndn-app-helper.hpp"
Spyridon Mastorakis5ea33222016-12-07 14:33:53 -080026#include "ns3/error-model.h"
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -070027
28#include "../tests-common.hpp"
29
30namespace ns3 {
31namespace ndn {
32
33class NndCxxFaceFixture : public ScenarioHelperWithCleanupFixture
34{
35public:
36 NndCxxFaceFixture()
37 : hasFired(false)
38 {
39 Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("10Mbps"));
40 Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("10ms"));
41 Config::SetDefault("ns3::DropTailQueue::MaxPackets", StringValue("20"));
42
43 createTopology({{"A", "B"}});
44 addRoutes({{"A", "B", "/test", 1}});
45 }
46
47protected:
48 bool hasFired;
49};
50
51BOOST_FIXTURE_TEST_SUITE(NdnCxxFace, NndCxxFaceFixture)
52
53class BaseTesterApp
54{
55public:
56 typedef std::function<void(const Name&)> NameCallback;
57 typedef std::function<void()> VoidCallback;
58
59protected:
60 ::ndn::Face m_face;
61};
62
63/////////////////////////////////////////////////////////////////////
64/////////////////////////////////////////////////////////////////////
65/////////////////////////////////////////////////////////////////////
66
67class BasicProducer : public BaseTesterApp
68{
69public:
70 BasicProducer(const Name& name, const NameCallback& onInterest, const VoidCallback& onFail)
71 {
72 m_face.setInterestFilter(name,
73 [this, onInterest] (const ::ndn::InterestFilter& filter, const Interest& interest) {
74 auto data = make_shared<Data>(Name(interest.getName()));
75 StackHelper::getKeyChain().sign(*data);
76 m_face.put(*data);
77 onInterest(interest.getName());
78 },
79 std::bind(onFail));
80 }
81};
82
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -070083BOOST_AUTO_TEST_CASE(SetInterestFilter)
84{
85 FactoryCallbackApp::Install(getNode("B"), [this] () -> shared_ptr<void> {
86 return make_shared<BasicProducer>("/test", [this] (const Name& interest) {
87 BOOST_CHECK_EQUAL(interest, "/test/prefix/%FE%00");
88 this->hasFired = true;
89 },
90 [] {
91 BOOST_ERROR("Unexpected failure to set interest filter");
92 });
93 })
94 .Start(Seconds(0.01));
95
96 addApps({{"A", "ns3::ndn::ConsumerBatches",
97 {{"Prefix", "/test/prefix"}, {"Batches", "0s 1"}}, "1s", "5.1s"}});
98
99 Simulator::Stop(Seconds(20));
100 Simulator::Run();
101
102 BOOST_CHECK(hasFired);
103}
104
105/////////////////////////////////////////////////////////////////////
106/////////////////////////////////////////////////////////////////////
107/////////////////////////////////////////////////////////////////////
108
109class SingleInterest : public BaseTesterApp
110{
111public:
Alexander Afanasyev09703402017-02-08 20:18:17 -0800112 SingleInterest(const Name& name, const std::function<void(const Data&)>& onData, const VoidCallback& onTimeout)
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -0700113 {
114 m_face.expressInterest(name, std::bind([onData] (const Data& data) {
Alexander Afanasyev09703402017-02-08 20:18:17 -0800115 onData(data);
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -0700116 }, _2),
117 std::bind(onTimeout));
118 }
119};
120
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -0700121BOOST_AUTO_TEST_CASE(ExpressInterestLocalhost)
122{
123 // Retrieve data from remote
124 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
Alexander Afanasyev09703402017-02-08 20:18:17 -0800125 return make_shared<SingleInterest>("/localhost", [this] (const Data& data) {
126 BOOST_CHECK(Name("/localhost").isPrefixOf(data.getName()));
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -0700127 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> {
Alexander Afanasyev09703402017-02-08 20:18:17 -0800148 return make_shared<SingleInterest>("/test/prefix", [this] (const Data& data) {
149 BOOST_CHECK_EQUAL(data.getName(), "/test/prefix");
150 BOOST_REQUIRE(data.getTag<lp::HopCountTag>() != nullptr);
151 BOOST_CHECK_EQUAL(*data.getTag<lp::HopCountTag>(), 2);
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -0700152 this->hasFired = true;
153 BOOST_CHECK_LE(Simulator::Now().ToDouble(Time::S), 2.0);
154 },
155 [] {
156 BOOST_ERROR("Unexpected timeout");
157 });
158 })
159 .Start(Seconds(1.01));
160
161 Simulator::Stop(Seconds(20));
162 Simulator::Run();
163
164 BOOST_CHECK(hasFired);
165}
166
167BOOST_AUTO_TEST_CASE(ExpressInterestTimeout)
168{
169 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
Alexander Afanasyev09703402017-02-08 20:18:17 -0800170 return make_shared<SingleInterest>("/test/prefix", [] (const Data&) {
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -0700171 BOOST_ERROR("Unexpected data");
172 },
173 [this] {
174 BOOST_CHECK_GT(Simulator::Now().ToDouble(Time::S), 6.0);
175 this->hasFired = true;
176 });
177 })
178 .Start(Seconds(2.01));
179
Spyridon Mastorakis5ea33222016-12-07 14:33:53 -0800180 // Make sure NACKs are never received
181 Ptr<ns3::RateErrorModel> model = CreateObject<ns3::RateErrorModel>();
182 model->SetRate(std::numeric_limits<double>::max());
183 Config::Set("/NodeList/*/DeviceList/*/$ns3::PointToPointNetDevice/ReceiveErrorModel", PointerValue(model));
184
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -0700185 Simulator::Stop(Seconds(20));
186 Simulator::Run();
187
188 BOOST_CHECK(hasFired);
189}
190
191// Expected failure until issue #3121 is resolved
192BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(ExpressInterestWithRib, 2);
193BOOST_AUTO_TEST_CASE(ExpressInterestWithRib)
194{
195 addApps({{"A", "ns3::ndn::Producer", {{"Prefix", "/"}}, "0s", "100s"}});
196
197 // Retrieve data from remote
198 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
Alexander Afanasyev09703402017-02-08 20:18:17 -0800199 return make_shared<SingleInterest>("/test/prefix", [this] (const Data& data) {
200 BOOST_CHECK_EQUAL(data.getName(), "/test/prefix");
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -0700201 this->hasFired = true;
202 BOOST_CHECK_LE(Simulator::Now().ToDouble(Time::S), 2.0);
203 },
204 [] {
205 BOOST_ERROR("Unexpected timeout");
206 });
207 })
208 .Start(Seconds(1.01));
209
210 Simulator::Stop(Seconds(20));
211 Simulator::Run();
212
213 BOOST_CHECK(hasFired);
214}
215
216/////////////////////////////////////////////////////////////////////
217/////////////////////////////////////////////////////////////////////
218/////////////////////////////////////////////////////////////////////
219
220class MultipleInterest : public BaseTesterApp
221{
222public:
223 MultipleInterest(const Name& name, const NameCallback& onData, const VoidCallback& onTimeout)
224 : m_scheduler(m_face.getIoService())
225 , m_event(m_scheduler)
226 {
227 expressNextInterest(name, 0, onData, onTimeout);
228 }
229
230private:
231 void
232 expressNextInterest(const Name& name, uint32_t seqNo, const NameCallback& onData, const VoidCallback& onTimeout)
233 {
234 m_face.expressInterest(Name(name).appendSegment(seqNo), std::bind([=] (const Data& data) {
235 onData(data.getName());
236
237 m_event = m_scheduler.scheduleEvent(time::seconds(1),
238 std::bind(&MultipleInterest::expressNextInterest, this,
239 name, seqNo + 1, onData, onTimeout));
240 }, _2),
241 std::bind(onTimeout));
242 }
243
244private:
245 ::ndn::Scheduler m_scheduler;
246 ::ndn::util::scheduler::ScopedEventId m_event;
247};
248
249BOOST_AUTO_TEST_CASE(ExpressMultipleInterests)
250{
251 addApps({{"B", "ns3::ndn::Producer", {{"Prefix", "/test"}}, "0s", "100s"}});
252
253 size_t recvCount = 0;
254
255 // Retrieve data from remote
256 FactoryCallbackApp::Install(getNode("A"), [this, &recvCount] () -> shared_ptr<void> {
257 return make_shared<MultipleInterest>("/test/prefix", [this, &recvCount] (const Name& data) {
258 BOOST_CHECK_EQUAL(data, Name("/test/prefix").appendSegment(recvCount));
259 ++recvCount;
260 },
261 [] {
262 BOOST_ERROR("Unexpected timeout");
263 });
264 })
265 .Start(Seconds(1.01));
266
267 Simulator::Stop(Seconds(10.9)); // this test case also checks that apps stops properly
268 Simulator::Run();
269
270 BOOST_CHECK_EQUAL(recvCount, 10);
271}
272
273class SingleInterestWithFaceShutdown : public BaseTesterApp
274{
275public:
276 SingleInterestWithFaceShutdown()
277 {
278 m_face.expressInterest(Name("/interest/to/timeout"),
279 std::bind([] {
280 BOOST_ERROR("Unexpected response");
281 }),
282 std::bind([this] {
283 m_face.shutdown();
284 }));
285 }
286};
287
288BOOST_AUTO_TEST_CASE(FaceShutdownFromTimeoutCallback)
289{
290 // This test case to check if Face.shutdown from an onTimeout callback doesn't cause segfaults
291
292 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
293 return make_shared<SingleInterestWithFaceShutdown>();
294 })
295 .Start(Seconds(1.01));
296
297 Simulator::Stop(Seconds(20));
298 Simulator::Run();
299}
300
301BOOST_AUTO_TEST_SUITE_END()
302
303} // namespace ndn
304} // namespace ns3