1 // Copyright 2014, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright notice,
10 // this list of conditions and the following disclaimer in the documentation
11 // and/or other materials provided with the distribution.
12 // * Neither the name of ARM Limited nor the names of its contributors may be
13 // used to endorse or promote products derived from this software without
14 // specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 #include "invalset-vixl.h"
28 #include "test-runner.h"
29
30 namespace vixl {
31
32 // This file contains tests for the `InvalSet` and `InvalSetIterator` classes.
33
34 #define TEST(name) TEST_(INVALSET_##name)
35
36 typedef ptrdiff_t KeyType;
37 typedef ptrdiff_t ValType;
38
39 // We test with an object for which the key and the value are distinct.
40 class Obj {
41 public:
Obj()42 Obj() {}
Obj(KeyType key,ValType val)43 Obj(KeyType key, ValType val) : key_(key), val_(val) {}
44 KeyType key_;
45 ValType val_;
46
operator ==(const Obj & other) const47 bool operator==(const Obj& other) const {
48 return (key_ == other.key_) && (val_ == other.val_);
49 }
operator <(const Obj & other) const50 bool operator<(const Obj& other) const {
51 return (key_ < other.key_) || ((key_ == other.key_) && (val_ < other.val_));
52 }
operator <=(const Obj & other) const53 bool operator<=(const Obj& other) const {
54 return (key_ <= other.key_) ||
55 ((key_ == other.key_) && (val_ <= other.val_));
56 }
operator >(const Obj & other) const57 bool operator>(const Obj& other) const {
58 return (key_ > other.key_) || ((key_ == other.key_) && (val_ > other.val_));
59 }
60 };
61
62 static const unsigned kNPreallocatedElements = 8;
63 static const KeyType kInvalidKey = PTRDIFF_MAX;
64 static const size_t kReclaimFrom = 1000;
65 static const unsigned kReclaimFactor = 10;
66
67 typedef InvalSet<Obj,
68 kNPreallocatedElements,
69 KeyType,
70 kInvalidKey,
71 kReclaimFrom,
72 kReclaimFactor>
73 TestSet;
74
75 template <>
76 inline KeyType InvalSet<Obj,
77 kNPreallocatedElements,
78 KeyType,
79 kInvalidKey,
80 kReclaimFrom,
GetKey(const Obj & obj)81 kReclaimFactor>::GetKey(const Obj& obj) {
82 return obj.key_;
83 }
84 template <>
85 inline void InvalSet<Obj,
86 kNPreallocatedElements,
87 KeyType,
88 kInvalidKey,
89 kReclaimFrom,
SetKey(Obj * obj,KeyType key)90 kReclaimFactor>::SetKey(Obj* obj, KeyType key) {
91 obj->key_ = key;
92 }
93
94
TEST(basic_test)95 TEST(basic_test) {
96 TestSet set;
97 VIXL_CHECK(set.empty() && (set.size() == 0));
98
99 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
100 set.insert(Obj(i, i));
101 }
102 VIXL_CHECK(set.size() == kNPreallocatedElements);
103
104 set.insert(Obj(-123, 456));
105 set.insert(Obj(2718, 2871828));
106 VIXL_CHECK(set.size() == kNPreallocatedElements + 2);
107 VIXL_CHECK(set.GetMinElement() == Obj(-123, 456));
108
109 set.erase(Obj(-123, 456));
110 VIXL_CHECK(set.GetMinElementKey() == 0);
111
112 set.clear();
113 VIXL_CHECK(set.empty() && (set.size() == 0));
114 }
115
116
TEST(valid_element)117 TEST(valid_element) {
118 VIXL_CHECK(TestSet::IsValid(Obj(0, 0)));
119 VIXL_CHECK(TestSet::IsValid(Obj(-1, 0)));
120 VIXL_CHECK(TestSet::IsValid(Obj(kInvalidKey - 1, 0)));
121 VIXL_CHECK(!TestSet::IsValid(Obj(kInvalidKey, 0)));
122 }
123
124
TEST(insert)125 TEST(insert) {
126 TestSet set;
127 VIXL_CHECK(set.empty() && (set.size() == 0));
128
129 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
130 set.insert(Obj(i, i));
131 }
132 VIXL_CHECK(set.size() == kNPreallocatedElements);
133 set.insert(Obj(-123, 1));
134 VIXL_CHECK(set.size() == kNPreallocatedElements + 1);
135 set.insert(Obj(-123, 2));
136 set.insert(Obj(-123, 3));
137 VIXL_CHECK(set.size() == kNPreallocatedElements + 3);
138
139 set.clear();
140 VIXL_CHECK(set.empty() && (set.size() == 0));
141 }
142
143
TEST(erase)144 TEST(erase) {
145 TestSet set;
146 VIXL_CHECK(set.empty() && (set.size() == 0));
147
148 // Test with only preallocated elements in the set.
149 VIXL_STATIC_ASSERT(kNPreallocatedElements >= 2);
150 set.insert(Obj(2718, 0));
151 set.erase(Obj(2718, 0));
152 VIXL_CHECK(set.empty() && (set.size() == 0));
153 set.insert(Obj(2718, 0));
154 VIXL_CHECK(set.size() == 1);
155 set.insert(Obj(2718, 1));
156 VIXL_CHECK(set.size() == 2);
157 set.erase(Obj(2718, 0));
158 VIXL_CHECK(set.size() == 1);
159
160 // Test with more elements.
161 for (unsigned i = 0; i < 100 * kNPreallocatedElements; i++) {
162 set.insert(Obj(i * i, i % 30));
163 set.insert(Obj(i, -1));
164 }
165 size_t max_size = set.size();
166 set.erase(Obj(100, -1));
167 VIXL_CHECK(set.size() == max_size - 1);
168 for (size_t i = 2; i <= max_size; i++) {
169 set.erase(set.GetMinElement());
170 VIXL_CHECK(set.size() == max_size - i);
171 }
172
173 VIXL_CHECK(set.empty() && (set.size() == 0));
174 }
175
176
TEST(min)177 TEST(min) {
178 TestSet set;
179 VIXL_CHECK(set.empty() && (set.size() == 0));
180
181 // Test with only preallocated elements in the set.
182 VIXL_STATIC_ASSERT(kNPreallocatedElements >= 4);
183 set.insert(Obj(-1, -1));
184 set.insert(Obj(-1, 0));
185 set.insert(Obj(0, 0));
186 set.insert(Obj(1, 0));
187 VIXL_CHECK(set.GetMinElement() == Obj(-1, -1));
188 VIXL_CHECK(set.GetMinElementKey() == -1);
189 VIXL_CHECK(set.GetMinElement().key_ == set.GetMinElementKey());
190
191 // Test with more elements.
192 set.clear();
193 int max_index = 100 * kNPreallocatedElements;
194 for (int i = 0; i <= max_index; i++) {
195 // Insert elements out of order.
196 int sign = ((i % 2) == 0) ? -1 : 1;
197 set.insert(Obj(sign * i, i));
198 }
199 VIXL_CHECK(set.GetMinElement() == Obj(-max_index, max_index));
200 VIXL_CHECK(set.GetMinElement().key_ == set.GetMinElementKey());
201
202 set.erase(Obj(0, 0));
203 VIXL_CHECK(set.GetMinElement() == Obj(-max_index, max_index));
204 set.erase(set.GetMinElement());
205 VIXL_CHECK(set.GetMinElement() == Obj(-(max_index - 2), max_index - 2));
206
207 set.clear();
208 VIXL_CHECK(set.empty() && (set.size() == 0));
209 }
210
211
TEST(iterator)212 TEST(iterator) {
213 TestSet set;
214 VIXL_CHECK(set.empty() && (set.size() == 0));
215
216 // Ensure that set.begin() == set.end() for the empty set.
217 VIXL_CHECK(set.begin() == set.end());
218
219 // Test with only preallocated elements in the set.
220 size_t expected_total = 0;
221 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
222 set.insert(Obj(i, i));
223 expected_total += i;
224 }
225
226 size_t size = 0;
227 size_t total = 0;
228 for (InvalSetIterator<TestSet> it = set.begin(); it != set.end(); ++it) {
229 total += it->val_;
230 size++;
231 }
232 VIXL_CHECK(size == set.size());
233 VIXL_CHECK(total == expected_total);
234
235 // Test with more elements.
236 for (unsigned i = kNPreallocatedElements; i < 4 * kNPreallocatedElements;
237 i++) {
238 set.insert(Obj(i, i));
239 expected_total += i;
240 }
241
242 size = 0;
243 total = 0;
244 for (InvalSetIterator<TestSet> it = set.begin(); it != set.end(); ++it) {
245 total += it->val_;
246 size++;
247 }
248 VIXL_CHECK(size == set.size());
249 VIXL_CHECK(total == expected_total);
250
251 // Test after elements have been deleted.
252 // - Select an interesting list of elements to erase.
253 std::vector<Obj> to_erase;
254 unsigned step = 0;
255 for (unsigned i = 0; i < set.size(); i += step, step++) {
256 to_erase.push_back(Obj(i, i));
257 }
258 to_erase.push_back(Obj(set.size() - 1, set.size() - 1)); // The last element.
259 to_erase.push_back(Obj(set.size(), set.size())); // Not in the set.
260
261 // - Erase one at a time, retesting after each one.
262 while (!to_erase.empty()) {
263 size_t erased = set.erase(to_erase.back());
264 if (erased > 0) {
265 VIXL_CHECK(erased == 1);
266 expected_total -= to_erase.back().val_;
267 } else {
268 }
269 to_erase.pop_back();
270
271 size = 0;
272 total = 0;
273 for (InvalSetIterator<TestSet> it = set.begin(); it != set.end(); ++it) {
274 total += it->val_;
275 size++;
276 }
277 VIXL_CHECK(size == set.size());
278 VIXL_CHECK(total == expected_total);
279 }
280 }
281
282
283 #if __cplusplus >= 201103L
TEST(iterator_cxx11)284 TEST(iterator_cxx11) {
285 TestSet set;
286 VIXL_CHECK(set.empty() && (set.size() == 0));
287
288 // Test with only preallocated elements in the set.
289 size_t expected_total = 0;
290 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
291 set.insert(Obj(i, i));
292 expected_total += i;
293 }
294
295 size_t size = 0;
296 size_t total = 0;
297 for (auto object : set) {
298 total += object.val_;
299 size++;
300 }
301 VIXL_CHECK(size == set.size());
302 VIXL_CHECK(total == expected_total);
303
304 // Test with more elements.
305 for (unsigned i = kNPreallocatedElements; i < 4 * kNPreallocatedElements;
306 i++) {
307 set.insert(Obj(i, i));
308 expected_total += i;
309 }
310
311 size = 0;
312 total = 0;
313 for (auto object : set) {
314 total += object.val_;
315 size++;
316 }
317 VIXL_CHECK(size == set.size());
318 VIXL_CHECK(total == expected_total);
319
320 // Test after elements have been deleted.
321 // - Select an interesting list of elements to erase.
322 std::vector<Obj> to_erase;
323 unsigned step = 0;
324 for (unsigned i = 0; i < set.size(); i += step, step++) {
325 to_erase.push_back(Obj(i, i));
326 }
327 to_erase.push_back(Obj(set.size() - 1, set.size() - 1)); // The last element.
328 to_erase.push_back(Obj(set.size(), set.size())); // Not in the set.
329
330 // - Erase one at a time, retesting after each one.
331 while (!to_erase.empty()) {
332 size_t erased = set.erase(to_erase.back());
333 if (erased > 0) {
334 VIXL_CHECK(erased == 1);
335 expected_total -= to_erase.back().val_;
336 } else {
337 }
338 to_erase.pop_back();
339
340 size = 0;
341 total = 0;
342 for (auto object : set) {
343 total += object.val_;
344 size++;
345 }
346 VIXL_CHECK(size == set.size());
347 VIXL_CHECK(total == expected_total);
348 }
349 }
350 #endif
351
352
TEST(stl_forward_iterator)353 TEST(stl_forward_iterator) {
354 {
355 TestSet::iterator default_it; // Default-constructible.
356 TestSet::iterator copy_it(default_it); // Copy-constructible.
357 copy_it = default_it; // Copy-assignable.
358 } // Destructible.
359
360 TestSet set1;
361 VIXL_CHECK(set1.empty() && (set1.size() == 0));
362
363 TestSet set2;
364 VIXL_CHECK(set2.empty() && (set2.size() == 0));
365
366 // Test with only preallocated elements in the set.
367 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
368 set1.insert(Obj(i, 1));
369 set2.insert(Obj(i, 2));
370 }
371
372 TestSet::iterator it1_a = set1.begin();
373 TestSet::iterator it1_b = set1.begin();
374
375 // Incrementable (whilst valid).
376 it1_a++;
377 ++it1_b;
378
379 // Testable for equivalence.
380 VIXL_CHECK(it1_a == it1_b);
381 VIXL_CHECK(set1.begin() != set1.end());
382 VIXL_CHECK(set2.begin() != set2.end());
383 VIXL_CHECK(set1.begin() != set2.begin());
384 VIXL_CHECK(set1.end() != set2.end());
385
386 // Dereferencable.
387 VIXL_CHECK((*it1_a++).key_ == 1);
388 VIXL_CHECK(((*it1_a).key_ == 2) && ((*it1_a).val_ == 1));
389 *it1_b = Obj(42, 1);
390 VIXL_CHECK((it1_b->key_ == 42) && (it1_b->val_ == 1));
391
392 #if __cplusplus >= 201103L
393 // Swappable.
394 std::swap(it1_a, it1_b);
395 VIXL_CHECK(it1_a->key_ == 42);
396 VIXL_CHECK(it1_b->key_ == 2);
397 #endif
398 }
399
400
401 } // namespace vixl
402