blob: 31ebfbcbb998b973cba38f70525841f6fc8e25f3 [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"
Spyridon Mastorakis5ea33222016-12-07 14:33:53 -080025#include "ns3/error-model.h"
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -070026
27#include "../tests-common.hpp"
28
29namespace ns3 {
30namespace ndn {
31
32class NndCxxFaceFixture : public ScenarioHelperWithCleanupFixture
33{
34public:
35 NndCxxFaceFixture()
36 : hasFired(false)
37 {
38 Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("10Mbps"));
39 Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("10ms"));
40 Config::SetDefault("ns3::DropTailQueue::MaxPackets", StringValue("20"));
41
42 createTopology({{"A", "B"}});
43 addRoutes({{"A", "B", "/test", 1}});
44 }
45
46protected:
47 bool hasFired;
48};
49
50BOOST_FIXTURE_TEST_SUITE(NdnCxxFace, NndCxxFaceFixture)
51
52class BaseTesterApp
53{
54public:
55 typedef std::function<void(const Name&)> NameCallback;
56 typedef std::function<void()> VoidCallback;
57
58protected:
59 ::ndn::Face m_face;
60};
61
62/////////////////////////////////////////////////////////////////////
63/////////////////////////////////////////////////////////////////////
64/////////////////////////////////////////////////////////////////////
65
66class BasicProducer : public BaseTesterApp
67{
68public:
69 BasicProducer(const Name& name, const NameCallback& onInterest, const VoidCallback& onFail)
70 {
71 m_face.setInterestFilter(name,
72 [this, onInterest] (const ::ndn::InterestFilter& filter, const Interest& interest) {
73 auto data = make_shared<Data>(Name(interest.getName()));
74 StackHelper::getKeyChain().sign(*data);
75 m_face.put(*data);
76 onInterest(interest.getName());
77 },
78 std::bind(onFail));
79 }
80};
81
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -070082BOOST_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
Spyridon Mastorakis5ea33222016-12-07 14:33:53 -0800179 // Make sure NACKs are never received
180 Ptr<ns3::RateErrorModel> model = CreateObject<ns3::RateErrorModel>();
181 model->SetRate(std::numeric_limits<double>::max());
182 Config::Set("/NodeList/*/DeviceList/*/$ns3::PointToPointNetDevice/ReceiveErrorModel", PointerValue(model));
183
Alexander Afanasyev5b4c4672015-08-21 12:23:55 -0700184 Simulator::Stop(Seconds(20));
185 Simulator::Run();
186
187 BOOST_CHECK(hasFired);
188}
189
190// Expected failure until issue #3121 is resolved
191BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(ExpressInterestWithRib, 2);
192BOOST_AUTO_TEST_CASE(ExpressInterestWithRib)
193{
194 addApps({{"A", "ns3::ndn::Producer", {{"Prefix", "/"}}, "0s", "100s"}});
195
196 // Retrieve data from remote
197 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
198 return make_shared<SingleInterest>("/test/prefix", [this] (const Name& data) {
199 BOOST_CHECK_EQUAL(data, "/test/prefix");
200 this->hasFired = true;
201 BOOST_CHECK_LE(Simulator::Now().ToDouble(Time::S), 2.0);
202 },
203 [] {
204 BOOST_ERROR("Unexpected timeout");
205 });
206 })
207 .Start(Seconds(1.01));
208
209 Simulator::Stop(Seconds(20));
210 Simulator::Run();
211
212 BOOST_CHECK(hasFired);
213}
214
215/////////////////////////////////////////////////////////////////////
216/////////////////////////////////////////////////////////////////////
217/////////////////////////////////////////////////////////////////////
218
219class MultipleInterest : public BaseTesterApp
220{
221public:
222 MultipleInterest(const Name& name, const NameCallback& onData, const VoidCallback& onTimeout)
223 : m_scheduler(m_face.getIoService())
224 , m_event(m_scheduler)
225 {
226 expressNextInterest(name, 0, onData, onTimeout);
227 }
228
229private:
230 void
231 expressNextInterest(const Name& name, uint32_t seqNo, const NameCallback& onData, const VoidCallback& onTimeout)
232 {
233 m_face.expressInterest(Name(name).appendSegment(seqNo), std::bind([=] (const Data& data) {
234 onData(data.getName());
235
236 m_event = m_scheduler.scheduleEvent(time::seconds(1),
237 std::bind(&MultipleInterest::expressNextInterest, this,
238 name, seqNo + 1, onData, onTimeout));
239 }, _2),
240 std::bind(onTimeout));
241 }
242
243private:
244 ::ndn::Scheduler m_scheduler;
245 ::ndn::util::scheduler::ScopedEventId m_event;
246};
247
248BOOST_AUTO_TEST_CASE(ExpressMultipleInterests)
249{
250 addApps({{"B", "ns3::ndn::Producer", {{"Prefix", "/test"}}, "0s", "100s"}});
251
252 size_t recvCount = 0;
253
254 // Retrieve data from remote
255 FactoryCallbackApp::Install(getNode("A"), [this, &recvCount] () -> shared_ptr<void> {
256 return make_shared<MultipleInterest>("/test/prefix", [this, &recvCount] (const Name& data) {
257 BOOST_CHECK_EQUAL(data, Name("/test/prefix").appendSegment(recvCount));
258 ++recvCount;
259 },
260 [] {
261 BOOST_ERROR("Unexpected timeout");
262 });
263 })
264 .Start(Seconds(1.01));
265
266 Simulator::Stop(Seconds(10.9)); // this test case also checks that apps stops properly
267 Simulator::Run();
268
269 BOOST_CHECK_EQUAL(recvCount, 10);
270}
271
272class SingleInterestWithFaceShutdown : public BaseTesterApp
273{
274public:
275 SingleInterestWithFaceShutdown()
276 {
277 m_face.expressInterest(Name("/interest/to/timeout"),
278 std::bind([] {
279 BOOST_ERROR("Unexpected response");
280 }),
281 std::bind([this] {
282 m_face.shutdown();
283 }));
284 }
285};
286
287BOOST_AUTO_TEST_CASE(FaceShutdownFromTimeoutCallback)
288{
289 // This test case to check if Face.shutdown from an onTimeout callback doesn't cause segfaults
290
291 FactoryCallbackApp::Install(getNode("A"), [this] () -> shared_ptr<void> {
292 return make_shared<SingleInterestWithFaceShutdown>();
293 })
294 .Start(Seconds(1.01));
295
296 Simulator::Stop(Seconds(20));
297 Simulator::Run();
298}
299
300BOOST_AUTO_TEST_SUITE_END()
301
302} // namespace ndn
303} // namespace ns3