blob: b44e7c5beb7d60716edc974d8f1b172bb71f6c33 [file] [log] [blame]
Zhuo Lib3558892016-08-12 15:51:12 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Eric Newberrybfd66ad2017-05-24 18:19:26 -07003 * Copyright (c) 2014-2017, Arizona Board of Regents.
Zhuo Lib3558892016-08-12 15:51:12 -07004 *
5 * This file is part of ndn-tools (Named Data Networking Essential Tools).
6 * See AUTHORS.md for complete list of ndn-tools authors and contributors.
7 *
8 * ndn-tools 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 * ndn-tools 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 * ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "tools/peek/ndnpeek/ndnpeek.hpp"
21
22#include "tests/test-common.hpp"
Davide Pesaventobf28cd72017-08-13 17:22:47 -040023
Zhuo Lib3558892016-08-12 15:51:12 -070024#include <ndn-cxx/util/dummy-client-face.hpp>
25
26#include <boost/mpl/vector.hpp>
27
28namespace ndn {
29namespace peek {
30namespace tests {
31
32using namespace ndn::tests;
33using boost::test_tools::output_test_stream;
34
35class CoutRedirector : noncopyable
36{
37public:
38 explicit
39 CoutRedirector(std::ostream& destination)
40 {
41 m_originalBuf = std::cout.rdbuf(destination.rdbuf());
42 }
43
44 ~CoutRedirector()
45 {
46 std::cout.rdbuf(m_originalBuf);
47 }
48
49private:
50 std::streambuf* m_originalBuf;
51};
52
53class NdnPeekFixture : public UnitTestTimeFixture
54{
55protected:
56 NdnPeekFixture()
57 : face(io)
58 {
59 }
60
61 void
62 initialize(const PeekOptions& opts)
63 {
64 peek = make_unique<NdnPeek>(face, opts);
65 }
66
67protected:
68 boost::asio::io_service io;
69 ndn::util::DummyClientFace face;
70 output_test_stream output;
71 unique_ptr<NdnPeek> peek;
72};
73
74static PeekOptions
75makeDefaultOptions()
76{
77 PeekOptions opt;
78 opt.prefix = "ndn:/peek/test";
79 opt.minSuffixComponents = -1;
80 opt.maxSuffixComponents = -1;
81 opt.interestLifetime = DEFAULT_INTEREST_LIFETIME;
82 opt.timeout = time::milliseconds(200);
83 opt.link = nullptr;
84 opt.isVerbose = false;
85 opt.mustBeFresh = false;
86 opt.wantRightmostChild = false;
87 opt.wantPayloadOnly = false;
88 return opt;
89}
90
91class OutputFull
92{
93public:
94 static PeekOptions
95 makeOptions()
96 {
97 return makeDefaultOptions();
98 }
99
100 static void
101 checkOutput(output_test_stream& output, const Data& data)
102 {
103 const Block& block = data.wireEncode();
104 std::string expected(reinterpret_cast<const char*>(block.wire()), block.size());
105 BOOST_CHECK(output.is_equal(expected));
106 }
107
108 static void
109 checkOutput(output_test_stream& output, const lp::Nack& nack)
110 {
111 const Block& block = nack.getHeader().wireEncode();
112 std::string expected(reinterpret_cast<const char*>(block.wire()), block.size());
113 BOOST_CHECK(output.is_equal(expected));
114 }
115};
116
117class OutputPayloadOnly
118{
119public:
120 static PeekOptions
121 makeOptions()
122 {
123 PeekOptions opt = makeDefaultOptions();
124 opt.wantPayloadOnly = true;
125 return opt;
126 }
127
128 static void
129 checkOutput(output_test_stream& output, const Data& data)
130 {
131 const Block& block = data.getContent();
132 std::string expected(reinterpret_cast<const char*>(block.value()), block.value_size());
133 BOOST_CHECK(output.is_equal(expected));
134 }
135
136 static void
137 checkOutput(output_test_stream& output, const lp::Nack& nack)
138 {
139 std::string expected = boost::lexical_cast<std::string>(nack.getReason()) + '\n';
140 BOOST_CHECK(output.is_equal(expected));
141 }
142};
143
144BOOST_AUTO_TEST_SUITE(Peek)
145BOOST_FIXTURE_TEST_SUITE(TestNdnPeek, NdnPeekFixture)
146
147using OutputChecks = boost::mpl::vector<OutputFull, OutputPayloadOnly>;
148
149BOOST_AUTO_TEST_CASE_TEMPLATE(Default, OutputCheck, OutputChecks)
150{
151 auto options = OutputCheck::makeOptions();
152 initialize(options);
153
154 auto data = makeData(options.prefix);
155 std::string payload = "NdnPeekTest";
156 data->setContent(reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
157
158 {
159 CoutRedirector redir(output);
160 peek->start();
161 this->advanceClocks(io, time::milliseconds(25), 4);
162 face.receive(*data);
163 }
164
165 OutputCheck::checkOutput(output, *data);
166 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
167 BOOST_CHECK_EQUAL(face.sentInterests.back().getMaxSuffixComponents(), -1);
168 BOOST_CHECK_EQUAL(face.sentInterests.back().getMinSuffixComponents(), -1);
169 BOOST_CHECK_EQUAL(face.sentInterests.back().getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
Junxiao Shia5b60cc2017-07-26 01:35:48 +0000170 BOOST_CHECK(face.sentInterests.back().getForwardingHint().empty());
Zhuo Lib3558892016-08-12 15:51:12 -0700171 BOOST_CHECK_EQUAL(face.sentInterests.back().getMustBeFresh(), false);
Eric Newberrybfd66ad2017-05-24 18:19:26 -0700172 BOOST_CHECK_EQUAL(face.sentInterests.back().getChildSelector(), DEFAULT_CHILD_SELECTOR);
Zhuo Lib3558892016-08-12 15:51:12 -0700173 BOOST_CHECK(peek->getResultCode() == ResultCode::DATA);
174}
175
176BOOST_AUTO_TEST_CASE_TEMPLATE(Selectors, OutputCheck, OutputChecks)
177{
178 auto options = OutputCheck::makeOptions();
179 options.minSuffixComponents = 1;
180 options.maxSuffixComponents = 1;
181 options.interestLifetime = time::milliseconds(200);
Zhuo Lib3558892016-08-12 15:51:12 -0700182 options.mustBeFresh = true;
183 options.wantRightmostChild = true;
184 initialize(options);
185
186 auto data = makeData(options.prefix);
187 std::string payload = "NdnPeekTest";
188 data->setContent(reinterpret_cast<const uint8_t*>(payload.data()), payload.size());
189
190 {
191 CoutRedirector redir(output);
192 peek->start();
193 this->advanceClocks(io, time::milliseconds(25), 4);
194 face.receive(*data);
195 }
196
197 OutputCheck::checkOutput(output, *data);
198 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
199 BOOST_CHECK_EQUAL(face.sentInterests.back().getMaxSuffixComponents(), 1);
200 BOOST_CHECK_EQUAL(face.sentInterests.back().getMinSuffixComponents(), 1);
201 BOOST_CHECK_EQUAL(face.sentInterests.back().getInterestLifetime(), time::milliseconds(200));
Davide Pesaventobf28cd72017-08-13 17:22:47 -0400202 BOOST_CHECK_EQUAL(face.sentInterests.back().getForwardingHint().size(), 0);
Zhuo Lib3558892016-08-12 15:51:12 -0700203 BOOST_CHECK_EQUAL(face.sentInterests.back().getMustBeFresh(), true);
Eric Newberrybfd66ad2017-05-24 18:19:26 -0700204 BOOST_CHECK_EQUAL(face.sentInterests.back().getChildSelector(), 1);
Zhuo Lib3558892016-08-12 15:51:12 -0700205 BOOST_CHECK(peek->getResultCode() == ResultCode::DATA);
206}
207
208BOOST_AUTO_TEST_CASE_TEMPLATE(ReceiveNackWithReason, OutputCheck, OutputChecks)
209{
210 auto options = OutputCheck::makeOptions();
211 initialize(options);
212 lp::Nack nack;
213
214 {
215 CoutRedirector redir(output);
216 peek->start();
217 this->advanceClocks(io, time::milliseconds(25), 4);
218 nack = makeNack(face.sentInterests.at(0), lp::NackReason::NO_ROUTE);
219 face.receive(nack);
220 }
221
222 OutputCheck::checkOutput(output, nack);
223 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
224 BOOST_CHECK(peek->getResultCode() == ResultCode::NACK);
225}
226
227BOOST_AUTO_TEST_CASE_TEMPLATE(ReceiveNackWithoutReason, OutputCheck, OutputChecks)
228{
229 auto options = OutputCheck::makeOptions();
230 initialize(options);
231 lp::Nack nack;
232
233 {
234 CoutRedirector redir(output);
235 peek->start();
236 this->advanceClocks(io, time::milliseconds(25), 4);
237 nack = makeNack(face.sentInterests.at(0), lp::NackReason::NONE);
238 face.receive(nack);
239 }
240
241 OutputCheck::checkOutput(output, nack);
242 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
243 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
244 BOOST_CHECK_EQUAL(face.sentNacks.size(), 0);
245 BOOST_CHECK(peek->getResultCode() == ResultCode::NACK);
246}
247
248BOOST_AUTO_TEST_CASE(TimeoutDefault)
249{
250 auto options = makeDefaultOptions();
251 initialize(options);
252
253 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 0);
254
255 peek->start();
256 this->advanceClocks(io, time::milliseconds(25), 4);
257
258 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
259 BOOST_CHECK(peek->getResultCode() == ResultCode::TIMEOUT);
260}
261
262BOOST_AUTO_TEST_CASE(TimeoutLessThanLifetime)
263{
264 auto options = makeDefaultOptions();
265 options.interestLifetime = time::milliseconds(200);
266 options.timeout = time::milliseconds(100);
267 initialize(options);
268
269 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 0);
270
271 peek->start();
272 this->advanceClocks(io, time::milliseconds(25), 8);
273
274 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
275 BOOST_CHECK(peek->getResultCode() == ResultCode::TIMEOUT);
276}
277
278BOOST_AUTO_TEST_CASE(TimeoutGreaterThanLifetime)
279{
280 auto options = makeDefaultOptions();
281 options.interestLifetime = time::milliseconds(50);
282 options.timeout = time::milliseconds(200);
283 initialize(options);
284
285 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 0);
286
287 peek->start();
288 this->advanceClocks(io, time::milliseconds(25), 4);
289
290 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
291 BOOST_CHECK(peek->getResultCode() == ResultCode::TIMEOUT);
292}
293
294BOOST_AUTO_TEST_SUITE_END() // TestNdnPeek
295BOOST_AUTO_TEST_SUITE_END() // Peek
296
297} // namespace tests
298} // namespace peek
299} // namespace ndn