blob: 5bbb0ff2d296cdc3bb88d2be490ed2347d56c894 [file] [log] [blame]
Shuo Chen9a43f162014-07-01 13:43:54 +08001/* -*- 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/skiplist.hpp"
21
22#include "../sqlite-fixture.hpp"
23#include "../dataset-fixtures.hpp"
24
25#include <boost/test/unit_test.hpp>
26#include <boost/concept_check.hpp>
27#include <iostream>
28
29namespace repo {
30namespace tests {
31
32BOOST_AUTO_TEST_SUITE(SkipList)
33
34template<class Dataset>
35class Fixture : public Dataset
36{
37};
38
Alexander Afanasyevb7e8a812014-07-23 01:36:47 -070039BOOST_AUTO_TEST_CASE(Correctness)
Shuo Chen9a43f162014-07-01 13:43:54 +080040{
41 typedef repo::SkipList<int, std::greater<int> > IntGtSkipList;
42 IntGtSkipList sl;
43 BOOST_CONCEPT_ASSERT((boost::BidirectionalIterator<IntGtSkipList::iterator>));
44
45 // initial state
46 BOOST_CHECK_EQUAL(sl.size(), 0);
47 BOOST_CHECK(sl.begin() == sl.end());
48 BOOST_CHECK(sl.lower_bound(10) == sl.end());
49
50 // initial contents
51 sl.insert(10);
52 sl.insert(20);
53 sl.insert(30);
54 BOOST_CHECK_EQUAL(sl.size(), 3);
55 // contents: [30,20,10]
56
57 // iterators
58 IntGtSkipList::iterator it1 = sl.begin();
59 IntGtSkipList::iterator it2 = sl.end();
60 --it2;
61 BOOST_CHECK_EQUAL(*it1, 30);
62 BOOST_CHECK_EQUAL(*it2, 10);
63 ++it1;
64 BOOST_CHECK_EQUAL(*it1, 20);
65 IntGtSkipList::iterator it3 = it1;
66 ++it1;
67 BOOST_CHECK(it2 == it1);
68 BOOST_CHECK_EQUAL(*it3, 20);
69
70 // lower_bound
71 IntGtSkipList::iterator found = sl.lower_bound(35);
72 BOOST_CHECK(found == sl.begin());
73 BOOST_CHECK_EQUAL(*found, 30);
74 found = sl.lower_bound(30);
75 BOOST_CHECK_EQUAL(*found, 30);
76 found = sl.lower_bound(25);
77 BOOST_CHECK_EQUAL(*found, 20);
78 found = sl.lower_bound(20);
79 BOOST_CHECK_EQUAL(*found, 20);
80 found = sl.lower_bound(15);
81 BOOST_CHECK_EQUAL(*found, 10);
82 found = sl.lower_bound(10);
83 BOOST_CHECK_EQUAL(*found, 10);
84 found = sl.lower_bound(5);
85 BOOST_CHECK(found == sl.end());
86
87 // insert duplicate
88 std::pair<IntGtSkipList::iterator, bool> insertRes = sl.insert(10);
89 BOOST_CHECK_EQUAL(insertRes.second, false);
90 BOOST_CHECK_EQUAL(*(insertRes.first), 10);
91 BOOST_CHECK_EQUAL(sl.size(), 3);
92 insertRes = sl.insert(20);
93 BOOST_CHECK_EQUAL(insertRes.second, false);
94 BOOST_CHECK_EQUAL(*(insertRes.first), 20);
95 BOOST_CHECK_EQUAL(sl.size(), 3);
96 insertRes = sl.insert(30);
97 BOOST_CHECK_EQUAL(insertRes.second, false);
98 BOOST_CHECK_EQUAL(*(insertRes.first), 30);
99 BOOST_CHECK_EQUAL(sl.size(), 3);
100
101 // insert non-duplicate
102 insertRes = sl.insert(5);
103 BOOST_CHECK_EQUAL(insertRes.second, true);
104 BOOST_CHECK_EQUAL(*(insertRes.first), 5);
105 BOOST_CHECK_EQUAL(sl.size(), 4);
106 insertRes = sl.insert(35);
107 BOOST_CHECK_EQUAL(insertRes.second, true);
108 BOOST_CHECK_EQUAL(*(insertRes.first), 35);
109 BOOST_CHECK_EQUAL(sl.size(), 5);
110 // contents: [35,30,20,10,5]
111
112 // erase
113 it1 = sl.erase(sl.begin());
114 // contents: [30,20,10,5]
115 BOOST_CHECK_EQUAL(*it1, 30);
116 BOOST_CHECK_EQUAL(sl.size(), 4);
117 it2 = sl.end();
118 --it2;
119 it1 = sl.erase(it2);
120 // contents: [30,20,10]
121 BOOST_CHECK(it1 == sl.end());
122 BOOST_CHECK_EQUAL(sl.size(), 3);
123 it2 = sl.lower_bound(20);
124 it1 = sl.erase(it2);
125 // contents: [30,10]
126 BOOST_CHECK_EQUAL(*it1, 10);
127 BOOST_CHECK_EQUAL(sl.size(), 2);
128 it3 = it1;
129 --it1;
130 BOOST_CHECK(it1 == sl.begin());
131 BOOST_CHECK_EQUAL(*it1, 30);
132 ++it3;
133 BOOST_CHECK(it3 == sl.end());
134}
135
Alexander Afanasyevb7e8a812014-07-23 01:36:47 -0700136class Item : public ndn::Name
137{
138public:
139 explicit
140 Item(const ndn::Name& name = "")
141 : ndn::Name(name)
142 , randomValue(ndn::random::generateWord64())
143 {
144 }
145
146public:
147 uint64_t randomValue;
148};
149
150BOOST_FIXTURE_TEST_CASE_TEMPLATE(Bulk, T, CommonDatasets, Fixture<T>)
151{
152 BOOST_TEST_MESSAGE(T::getName());
153 typedef repo::SkipList<Item, std::less<Item> > SkipList;
154 SkipList skipList;
155
156 std::vector<Item> items;
157 std::set<ndn::Name> names;
158 for (typename T::DataContainer::iterator i = this->data.begin();
159 i != this->data.end(); ++i) {
160 std::pair<std::set<ndn::Name>::iterator, bool> ret = names.insert((*i)->getName());
161 if (ret.second) {
162 items.push_back(Item((*i)->getName()));
163 }
164 }
165
166 // Insert
167 for (std::vector<Item>::iterator i = items.begin(); i != items.end(); ++i) {
168 skipList.insert(*i);
169 }
170
171 BOOST_CHECK_EQUAL(items.size(), skipList.size());
172
173 // Randomize items
174 std::random_shuffle(items.begin(), items.end());
175
176 // Find items and check if the right item is found
177 for (std::vector<Item>::iterator i = items.begin(); i != items.end(); ++i) {
178 SkipList::iterator item = skipList.find(*i);
179 BOOST_CHECK(item != skipList.end());
180
181 BOOST_CHECK_EQUAL(static_cast<const Name&>(*item), static_cast<const Name&>(*i));
182 BOOST_CHECK_EQUAL(item->randomValue, i->randomValue);
183 }
184}
185
Shuo Chen9a43f162014-07-01 13:43:54 +0800186BOOST_AUTO_TEST_SUITE_END()
187
188} // namespace tests
189} // namespace repo