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