blob: 49af9fed47b3f6c13c5deb9ac1120920485d3a8d [file] [log] [blame]
Weiqi Shi28a90fb2014-07-09 10:28:55 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014, Regents of the University of California.
4 *
5 * This file is part of NDN repo-ng (Next generation of NDN repository).
6 * See AUTHORS.md for complete list of repo-ng authors and contributors.
7 *
8 * repo-ng 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 * repo-ng 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 * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "storage/index.hpp"
21
22#include "../sqlite-fixture.hpp"
23#include "../dataset-fixtures.hpp"
24
25#include <boost/test/unit_test.hpp>
26#include <iostream>
27
28namespace repo {
29namespace tests {
30
Alexander Afanasyevb7e8a812014-07-23 01:36:47 -070031BOOST_AUTO_TEST_SUITE(Index)
Weiqi Shif0330d52014-07-09 10:54:27 -070032
Weiqi Shi28a90fb2014-07-09 10:28:55 -070033class FindFixture
34{
35protected:
36 FindFixture()
37 : m_index(std::numeric_limits<size_t>::max())
38 {
39 }
40
41 void
42 insert(int id, const Name& name)
43 {
44 shared_ptr<Data> data = make_shared<Data>(name);
45 data->setContent(reinterpret_cast<const uint8_t*>(&id), sizeof(id));
46 m_keyChain.signWithSha256(*data);
47 data->wireEncode();
48 m_index.insert(*data, id);
49 }
50
51 Interest&
52 startInterest(const Name& name)
53 {
54 m_interest = make_shared<Interest>(name);
55 return *m_interest;
56 }
57
Weiqi Shif0330d52014-07-09 10:54:27 -070058 uint64_t
Weiqi Shi28a90fb2014-07-09 10:28:55 -070059 find()
60 {
61 std::pair<int,Name> found = m_index.find(*m_interest);
62 return found.first;
63 }
64
65protected:
Alexander Afanasyevb7e8a812014-07-23 01:36:47 -070066 repo::Index m_index;
Weiqi Shi28a90fb2014-07-09 10:28:55 -070067 KeyChain m_keyChain;
68 shared_ptr<Interest> m_interest;
69};
70
71BOOST_FIXTURE_TEST_SUITE(Find, FindFixture)
72
73BOOST_AUTO_TEST_CASE(EmptyDataName)
74{
75 insert(1, "ndn:/");
76 startInterest("ndn:/");
77 BOOST_CHECK_EQUAL(find(), 1);
78}
79
80BOOST_AUTO_TEST_CASE(EmptyInterestName)
81{
82 insert(1, "ndn:/A");
83 startInterest("ndn:/");
84 BOOST_CHECK_EQUAL(find(), 1);
85}
86
87BOOST_AUTO_TEST_CASE(Leftmost)
88{
89 insert(1, "ndn:/A");
90 insert(2, "ndn:/B/p/1");
91 insert(3, "ndn:/B/p/2");
92 insert(4, "ndn:/B/q/1");
93 insert(5, "ndn:/B/q/2");
94 insert(6, "ndn:/C");
95
96 startInterest("ndn:/B");
97 BOOST_CHECK_EQUAL(find(), 2);
98}
99
100BOOST_AUTO_TEST_CASE(Rightmost)
101{
102 insert(1, "ndn:/A");
103 insert(2, "ndn:/B/p/1");
104 insert(3, "ndn:/B/p/2");
105 insert(4, "ndn:/B/q/1");
106 insert(5, "ndn:/B/q/2");
107 insert(6, "ndn:/C");
108
109 startInterest("ndn:/B")
110 .setChildSelector(1);
111 BOOST_CHECK_EQUAL(find(), 4);
112}
113
114BOOST_AUTO_TEST_CASE(Leftmost_ExactName1)
115{
116 insert(1, "ndn:/");
117 insert(2, "ndn:/A/B");
118 insert(3, "ndn:/A/C");
119 insert(4, "ndn:/A");
120 insert(5, "ndn:/D");
121
122 // Intuitively you would think Data 4 should be between Data 1 and 2,
123 // but Data 4 has full Name ndn:/A/<32-octet hash>.
124 startInterest("ndn:/A");
125 BOOST_CHECK_EQUAL(find(), 2);
126}
127
128BOOST_AUTO_TEST_CASE(Leftmost_ExactName33)
129{
130 insert(1, "ndn:/");
131 insert(2, "ndn:/A");
132 insert(3, "ndn:/A/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); // 33 'B's
133 insert(4, "ndn:/A/CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"); // 33 'C's
134 insert(5, "ndn:/D");
135
136 // Data 2 is returned, because <32-octet hash> is less than Data 3.
137 startInterest("ndn:/A");
138 BOOST_CHECK_EQUAL(find(), 2);
139}
140
141BOOST_AUTO_TEST_CASE(MinSuffixComponents)
142{
143 insert(1, "ndn:/A/1/2/3/4");
144 insert(2, "ndn:/B/1/2/3");
145 insert(3, "ndn:/C/1/2");
146 insert(4, "ndn:/D/1");
147 insert(5, "ndn:/E");
148 insert(6, "ndn:/");
149
150 startInterest("ndn:/")
151 .setChildSelector(1)
152 .setMinSuffixComponents(0);
153 BOOST_CHECK_EQUAL(find(), 6);
154
155 startInterest("ndn:/")
156 .setChildSelector(1)
157 .setMinSuffixComponents(1);
158 BOOST_CHECK_EQUAL(find(), 6);
159
160 startInterest("ndn:/")
161 .setChildSelector(1)
162 .setMinSuffixComponents(2);
163 BOOST_CHECK_EQUAL(find(), 5);
164
165 startInterest("ndn:/")
166 .setChildSelector(1)
167 .setMinSuffixComponents(3);
168 BOOST_CHECK_EQUAL(find(), 4);
169
170 startInterest("ndn:/")
171 .setChildSelector(1)
172 .setMinSuffixComponents(4);
173 BOOST_CHECK_EQUAL(find(), 3);
174
175 startInterest("ndn:/")
176 .setChildSelector(1)
177 .setMinSuffixComponents(5);
178 BOOST_CHECK_EQUAL(find(), 2);
179
180 startInterest("ndn:/")
181 .setChildSelector(1)
182 .setMinSuffixComponents(6);
183 BOOST_CHECK_EQUAL(find(), 1);
184
185 startInterest("ndn:/")
186 .setChildSelector(1)
187 .setMinSuffixComponents(7);
188 BOOST_CHECK_EQUAL(find(), 0);
189}
190
191BOOST_AUTO_TEST_CASE(MaxSuffixComponents)
192{
193 insert(1, "ndn:/");
194 insert(2, "ndn:/A");
195 insert(3, "ndn:/A/B");
196 insert(4, "ndn:/A/B/C");
197 insert(5, "ndn:/A/B/C/D");
198 insert(6, "ndn:/A/B/C/D/E");
199 // Order is 6,5,4,3,2,1, because <32-octet hash> is greater than a 1-octet component.
200
201 startInterest("ndn:/")
202 .setMaxSuffixComponents(0);
203 BOOST_CHECK_EQUAL(find(), 0);
204
205 startInterest("ndn:/")
206 .setMaxSuffixComponents(1);
207 BOOST_CHECK_EQUAL(find(), 1);
208
209 startInterest("ndn:/")
210 .setMaxSuffixComponents(2);
211 BOOST_CHECK_EQUAL(find(), 2);
212
213 startInterest("ndn:/")
214 .setMaxSuffixComponents(3);
215 BOOST_CHECK_EQUAL(find(), 3);
216
217 startInterest("ndn:/")
218 .setMaxSuffixComponents(4);
219 BOOST_CHECK_EQUAL(find(), 4);
220
221 startInterest("ndn:/")
222 .setMaxSuffixComponents(5);
223 BOOST_CHECK_EQUAL(find(), 5);
224
225 startInterest("ndn:/")
226 .setMaxSuffixComponents(6);
227 BOOST_CHECK_EQUAL(find(), 6);
228}
229
230BOOST_AUTO_TEST_CASE(DigestOrder)
231{
232 insert(1, "ndn:/A");
233 insert(2, "ndn:/A");
234 // We don't know which comes first, but there must be some order
235
236 startInterest("ndn:/A")
237 .setChildSelector(0);
238 uint32_t leftmost = find();
239
240 startInterest("ndn:/A")
241 .setChildSelector(1);
242 uint32_t rightmost = find();
243
244 BOOST_CHECK_NE(leftmost, rightmost);
245}
246
247BOOST_AUTO_TEST_CASE(DigestExclude)
248{
249 insert(1, "ndn:/A/B");
250 insert(2, "ndn:/A");
251 insert(3, "ndn:/A/CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"); // 33 'C's
252
253 startInterest("ndn:/A")
254 .setExclude(Exclude().excludeBefore(Name::Component(reinterpret_cast<const uint8_t*>(
255 "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
256 "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"), 31))); // 31 0xFF's
257 BOOST_CHECK_EQUAL(find(), 2);
258
259 startInterest("ndn:/A")
260 .setChildSelector(1)
261 .setExclude(Exclude().excludeAfter(Name::Component(reinterpret_cast<const uint8_t*>(
262 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
263 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
264 "\x00"), 33))); // 33 0x00's
265 BOOST_CHECK_EQUAL(find(), 2);
266}
267
268BOOST_AUTO_TEST_CASE(ExactName32)
269{
270 insert(1, "ndn:/A/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); // 32 'B's
271 insert(2, "ndn:/A/CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"); // 32 'C's
272
273 startInterest("ndn:/A/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
274 BOOST_CHECK_EQUAL(find(), 1);
275}
276
277BOOST_AUTO_TEST_CASE(MinSuffixComponents32)
278{
279 insert(1, "ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/A/1/2/3/4"); // 32 'x's
280 insert(2, "ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/B/1/2/3");
281 insert(3, "ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/C/1/2");
282 insert(4, "ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/D/1");
283 insert(5, "ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/E");
284 insert(6, "ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
285
286 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
287 .setChildSelector(1)
288 .setMinSuffixComponents(0);
289 BOOST_CHECK_EQUAL(find(), 6);
290
291 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
292 .setChildSelector(1)
293 .setMinSuffixComponents(1);
294 BOOST_CHECK_EQUAL(find(), 6);
295
296 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
297 .setChildSelector(1)
298 .setMinSuffixComponents(2);
299 BOOST_CHECK_EQUAL(find(), 5);
300
301 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
302 .setChildSelector(1)
303 .setMinSuffixComponents(3);
304 BOOST_CHECK_EQUAL(find(), 4);
305
306 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
307 .setChildSelector(1)
308 .setMinSuffixComponents(4);
309 BOOST_CHECK_EQUAL(find(), 3);
310
311 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
312 .setChildSelector(1)
313 .setMinSuffixComponents(5);
314 BOOST_CHECK_EQUAL(find(), 2);
315
316 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
317 .setChildSelector(1)
318 .setMinSuffixComponents(6);
319 BOOST_CHECK_EQUAL(find(), 1);
320
321 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
322 .setChildSelector(1)
323 .setMinSuffixComponents(7);
324 BOOST_CHECK_EQUAL(find(), 0);
325}
326
327BOOST_AUTO_TEST_CASE(MaxSuffixComponents32)
328{
329 insert(1, "ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/"); // 32 'x's
330 insert(2, "ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/A");
331 insert(3, "ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/A/B");
332 insert(4, "ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/A/B/C");
333 insert(5, "ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/A/B/C/D");
334 insert(6, "ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/A/B/C/D/E");
335 // Order is 6,5,4,3,2,1, because <32-octet hash> is greater than a 1-octet component.
336
337 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
338 .setMaxSuffixComponents(0);
339 BOOST_CHECK_EQUAL(find(), 0);
340
341 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
342 .setMaxSuffixComponents(1);
343 BOOST_CHECK_EQUAL(find(), 1);
344
345 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
346 .setMaxSuffixComponents(2);
347 BOOST_CHECK_EQUAL(find(), 2);
348
349 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
350 .setMaxSuffixComponents(3);
351 BOOST_CHECK_EQUAL(find(), 3);
352
353 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
354 .setMaxSuffixComponents(4);
355 BOOST_CHECK_EQUAL(find(), 4);
356
357 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
358 .setMaxSuffixComponents(5);
359 BOOST_CHECK_EQUAL(find(), 5);
360
361 startInterest("ndn:/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
362 .setMaxSuffixComponents(6);
363 BOOST_CHECK_EQUAL(find(), 6);
364}
365
366BOOST_AUTO_TEST_SUITE_END() // Find
367
Alexander Afanasyevb7e8a812014-07-23 01:36:47 -0700368
369template<class Dataset>
370class Fixture : public Dataset
371{
372public:
373 Fixture()
374 : index(65535)
375 {
376 }
377
378public:
379 std::map<int64_t, shared_ptr<Data> > idToDataMap;
380 repo::Index index;
381};
382
383// Combine CommonDatasets with ComplexSelectorDataset
384typedef boost::mpl::push_back<CommonDatasets,
385 ComplexSelectorsDataset>::type Datasets;
386
387BOOST_FIXTURE_TEST_CASE_TEMPLATE(Bulk, T, Datasets, Fixture<T>)
388{
389 BOOST_TEST_MESSAGE(T::getName());
390
391 for (typename T::DataContainer::iterator i = this->data.begin();
392 i != this->data.end(); ++i)
393 {
394 int64_t id = std::abs(static_cast<int64_t>(ndn::random::generateWord64()));
395 this->idToDataMap.insert(std::make_pair(id, *i));
396
397 BOOST_CHECK_EQUAL(this->index.insert(**i, id), true);
398 }
399
400 BOOST_CHECK_EQUAL(this->index.size(), this->data.size());
401
402 for (typename T::InterestContainer::iterator i = this->interests.begin();
403 i != this->interests.end(); ++i)
404 {
405 std::pair<int64_t, Name> item = this->index.find(i->first);
406
407 BOOST_REQUIRE_GT(item.first, 0);
408 BOOST_REQUIRE(this->idToDataMap.count(item.first) > 0);
409
410 BOOST_TEST_MESSAGE(i->first);
411 BOOST_CHECK_EQUAL(*this->idToDataMap[item.first], *i->second);
412
413 BOOST_CHECK_EQUAL(this->index.hasData(*i->second), true);
414 }
415
416 // Need support for selector-based removal
417 // for (typename T::RemovalsContainer::iterator i = this->removals.begin();
418 // i != this->removals.end(); ++i)
419 // {
420 // size_t nRemoved = 0;
421 // BOOST_REQUIRE_NO_THROW(this->index.erase(*i));
422 // BOOST_CHECK_EQUAL(nRemoved, i->seconds);
423 // }
424}
425
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700426BOOST_AUTO_TEST_SUITE_END()
427
428} // namespace tests
429} // namespace repo