blob: a79e2d5dea0ddcfa7dfc46c31a045e38e3ff9742 [file] [log] [blame]
HYuana9b85752014-02-26 02:32:30 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shia6de4292016-07-12 02:08:10 +00003 * Copyright (c) 2014-2016, Regents of the University of California,
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -08004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Alexander Afanasyev28d586a2014-07-10 20:10:54 -070024 */
HYuana9b85752014-02-26 02:32:30 -060025
26#include "table/name-tree.hpp"
Junxiao Shi60607c72014-11-26 22:40:36 -070027#include <unordered_set>
28
Junxiao Shid9ee45c2014-02-27 15:38:11 -070029#include "tests/test-common.hpp"
HYuana9b85752014-02-26 02:32:30 -060030
31namespace nfd {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070032namespace tests {
HYuana9b85752014-02-26 02:32:30 -060033
34using name_tree::Entry;
35
Junxiao Shid9ee45c2014-02-27 15:38:11 -070036BOOST_FIXTURE_TEST_SUITE(TableNameTree, BaseFixture)
HYuana9b85752014-02-26 02:32:30 -060037
Haowei Yuanf52dac72014-03-24 23:35:03 -050038BOOST_AUTO_TEST_CASE(Hash)
39{
40 Name root("/");
41 root.wireEncode();
42 size_t hashValue = name_tree::computeHash(root);
43 BOOST_CHECK_EQUAL(hashValue, static_cast<size_t>(0));
44
45 Name prefix("/nohello/world/ndn/research");
46 prefix.wireEncode();
47 std::vector<size_t> hashSet = name_tree::computeHashSet(prefix);
48 BOOST_CHECK_EQUAL(hashSet.size(), prefix.size() + 1);
49}
50
Junxiao Shid9ee45c2014-02-27 15:38:11 -070051BOOST_AUTO_TEST_CASE(Entry)
HYuana9b85752014-02-26 02:32:30 -060052{
53 Name prefix("ndn:/named-data/research/abc/def/ghi");
54
Junxiao Shiefceadc2014-03-09 18:52:57 -070055 shared_ptr<name_tree::Entry> npe = make_shared<name_tree::Entry>(prefix);
56 BOOST_CHECK_EQUAL(npe->getPrefix(), prefix);
HYuana9b85752014-02-26 02:32:30 -060057
58 // examine all the get methods
59
Haowei Yuanf52dac72014-03-24 23:35:03 -050060 size_t hash = npe->getHash();
61 BOOST_CHECK_EQUAL(hash, static_cast<size_t>(0));
HYuana9b85752014-02-26 02:32:30 -060062
Junxiao Shiefceadc2014-03-09 18:52:57 -070063 shared_ptr<name_tree::Entry> parent = npe->getParent();
HYuana9b85752014-02-26 02:32:30 -060064 BOOST_CHECK(!static_cast<bool>(parent));
65
Junxiao Shiefceadc2014-03-09 18:52:57 -070066 std::vector<shared_ptr<name_tree::Entry> >& childList = npe->getChildren();
Haowei Yuanf52dac72014-03-24 23:35:03 -050067 BOOST_CHECK_EQUAL(childList.size(), static_cast<size_t>(0));
HYuana9b85752014-02-26 02:32:30 -060068
Junxiao Shia6de4292016-07-12 02:08:10 +000069 fib::Entry* fib = npe->getFibEntry();
70 BOOST_CHECK(fib == nullptr);
HYuana9b85752014-02-26 02:32:30 -060071
Junxiao Shi9f7455b2014-04-07 21:02:16 -070072 const std::vector< shared_ptr<pit::Entry> >& pitList = npe->getPitEntries();
Haowei Yuanf52dac72014-03-24 23:35:03 -050073 BOOST_CHECK_EQUAL(pitList.size(), static_cast<size_t>(0));
HYuana9b85752014-02-26 02:32:30 -060074
Haowei Yuane1079fc2014-03-08 14:41:25 -060075 // examine all the set method
HYuana9b85752014-02-26 02:32:30 -060076
Haowei Yuanf52dac72014-03-24 23:35:03 -050077 npe->setHash(static_cast<size_t>(12345));
78 BOOST_CHECK_EQUAL(npe->getHash(), static_cast<size_t>(12345));
HYuana9b85752014-02-26 02:32:30 -060079
80 Name parentName("ndn:/named-data/research/abc/def");
81 parent = make_shared<name_tree::Entry>(parentName);
Junxiao Shiefceadc2014-03-09 18:52:57 -070082 npe->setParent(parent);
83 BOOST_CHECK_EQUAL(npe->getParent(), parent);
HYuana9b85752014-02-26 02:32:30 -060084
Haowei Yuane1079fc2014-03-08 14:41:25 -060085 // Insert FIB
HYuana9b85752014-02-26 02:32:30 -060086
Junxiao Shia6de4292016-07-12 02:08:10 +000087 npe->setFibEntry(make_unique<fib::Entry>(prefix));
88 BOOST_REQUIRE(npe->getFibEntry() != nullptr);
89 BOOST_CHECK_EQUAL(npe->getFibEntry()->getPrefix(), prefix);
Haowei Yuane1079fc2014-03-08 14:41:25 -060090
Junxiao Shia6de4292016-07-12 02:08:10 +000091 npe->setFibEntry(nullptr);
92 BOOST_CHECK(npe->getFibEntry() == nullptr);
HYuana9b85752014-02-26 02:32:30 -060093
94 // Insert a PIT
95
Alexander Afanasyev28d586a2014-07-10 20:10:54 -070096 shared_ptr<pit::Entry> pitEntry(make_shared<pit::Entry>(*makeInterest(prefix)));
97 shared_ptr<pit::Entry> pitEntry2(make_shared<pit::Entry>(*makeInterest(parentName)));
HYuana9b85752014-02-26 02:32:30 -060098
Alexander Afanasyev28d586a2014-07-10 20:10:54 -070099 npe->insertPitEntry(pitEntry);
Junxiao Shiefceadc2014-03-09 18:52:57 -0700100 BOOST_CHECK_EQUAL(npe->getPitEntries().size(), 1);
HYuana9b85752014-02-26 02:32:30 -0600101
Alexander Afanasyev28d586a2014-07-10 20:10:54 -0700102 npe->insertPitEntry(pitEntry2);
Junxiao Shiefceadc2014-03-09 18:52:57 -0700103 BOOST_CHECK_EQUAL(npe->getPitEntries().size(), 2);
HYuana9b85752014-02-26 02:32:30 -0600104
Alexander Afanasyev28d586a2014-07-10 20:10:54 -0700105 npe->erasePitEntry(pitEntry);
Junxiao Shiefceadc2014-03-09 18:52:57 -0700106 BOOST_CHECK_EQUAL(npe->getPitEntries().size(), 1);
HYuana9b85752014-02-26 02:32:30 -0600107
Alexander Afanasyev28d586a2014-07-10 20:10:54 -0700108 npe->erasePitEntry(pitEntry2);
Junxiao Shiefceadc2014-03-09 18:52:57 -0700109 BOOST_CHECK_EQUAL(npe->getPitEntries().size(), 0);
HYuana9b85752014-02-26 02:32:30 -0600110}
111
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700112BOOST_AUTO_TEST_CASE(Basic)
HYuana9b85752014-02-26 02:32:30 -0600113{
114 size_t nBuckets = 16;
115 NameTree nt(nBuckets);
116
117 BOOST_CHECK_EQUAL(nt.size(), 0);
Haowei Yuane1079fc2014-03-08 14:41:25 -0600118 BOOST_CHECK_EQUAL(nt.getNBuckets(), nBuckets);
HYuana9b85752014-02-26 02:32:30 -0600119
Haowei Yuane1079fc2014-03-08 14:41:25 -0600120 Name nameABC("ndn:/a/b/c");
HYuana9b85752014-02-26 02:32:30 -0600121 shared_ptr<name_tree::Entry> npeABC = nt.lookup(nameABC);
122 BOOST_CHECK_EQUAL(nt.size(), 4);
Haowei Yuane1079fc2014-03-08 14:41:25 -0600123
124 Name nameABD("/a/b/d");
HYuana9b85752014-02-26 02:32:30 -0600125 shared_ptr<name_tree::Entry> npeABD = nt.lookup(nameABD);
126 BOOST_CHECK_EQUAL(nt.size(), 5);
127
Haowei Yuane1079fc2014-03-08 14:41:25 -0600128 Name nameAE("/a/e/");
HYuana9b85752014-02-26 02:32:30 -0600129 shared_ptr<name_tree::Entry> npeAE = nt.lookup(nameAE);
130 BOOST_CHECK_EQUAL(nt.size(), 6);
131
Haowei Yuane1079fc2014-03-08 14:41:25 -0600132 Name nameF("/f");
HYuana9b85752014-02-26 02:32:30 -0600133 shared_ptr<name_tree::Entry> npeF = nt.lookup(nameF);
134 BOOST_CHECK_EQUAL(nt.size(), 7);
135
Haowei Yuane1079fc2014-03-08 14:41:25 -0600136 // validate lookup() and findExactMatch()
HYuana9b85752014-02-26 02:32:30 -0600137
138 Name nameAB ("/a/b");
139 BOOST_CHECK_EQUAL(npeABC->getParent(), nt.findExactMatch(nameAB));
140 BOOST_CHECK_EQUAL(npeABD->getParent(), nt.findExactMatch(nameAB));
141
142 Name nameA ("/a");
143 BOOST_CHECK_EQUAL(npeAE->getParent(), nt.findExactMatch(nameA));
144
145 Name nameRoot ("/");
146 BOOST_CHECK_EQUAL(npeF->getParent(), nt.findExactMatch(nameRoot));
147 BOOST_CHECK_EQUAL(nt.size(), 7);
148
Haowei Yuane1079fc2014-03-08 14:41:25 -0600149 Name name0("/does/not/exist");
HYuana9b85752014-02-26 02:32:30 -0600150 shared_ptr<name_tree::Entry> npe0 = nt.findExactMatch(name0);
151 BOOST_CHECK(!static_cast<bool>(npe0));
152
153
154 // Longest Prefix Matching
HYuana9b85752014-02-26 02:32:30 -0600155 shared_ptr<name_tree::Entry> temp;
156 Name nameABCLPM("/a/b/c/def/asdf/nlf");
157 temp = nt.findLongestPrefixMatch(nameABCLPM);
158 BOOST_CHECK_EQUAL(temp, nt.findExactMatch(nameABC));
159
160 Name nameABDLPM("/a/b/d/def/asdf/nlf");
161 temp = nt.findLongestPrefixMatch(nameABDLPM);
162 BOOST_CHECK_EQUAL(temp, nt.findExactMatch(nameABD));
163
164 Name nameABLPM("/a/b/hello/world");
165 temp = nt.findLongestPrefixMatch(nameABLPM);
166 BOOST_CHECK_EQUAL(temp, nt.findExactMatch(nameAB));
167
168 Name nameAELPM("/a/e/hello/world");
169 temp = nt.findLongestPrefixMatch(nameAELPM);
170 BOOST_CHECK_EQUAL(temp, nt.findExactMatch(nameAE));
171
172 Name nameALPM("/a/hello/world");
173 temp = nt.findLongestPrefixMatch(nameALPM);
174 BOOST_CHECK_EQUAL(temp, nt.findExactMatch(nameA));
175
176 Name nameFLPM("/f/hello/world");
177 temp = nt.findLongestPrefixMatch(nameFLPM);
178 BOOST_CHECK_EQUAL(temp, nt.findExactMatch(nameF));
179
180 Name nameRootLPM("/does_not_exist");
181 temp = nt.findLongestPrefixMatch(nameRootLPM);
182 BOOST_CHECK_EQUAL(temp, nt.findExactMatch(nameRoot));
183
HYuana9b85752014-02-26 02:32:30 -0600184 bool eraseResult = false;
185 temp = nt.findExactMatch(nameABC);
186 if (static_cast<bool>(temp))
187 eraseResult = nt.
188 eraseEntryIfEmpty(temp);
189 BOOST_CHECK_EQUAL(nt.size(), 6);
190 BOOST_CHECK(!static_cast<bool>(nt.findExactMatch(nameABC)));
191 BOOST_CHECK_EQUAL(eraseResult, true);
192
193 eraseResult = false;
194 temp = nt.findExactMatch(nameABCLPM);
Haowei Yuane1079fc2014-03-08 14:41:25 -0600195 if (static_cast<bool>(temp))
HYuana9b85752014-02-26 02:32:30 -0600196 eraseResult = nt.
197 eraseEntryIfEmpty(temp);
198 BOOST_CHECK(!static_cast<bool>(temp));
199 BOOST_CHECK_EQUAL(nt.size(), 6);
200 BOOST_CHECK_EQUAL(eraseResult, false);
201
202 // nt.dump(std::cout);
203
204 nt.lookup(nameABC);
205 BOOST_CHECK_EQUAL(nt.size(), 7);
206
207 eraseResult = false;
208 temp = nt.findExactMatch(nameABC);
Haowei Yuane1079fc2014-03-08 14:41:25 -0600209 if (static_cast<bool>(temp))
HYuana9b85752014-02-26 02:32:30 -0600210 eraseResult = nt.
211 eraseEntryIfEmpty(temp);
212 BOOST_CHECK_EQUAL(nt.size(), 6);
213 BOOST_CHECK_EQUAL(eraseResult, true);
214 BOOST_CHECK(!static_cast<bool>(nt.findExactMatch(nameABC)));
215
HYuana9b85752014-02-26 02:32:30 -0600216 BOOST_CHECK_EQUAL(nt.getNBuckets(), 16);
217
Haowei Yuane1079fc2014-03-08 14:41:25 -0600218 // should resize now
HYuana9b85752014-02-26 02:32:30 -0600219 Name nameABCD("a/b/c/d");
220 nt.lookup(nameABCD);
221 Name nameABCDE("a/b/c/d/e");
222 nt.lookup(nameABCDE);
223 BOOST_CHECK_EQUAL(nt.size(), 9);
224 BOOST_CHECK_EQUAL(nt.getNBuckets(), 32);
225
Haowei Yuane1079fc2014-03-08 14:41:25 -0600226 // try to erase /a/b/c, should return false
HYuana9b85752014-02-26 02:32:30 -0600227 temp = nt.findExactMatch(nameABC);
228 BOOST_CHECK_EQUAL(temp->getPrefix(), nameABC);
229 eraseResult = nt.
230 eraseEntryIfEmpty(temp);
231 BOOST_CHECK_EQUAL(eraseResult, false);
232 temp = nt.findExactMatch(nameABC);
233 BOOST_CHECK_EQUAL(temp->getPrefix(), nameABC);
234
235 temp = nt.findExactMatch(nameABD);
Haowei Yuane1079fc2014-03-08 14:41:25 -0600236 if (static_cast<bool>(temp))
HYuana9b85752014-02-26 02:32:30 -0600237 nt.
238 eraseEntryIfEmpty(temp);
239 BOOST_CHECK_EQUAL(nt.size(), 8);
Haowei Yuane1079fc2014-03-08 14:41:25 -0600240}
HYuana9b85752014-02-26 02:32:30 -0600241
Junxiao Shi60607c72014-11-26 22:40:36 -0700242/** \brief verify a NameTree enumeration contains expected entries
243 *
244 * Example:
245 * \code{.cpp}
246 * auto& enumerable = ...;
247 * EnumerationVerifier(enumerable)
248 * .expect("/A")
249 * .expect("/B")
250 * .end();
251 * // enumerable must have /A /B and nothing else to pass the test.
252 * \endcode
253 */
254class EnumerationVerifier : noncopyable
Haowei Yuane1079fc2014-03-08 14:41:25 -0600255{
Junxiao Shi60607c72014-11-26 22:40:36 -0700256public:
257 template<typename Enumerable>
258 EnumerationVerifier(Enumerable&& enumerable)
259 {
260 for (const name_tree::Entry& entry : enumerable) {
261 const Name& name = entry.getPrefix();
262 BOOST_CHECK_MESSAGE(m_names.insert(name).second, "duplicate Name " << name);
263 }
264 }
HYuana9b85752014-02-26 02:32:30 -0600265
Junxiao Shi60607c72014-11-26 22:40:36 -0700266 EnumerationVerifier&
267 expect(const Name& name)
268 {
269 BOOST_CHECK_MESSAGE(m_names.erase(name) == 1, "missing Name " << name);
270 return *this;
271 }
Haowei Yuane1079fc2014-03-08 14:41:25 -0600272
Junxiao Shi60607c72014-11-26 22:40:36 -0700273 void
274 end()
275 {
Alexander Afanasyeve84044e2015-02-26 21:52:18 -0800276 BOOST_CHECK(m_names.empty());
Junxiao Shi60607c72014-11-26 22:40:36 -0700277 }
278
279private:
280 std::unordered_set<Name> m_names;
281};
282
283class EnumerationFixture : public BaseFixture
284{
285protected:
286 EnumerationFixture()
287 : nt(N_BUCKETS)
288 {
289 BOOST_CHECK_EQUAL(nt.size(), 0);
290 BOOST_CHECK_EQUAL(nt.getNBuckets(), N_BUCKETS);
291 }
292
293 void
294 insertAbAc()
295 {
296 nt.lookup("/a/b");
297 nt.lookup("/a/c");
298 BOOST_CHECK_EQUAL(nt.size(), 4);
299 // /, /a, /a/b, /a/c
300 }
301
302 void
303 insertAb1Ab2Ac1Ac2()
304 {
305 nt.lookup("/a/b/1");
306 nt.lookup("/a/b/2");
307 nt.lookup("/a/c/1");
308 nt.lookup("/a/c/2");
309 BOOST_CHECK_EQUAL(nt.size(), 8);
310 // /, /a, /a/b, /a/b/1, /a/b/2, /a/c, /a/c/1, /a/c/2
311 }
312
313protected:
314 static const size_t N_BUCKETS = 16;
315 NameTree nt;
316};
317const size_t EnumerationFixture::N_BUCKETS;
318
319BOOST_FIXTURE_TEST_CASE(IteratorFullEnumerate, EnumerationFixture)
320{
321 nt.lookup("/a/b/c");
Haowei Yuane1079fc2014-03-08 14:41:25 -0600322 BOOST_CHECK_EQUAL(nt.size(), 4);
323
Junxiao Shi60607c72014-11-26 22:40:36 -0700324 nt.lookup("/a/b/d");
Haowei Yuane1079fc2014-03-08 14:41:25 -0600325 BOOST_CHECK_EQUAL(nt.size(), 5);
326
Junxiao Shi60607c72014-11-26 22:40:36 -0700327 nt.lookup("/a/e");
Haowei Yuane1079fc2014-03-08 14:41:25 -0600328 BOOST_CHECK_EQUAL(nt.size(), 6);
329
Junxiao Shi60607c72014-11-26 22:40:36 -0700330 nt.lookup("/f");
Haowei Yuane1079fc2014-03-08 14:41:25 -0600331 BOOST_CHECK_EQUAL(nt.size(), 7);
332
Junxiao Shi60607c72014-11-26 22:40:36 -0700333 nt.lookup("/");
Haowei Yuane1079fc2014-03-08 14:41:25 -0600334 BOOST_CHECK_EQUAL(nt.size(), 7);
335
Junxiao Shi60607c72014-11-26 22:40:36 -0700336 auto&& enumerable = nt.fullEnumerate();
337 EnumerationVerifier(enumerable)
338 .expect("/")
339 .expect("/a")
340 .expect("/a/b")
341 .expect("/a/b/c")
342 .expect("/a/b/d")
343 .expect("/a/e")
344 .expect("/f")
345 .end();
Haowei Yuane1079fc2014-03-08 14:41:25 -0600346}
347
Junxiao Shi60607c72014-11-26 22:40:36 -0700348BOOST_FIXTURE_TEST_SUITE(IteratorPartialEnumerate, EnumerationFixture)
Haowei Yuane1079fc2014-03-08 14:41:25 -0600349
Junxiao Shi60607c72014-11-26 22:40:36 -0700350BOOST_AUTO_TEST_CASE(Empty)
Haowei Yuane1079fc2014-03-08 14:41:25 -0600351{
Junxiao Shi60607c72014-11-26 22:40:36 -0700352 auto&& enumerable = nt.partialEnumerate("/a");
353
354 EnumerationVerifier(enumerable)
355 .end();
Haowei Yuane1079fc2014-03-08 14:41:25 -0600356}
357
Junxiao Shi60607c72014-11-26 22:40:36 -0700358BOOST_AUTO_TEST_CASE(NotIn)
Haowei Yuane1079fc2014-03-08 14:41:25 -0600359{
Junxiao Shi60607c72014-11-26 22:40:36 -0700360 this->insertAbAc();
Haowei Yuane1079fc2014-03-08 14:41:25 -0600361
362 // Enumerate on some name that is not in nameTree
Junxiao Shi60607c72014-11-26 22:40:36 -0700363 Name name0("/0");
364 auto&& enumerable = nt.partialEnumerate("/0");
365
366 EnumerationVerifier(enumerable)
367 .end();
368}
369
370BOOST_AUTO_TEST_CASE(OnlyA)
371{
372 this->insertAbAc();
Haowei Yuane1079fc2014-03-08 14:41:25 -0600373
374 // Accept "root" nameA only
Junxiao Shi60607c72014-11-26 22:40:36 -0700375 auto&& enumerable = nt.partialEnumerate("/a", [] (const name_tree::Entry& entry) {
376 return std::make_pair(entry.getPrefix() == "/a", true);
377 });
378
379 EnumerationVerifier(enumerable)
380 .expect("/a")
381 .end();
382}
383
384BOOST_AUTO_TEST_CASE(ExceptA)
385{
386 this->insertAbAc();
Haowei Yuane1079fc2014-03-08 14:41:25 -0600387
388 // Accept anything except "root" nameA
Junxiao Shi60607c72014-11-26 22:40:36 -0700389 auto&& enumerable = nt.partialEnumerate("/a", [] (const name_tree::Entry& entry) {
390 return std::make_pair(entry.getPrefix() != "/a", true);
391 });
Haowei Yuane1079fc2014-03-08 14:41:25 -0600392
Junxiao Shi60607c72014-11-26 22:40:36 -0700393 EnumerationVerifier(enumerable)
394 .expect("/a/b")
395 .expect("/a/c")
396 .end();
397}
Haowei Yuane1079fc2014-03-08 14:41:25 -0600398
Junxiao Shi60607c72014-11-26 22:40:36 -0700399BOOST_AUTO_TEST_CASE(NoNameANoSubTreeAB)
400{
401 this->insertAb1Ab2Ac1Ac2();
Haowei Yuane1079fc2014-03-08 14:41:25 -0600402
403 // No NameA
404 // No SubTree from NameAB
Junxiao Shi60607c72014-11-26 22:40:36 -0700405 auto&& enumerable = nt.partialEnumerate("/a", [] (const name_tree::Entry& entry) {
406 return std::make_pair(entry.getPrefix() != "/a", entry.getPrefix() != "/a/b");
407 });
Haowei Yuane1079fc2014-03-08 14:41:25 -0600408
Junxiao Shi60607c72014-11-26 22:40:36 -0700409 EnumerationVerifier(enumerable)
410 .expect("/a/b")
411 .expect("/a/c")
412 .expect("/a/c/1")
413 .expect("/a/c/2")
414 .end();
415}
Haowei Yuane1079fc2014-03-08 14:41:25 -0600416
Junxiao Shi60607c72014-11-26 22:40:36 -0700417BOOST_AUTO_TEST_CASE(NoNameANoSubTreeAC)
418{
419 this->insertAb1Ab2Ac1Ac2();
Haowei Yuane1079fc2014-03-08 14:41:25 -0600420
421 // No NameA
422 // No SubTree from NameAC
Junxiao Shi60607c72014-11-26 22:40:36 -0700423 auto&& enumerable = nt.partialEnumerate("/a", [] (const name_tree::Entry& entry) {
424 return std::make_pair(entry.getPrefix() != "/a", entry.getPrefix() != "/a/c");
425 });
Haowei Yuane1079fc2014-03-08 14:41:25 -0600426
Junxiao Shi60607c72014-11-26 22:40:36 -0700427 EnumerationVerifier(enumerable)
428 .expect("/a/b")
429 .expect("/a/b/1")
430 .expect("/a/b/2")
431 .expect("/a/c")
432 .end();
433}
Haowei Yuane1079fc2014-03-08 14:41:25 -0600434
Junxiao Shi60607c72014-11-26 22:40:36 -0700435BOOST_AUTO_TEST_CASE(NoSubTreeA)
436{
437 this->insertAb1Ab2Ac1Ac2();
Haowei Yuane1079fc2014-03-08 14:41:25 -0600438
439 // No Subtree from NameA
Junxiao Shi60607c72014-11-26 22:40:36 -0700440 auto&& enumerable = nt.partialEnumerate("/a", [] (const name_tree::Entry& entry) {
441 return std::make_pair(true, entry.getPrefix() != "/a");
442 });
Haowei Yuane1079fc2014-03-08 14:41:25 -0600443
Junxiao Shi60607c72014-11-26 22:40:36 -0700444 EnumerationVerifier(enumerable)
445 .expect("/a")
446 .end();
447}
Haowei Yuane1079fc2014-03-08 14:41:25 -0600448
Junxiao Shi60607c72014-11-26 22:40:36 -0700449BOOST_AUTO_TEST_CASE(Example)
450{
Haowei Yuane1079fc2014-03-08 14:41:25 -0600451 // Example
452 // /
453 // /A
454 // /A/B x
455 // /A/B/C
456 // /A/D x
457 // /E
458 // /F
459
Junxiao Shi60607c72014-11-26 22:40:36 -0700460 nt.lookup("/A");
461 nt.lookup("/A/B");
462 nt.lookup("/A/B/C");
463 nt.lookup("/A/D");
464 nt.lookup("/E");
465 nt.lookup("/F");
Haowei Yuane1079fc2014-03-08 14:41:25 -0600466
Junxiao Shi60607c72014-11-26 22:40:36 -0700467 auto&& enumerable = nt.partialEnumerate("/A",
468 [] (const name_tree::Entry& entry) -> std::pair<bool, bool> {
469 bool visitEntry = false;
470 bool visitChildren = false;
Haowei Yuane1079fc2014-03-08 14:41:25 -0600471
Junxiao Shi60607c72014-11-26 22:40:36 -0700472 Name name = entry.getPrefix();
Haowei Yuane1079fc2014-03-08 14:41:25 -0600473
Junxiao Shi60607c72014-11-26 22:40:36 -0700474 if (name == "/" || name == "/A/B" || name == "/A/B/C" || name == "/A/D") {
475 visitEntry = true;
476 }
Haowei Yuane1079fc2014-03-08 14:41:25 -0600477
Junxiao Shi60607c72014-11-26 22:40:36 -0700478 if (name == "/" || name == "/A" || name == "/F") {
479 visitChildren = true;
480 }
Haowei Yuane1079fc2014-03-08 14:41:25 -0600481
Junxiao Shi60607c72014-11-26 22:40:36 -0700482 return {visitEntry, visitChildren};
483 });
Haowei Yuane1079fc2014-03-08 14:41:25 -0600484
Junxiao Shi60607c72014-11-26 22:40:36 -0700485 EnumerationVerifier(enumerable)
486 .expect("/A/B")
487 .expect("/A/D")
488 .end();
Haowei Yuane1079fc2014-03-08 14:41:25 -0600489}
490
Junxiao Shi60607c72014-11-26 22:40:36 -0700491BOOST_AUTO_TEST_SUITE_END()
Haowei Yuane1079fc2014-03-08 14:41:25 -0600492
Junxiao Shi60607c72014-11-26 22:40:36 -0700493BOOST_FIXTURE_TEST_CASE(IteratorFindAllMatches, EnumerationFixture)
Haowei Yuane1079fc2014-03-08 14:41:25 -0600494{
Junxiao Shi60607c72014-11-26 22:40:36 -0700495 nt.lookup("/a/b/c/d/e/f");
496 nt.lookup("/a/a/c");
497 nt.lookup("/a/a/d/1");
498 nt.lookup("/a/a/d/2");
Haowei Yuane1079fc2014-03-08 14:41:25 -0600499 BOOST_CHECK_EQUAL(nt.size(), 12);
500
Junxiao Shi60607c72014-11-26 22:40:36 -0700501 auto&& allMatches = nt.findAllMatches("/a/b/c/d/e");
Haowei Yuane1079fc2014-03-08 14:41:25 -0600502
Junxiao Shi60607c72014-11-26 22:40:36 -0700503 EnumerationVerifier(allMatches)
504 .expect("/")
505 .expect("/a")
506 .expect("/a/b")
507 .expect("/a/b/c")
508 .expect("/a/b/c/d")
509 .expect("/a/b/c/d/e")
510 .end();
HYuana9b85752014-02-26 02:32:30 -0600511}
512
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700513BOOST_AUTO_TEST_CASE(HashTableResizeShrink)
Haowei Yuanf52dac72014-03-24 23:35:03 -0500514{
515 size_t nBuckets = 16;
516 NameTree nameTree(nBuckets);
517
518 Name prefix("/a/b/c/d/e/f/g/h"); // requires 9 buckets
519
520 shared_ptr<name_tree::Entry> entry = nameTree.lookup(prefix);
521 BOOST_CHECK_EQUAL(nameTree.size(), 9);
522 BOOST_CHECK_EQUAL(nameTree.getNBuckets(), 32);
523
524 nameTree.eraseEntryIfEmpty(entry);
525 BOOST_CHECK_EQUAL(nameTree.size(), 0);
526 BOOST_CHECK_EQUAL(nameTree.getNBuckets(), 16);
527}
528
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700529// .lookup should not invalidate iterator
530BOOST_AUTO_TEST_CASE(SurvivedIteratorAfterLookup)
531{
532 NameTree nt;
533 nt.lookup("/A/B/C");
534 nt.lookup("/E");
535
536 Name nameB("/A/B");
537 std::set<Name> seenNames;
538 for (NameTree::const_iterator it = nt.begin(); it != nt.end(); ++it) {
539 BOOST_CHECK(seenNames.insert(it->getPrefix()).second);
540 if (it->getPrefix() == nameB) {
541 nt.lookup("/D");
542 }
543 }
544
545 BOOST_CHECK_EQUAL(seenNames.count("/"), 1);
546 BOOST_CHECK_EQUAL(seenNames.count("/A"), 1);
547 BOOST_CHECK_EQUAL(seenNames.count("/A/B"), 1);
548 BOOST_CHECK_EQUAL(seenNames.count("/A/B/C"), 1);
549 BOOST_CHECK_EQUAL(seenNames.count("/E"), 1);
550
551 seenNames.erase("/D"); // /D may or may not appear
552 BOOST_CHECK(seenNames.size() == 5);
553}
554
555// .eraseEntryIfEmpty should not invalidate iterator
556BOOST_AUTO_TEST_CASE(SurvivedIteratorAfterErase)
557{
558 NameTree nt;
559 nt.lookup("/A/B/C");
560 nt.lookup("/A/D/E");
561 nt.lookup("/A/F/G");
562 nt.lookup("/H");
563
564 Name nameD("/A/D");
565 std::set<Name> seenNames;
566 for (NameTree::const_iterator it = nt.begin(); it != nt.end(); ++it) {
567 BOOST_CHECK(seenNames.insert(it->getPrefix()).second);
568 if (it->getPrefix() == nameD) {
569 nt.eraseEntryIfEmpty(nt.findExactMatch("/A/F/G")); // /A/F/G and /A/F are erased
570 }
571 }
572
573 BOOST_CHECK_EQUAL(seenNames.count("/"), 1);
574 BOOST_CHECK_EQUAL(seenNames.count("/A"), 1);
575 BOOST_CHECK_EQUAL(seenNames.count("/A/B"), 1);
576 BOOST_CHECK_EQUAL(seenNames.count("/A/B/C"), 1);
577 BOOST_CHECK_EQUAL(seenNames.count("/A/D"), 1);
578 BOOST_CHECK_EQUAL(seenNames.count("/A/D/E"), 1);
579 BOOST_CHECK_EQUAL(seenNames.count("/H"), 1);
580
581 seenNames.erase("/A/F"); // /A/F may or may not appear
582 seenNames.erase("/A/F/G"); // /A/F/G may or may not appear
583 BOOST_CHECK(seenNames.size() == 7);
584}
585
HYuana9b85752014-02-26 02:32:30 -0600586BOOST_AUTO_TEST_SUITE_END()
587
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700588} // namespace tests
HYuana9b85752014-02-26 02:32:30 -0600589} // namespace nfd