blob: f5d274dbc3dcd845762f06083ea5f8fa1b7e5012 [file] [log] [blame]
Alexander Afanasyevf3cfab52014-08-17 22:15:25 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2014 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "util/segment-fetcher.hpp"
23
24#include "boost-test.hpp"
25#include "../dummy-client-face.hpp"
26#include "security/key-chain.hpp"
27
28namespace ndn {
29namespace util {
30namespace tests {
31
32BOOST_AUTO_TEST_SUITE(UtilSegmentFetcher)
33
34class Fixture
35{
36public:
37 Fixture()
38 : face(::ndn::tests::makeDummyClientFace())
39 , nErrors(0)
40 , nDatas(0)
41 , dataSize(0)
42 {
43 }
44
45 shared_ptr<Data>
46 makeData(const Name& baseName, uint64_t segment, bool isFinal)
47 {
48 const uint8_t buffer[] = "Hello, world!";
49
50 shared_ptr<Data> data = make_shared<Data>(Name(baseName).appendSegment(segment));
51 data->setContent(buffer, sizeof(buffer));
52
53 if (isFinal)
54 data->setFinalBlockId(data->getName()[-1]);
55 keyChain.sign(*data);
56
57 return data;
58 }
59
60 void
61 onError(uint32_t errorCode)
62 {
63 ++nErrors;
64 lastError = errorCode;
65 }
66
67 void
68 onData(const ConstBufferPtr& data)
69 {
70 ++nDatas;
71 dataSize = data->size();
72 }
73
74
75public:
76 shared_ptr<ndn::tests::DummyClientFace> face;
77 KeyChain keyChain;
78
79 uint32_t nErrors;
80 uint32_t lastError;
81 uint32_t nDatas;
82 size_t dataSize;
83};
84
85BOOST_FIXTURE_TEST_CASE(Timeout, Fixture)
86{
87 SegmentFetcher::fetch(*face, Interest("/hello/world", time::milliseconds(100)),
88 DontVerifySegment(),
89 bind(&Fixture::onData, this, _1),
90 bind(&Fixture::onError, this, _1));
91
92 face->processEvents(time::seconds(1));
93
94 BOOST_CHECK_EQUAL(nErrors, 1);
95 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::INTEREST_TIMEOUT));
96 BOOST_CHECK_EQUAL(nDatas, 0);
97 BOOST_REQUIRE_EQUAL(face->m_sentInterests.size(), 1);
98 BOOST_CHECK_EQUAL(face->m_sentDatas.size(), 0);
99
100 const Interest& interest = face->m_sentInterests[0];
101 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
102 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
103 BOOST_CHECK_EQUAL(interest.getChildSelector(), 1);
104}
105
106
107BOOST_FIXTURE_TEST_CASE(Basic, Fixture)
108{
109
110 SegmentFetcher::fetch(*face, Interest("/hello/world", time::seconds(1000)),
111 DontVerifySegment(),
112 bind(&Fixture::onData, this, _1),
113 bind(&Fixture::onError, this, _1));
114
115
116 face->processEvents(time::milliseconds(-100));
117 face->receive(*makeData("/hello/world/version0", 0, true));
118 face->processEvents(time::milliseconds(-100));
119
120 BOOST_CHECK_EQUAL(nErrors, 0);
121 BOOST_CHECK_EQUAL(nDatas, 1);
122
123 BOOST_CHECK_EQUAL(dataSize, 14);
124
125 BOOST_REQUIRE_EQUAL(face->m_sentInterests.size(), 1);
126 BOOST_CHECK_EQUAL(face->m_sentDatas.size(), 0);
127
128 const Interest& interest = face->m_sentInterests[0];
129 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
130 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
131 BOOST_CHECK_EQUAL(interest.getChildSelector(), 1);
132}
133
134BOOST_FIXTURE_TEST_CASE(NoSegmentInData, Fixture)
135{
136
137 SegmentFetcher::fetch(*face, Interest("/hello/world", time::seconds(1000)),
138 DontVerifySegment(),
139 bind(&Fixture::onData, this, _1),
140 bind(&Fixture::onError, this, _1));
141
142 face->processEvents(time::milliseconds(-100));
143
144 const uint8_t buffer[] = "Hello, world!";
145
146 shared_ptr<Data> data = make_shared<Data>("/hello/world/version0/no-segment");
147 data->setContent(buffer, sizeof(buffer));
148 keyChain.sign(*data);
149
150 face->receive(*data);
151 face->processEvents(time::milliseconds(-100));
152
153 BOOST_CHECK_EQUAL(nErrors, 1);
154 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::DATA_HAS_NO_SEGMENT));
155 BOOST_CHECK_EQUAL(nDatas, 0);
156}
157
158bool
159failValidation(const Data& data)
160{
161 return false;
162}
163
164BOOST_FIXTURE_TEST_CASE(SegmentValidationFailure, Fixture)
165{
166
167 SegmentFetcher::fetch(*face, Interest("/hello/world", time::seconds(1000)),
168 &failValidation,
169 bind(&Fixture::onData, this, _1),
170 bind(&Fixture::onError, this, _1));
171
172 face->processEvents(time::milliseconds(-100));
173 face->receive(*makeData("/hello/world/version0", 0, true));
174 face->processEvents(time::milliseconds(-100));
175
176 BOOST_CHECK_EQUAL(nErrors, 1);
177 BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::SEGMENT_VERIFICATION_FAIL));
178 BOOST_CHECK_EQUAL(nDatas, 0);
179}
180
181
182BOOST_FIXTURE_TEST_CASE(Triple, Fixture)
183{
184 KeyChain keyChain;
185
186 SegmentFetcher::fetch(*face, Interest("/hello/world", time::seconds(1000)),
187 DontVerifySegment(),
188 bind(&Fixture::onData, this, _1),
189 bind(&Fixture::onError, this, _1));
190
191 face->processEvents(time::milliseconds(-100));
192 face->receive(*makeData("/hello/world/version0", 0, false));
193
194 face->processEvents(time::milliseconds(-100));
195 face->receive(*makeData("/hello/world/version0", 1, false));
196
197 face->processEvents(time::milliseconds(-100));
198 face->receive(*makeData("/hello/world/version0", 2, true));
199
200 face->processEvents(time::milliseconds(-100));
201
202 BOOST_CHECK_EQUAL(nErrors, 0);
203 BOOST_CHECK_EQUAL(nDatas, 1);
204
205 BOOST_CHECK_EQUAL(dataSize, 42);
206
207 BOOST_REQUIRE_EQUAL(face->m_sentInterests.size(), 3);
208 BOOST_CHECK_EQUAL(face->m_sentDatas.size(), 0);
209
210 {
211 const Interest& interest = face->m_sentInterests[0];
212 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
213 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
214 BOOST_CHECK_EQUAL(interest.getChildSelector(), 1);
215 }
216
217 {
218 const Interest& interest = face->m_sentInterests[1];
219 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world/version0/%00%01");
220 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), false);
221 BOOST_CHECK_EQUAL(interest.getChildSelector(), 0);
222 }
223
224 {
225 const Interest& interest = face->m_sentInterests[2];
226 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world/version0/%00%02");
227 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), false);
228 BOOST_CHECK_EQUAL(interest.getChildSelector(), 0);
229 }
230}
231
232BOOST_FIXTURE_TEST_CASE(TripleWithInitialSegmentFetching, Fixture)
233{
234 KeyChain keyChain;
235
236 SegmentFetcher::fetch(*face, Interest("/hello/world", time::seconds(1000)),
237 DontVerifySegment(),
238 bind(&Fixture::onData, this, _1),
239 bind(&Fixture::onError, this, _1));
240
241 face->processEvents(time::milliseconds(-100));
242 face->receive(*makeData("/hello/world/version0", 1, false));
243
244 face->processEvents(time::milliseconds(-100));
245 face->receive(*makeData("/hello/world/version0", 0, false));
246
247 face->processEvents(time::milliseconds(-100));
248 face->receive(*makeData("/hello/world/version0", 1, false));
249
250 face->processEvents(time::milliseconds(-100));
251 face->receive(*makeData("/hello/world/version0", 2, true));
252
253 face->processEvents(time::milliseconds(-100));
254
255 BOOST_CHECK_EQUAL(nErrors, 0);
256 BOOST_CHECK_EQUAL(nDatas, 1);
257
258 BOOST_CHECK_EQUAL(dataSize, 42);
259
260 BOOST_REQUIRE_EQUAL(face->m_sentInterests.size(), 4);
261 BOOST_CHECK_EQUAL(face->m_sentDatas.size(), 0);
262
263 {
264 const Interest& interest = face->m_sentInterests[0];
265 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
266 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
267 BOOST_CHECK_EQUAL(interest.getChildSelector(), 1);
268 }
269
270 {
271 const Interest& interest = face->m_sentInterests[1];
272 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world/version0/%00%00");
273 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), false);
274 BOOST_CHECK_EQUAL(interest.getChildSelector(), 0);
275 }
276
277 {
278 const Interest& interest = face->m_sentInterests[2];
279 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world/version0/%00%01");
280 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), false);
281 BOOST_CHECK_EQUAL(interest.getChildSelector(), 0);
282 }
283
284 {
285 const Interest& interest = face->m_sentInterests[3];
286 BOOST_CHECK_EQUAL(interest.getName(), "/hello/world/version0/%00%02");
287 BOOST_CHECK_EQUAL(interest.getMustBeFresh(), false);
288 BOOST_CHECK_EQUAL(interest.getChildSelector(), 0);
289 }
290}
291
292
293BOOST_AUTO_TEST_SUITE_END()
294
295} // namespace tests
296} // namespace util
297} // namespace ndn