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> TestSet;
73
74 template <>
75 inline KeyType InvalSet<Obj,
76 kNPreallocatedElements,
77 KeyType,
78 kInvalidKey,
79 kReclaimFrom,
GetKey(const Obj & obj)80 kReclaimFactor>::GetKey(const Obj& obj) {
81 return obj.key_;
82 }
83 template <>
84 inline void InvalSet<Obj,
85 kNPreallocatedElements,
86 KeyType,
87 kInvalidKey,
88 kReclaimFrom,
SetKey(Obj * obj,KeyType key)89 kReclaimFactor>::SetKey(Obj* obj, KeyType key) {
90 obj->key_ = key;
91 }
92
93
TEST(basic_test)94 TEST(basic_test) {
95 TestSet set;
96 VIXL_CHECK(set.empty() && (set.size() == 0));
97
98 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
99 set.insert(Obj(i, i));
100 }
101 VIXL_CHECK(set.size() == kNPreallocatedElements);
102
103 set.insert(Obj(-123, 456));
104 set.insert(Obj(2718, 2871828));
105 VIXL_CHECK(set.size() == kNPreallocatedElements + 2);
106 VIXL_CHECK(set.GetMinElement() == Obj(-123, 456));
107
108 set.erase(Obj(-123, 456));
109 VIXL_CHECK(set.GetMinElementKey() == 0);
110
111 set.clear();
112 VIXL_CHECK(set.empty() && (set.size() == 0));
113 }
114
115
TEST(valid_element)116 TEST(valid_element) {
117 VIXL_CHECK(TestSet::IsValid(Obj(0, 0)));
118 VIXL_CHECK(TestSet::IsValid(Obj(-1, 0)));
119 VIXL_CHECK(TestSet::IsValid(Obj(kInvalidKey - 1, 0)));
120 VIXL_CHECK(!TestSet::IsValid(Obj(kInvalidKey, 0)));
121 }
122
123
TEST(insert)124 TEST(insert) {
125 TestSet set;
126 VIXL_CHECK(set.empty() && (set.size() == 0));
127
128 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
129 set.insert(Obj(i, i));
130 }
131 VIXL_CHECK(set.size() == kNPreallocatedElements);
132 set.insert(Obj(-123, 1));
133 VIXL_CHECK(set.size() == kNPreallocatedElements + 1);
134 set.insert(Obj(-123, 2));
135 set.insert(Obj(-123, 3));
136 VIXL_CHECK(set.size() == kNPreallocatedElements + 3);
137
138 set.clear();
139 VIXL_CHECK(set.empty() && (set.size() == 0));
140 }
141
142
TEST(erase)143 TEST(erase) {
144 TestSet set;
145 VIXL_CHECK(set.empty() && (set.size() == 0));
146
147 // Test with only preallocated elements in the set.
148 VIXL_STATIC_ASSERT(kNPreallocatedElements >= 2);
149 set.insert(Obj(2718, 0));
150 set.erase(Obj(2718, 0));
151 VIXL_CHECK(set.empty() && (set.size() == 0));
152 set.insert(Obj(2718, 0));
153 VIXL_CHECK(set.size() == 1);
154 set.insert(Obj(2718, 1));
155 VIXL_CHECK(set.size() == 2);
156 set.erase(Obj(2718, 0));
157 VIXL_CHECK(set.size() == 1);
158
159 // Test with more elements.
160 for (unsigned i = 0; i < 100 * kNPreallocatedElements; i++) {
161 set.insert(Obj(i * i, i % 30));
162 set.insert(Obj(i, -1));
163 }
164 size_t max_size = set.size();
165 set.erase(Obj(100, -1));
166 VIXL_CHECK(set.size() == max_size - 1);
167 for (size_t i = 2; i <= max_size; i++) {
168 set.erase(set.GetMinElement());
169 VIXL_CHECK(set.size() == max_size - i);
170 }
171
172 VIXL_CHECK(set.empty() && (set.size() == 0));
173 }
174
175
TEST(min)176 TEST(min) {
177 TestSet set;
178 VIXL_CHECK(set.empty() && (set.size() == 0));
179
180 // Test with only preallocated elements in the set.
181 VIXL_STATIC_ASSERT(kNPreallocatedElements >= 4);
182 set.insert(Obj(-1, -1));
183 set.insert(Obj(-1, 0));
184 set.insert(Obj(0, 0));
185 set.insert(Obj(1, 0));
186 VIXL_CHECK(set.GetMinElement() == Obj(-1, -1));
187 VIXL_CHECK(set.GetMinElementKey() == -1);
188 VIXL_CHECK(set.GetMinElement().key_ == set.GetMinElementKey());
189
190 // Test with more elements.
191 set.clear();
192 int max_index = 100 * kNPreallocatedElements;
193 for (int i = 0; i <= max_index; i++) {
194 // Insert elements out of order.
195 int sign = ((i % 2) == 0) ? -1 : 1;
196 set.insert(Obj(sign * i, i));
197 }
198 VIXL_CHECK(set.GetMinElement() == Obj(-max_index, max_index));
199 VIXL_CHECK(set.GetMinElement().key_ == set.GetMinElementKey());
200
201 set.erase(Obj(0, 0));
202 VIXL_CHECK(set.GetMinElement() == Obj(-max_index, max_index));
203 set.erase(set.GetMinElement());
204 VIXL_CHECK(set.GetMinElement() == Obj(-(max_index - 2), max_index - 2));
205
206 set.clear();
207 VIXL_CHECK(set.empty() && (set.size() == 0));
208 }
209
210
TEST(iterator)211 TEST(iterator) {
212 TestSet set;
213 VIXL_CHECK(set.empty() && (set.size() == 0));
214
215 // Ensure that set.begin() == set.end() for the empty set.
216 VIXL_CHECK(set.begin() == set.end());
217
218 // Test with only preallocated elements in the set.
219 size_t expected_total = 0;
220 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
221 set.insert(Obj(i, i));
222 expected_total += i;
223 }
224
225 size_t size = 0;
226 size_t total = 0;
227 for (InvalSetIterator<TestSet> it = set.begin(); it != set.end(); ++it) {
228 total += it->val_;
229 size++;
230 }
231 VIXL_CHECK(size == set.size());
232 VIXL_CHECK(total == expected_total);
233
234 // Test with more elements.
235 for (unsigned i = kNPreallocatedElements; i < 4 * kNPreallocatedElements;
236 i++) {
237 set.insert(Obj(i, i));
238 expected_total += i;
239 }
240
241 size = 0;
242 total = 0;
243 for (InvalSetIterator<TestSet> it = set.begin(); it != set.end(); ++it) {
244 total += it->val_;
245 size++;
246 }
247 VIXL_CHECK(size == set.size());
248 VIXL_CHECK(total == expected_total);
249
250 // Test after elements have been deleted.
251 // - Select an interesting list of elements to erase.
252 std::vector<Obj> to_erase;
253 unsigned step = 0;
254 for (unsigned i = 0; i < set.size(); i += step, step++) {
255 to_erase.push_back(Obj(i, i));
256 }
257 to_erase.push_back(Obj(set.size() - 1, set.size() - 1)); // The last element.
258 to_erase.push_back(Obj(set.size(), set.size())); // Not in the set.
259
260 // - Erase one at a time, retesting after each one.
261 while (!to_erase.empty()) {
262 size_t erased = set.erase(to_erase.back());
263 if (erased > 0) {
264 VIXL_CHECK(erased == 1);
265 expected_total -= to_erase.back().val_;
266 } else {
267 }
268 to_erase.pop_back();
269
270 size = 0;
271 total = 0;
272 for (InvalSetIterator<TestSet> it = set.begin(); it != set.end(); ++it) {
273 total += it->val_;
274 size++;
275 }
276 VIXL_CHECK(size == set.size());
277 VIXL_CHECK(total == expected_total);
278 }
279 }
280
281
282 #if __cplusplus >= 201103L
TEST(iterator_cxx11)283 TEST(iterator_cxx11) {
284 TestSet set;
285 VIXL_CHECK(set.empty() && (set.size() == 0));
286
287 // Test with only preallocated elements in the set.
288 size_t expected_total = 0;
289 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
290 set.insert(Obj(i, i));
291 expected_total += i;
292 }
293
294 size_t size = 0;
295 size_t total = 0;
296 for (auto object : set) {
297 total += object.val_;
298 size++;
299 }
300 VIXL_CHECK(size == set.size());
301 VIXL_CHECK(total == expected_total);
302
303 // Test with more elements.
304 for (unsigned i = kNPreallocatedElements; i < 4 * kNPreallocatedElements;
305 i++) {
306 set.insert(Obj(i, i));
307 expected_total += i;
308 }
309
310 size = 0;
311 total = 0;
312 for (auto object : set) {
313 total += object.val_;
314 size++;
315 }
316 VIXL_CHECK(size == set.size());
317 VIXL_CHECK(total == expected_total);
318
319 // Test after elements have been deleted.
320 // - Select an interesting list of elements to erase.
321 std::vector<Obj> to_erase;
322 unsigned step = 0;
323 for (unsigned i = 0; i < set.size(); i += step, step++) {
324 to_erase.push_back(Obj(i, i));
325 }
326 to_erase.push_back(Obj(set.size() - 1, set.size() - 1)); // The last element.
327 to_erase.push_back(Obj(set.size(), set.size())); // Not in the set.
328
329 // - Erase one at a time, retesting after each one.
330 while (!to_erase.empty()) {
331 size_t erased = set.erase(to_erase.back());
332 if (erased > 0) {
333 VIXL_CHECK(erased == 1);
334 expected_total -= to_erase.back().val_;
335 } else {
336 }
337 to_erase.pop_back();
338
339 size = 0;
340 total = 0;
341 for (auto object : set) {
342 total += object.val_;
343 size++;
344 }
345 VIXL_CHECK(size == set.size());
346 VIXL_CHECK(total == expected_total);
347 }
348 }
349 #endif
350
351
TEST(stl_forward_iterator)352 TEST(stl_forward_iterator) {
353 {
354 TestSet::iterator default_it; // Default-constructible.
355 TestSet::iterator copy_it(default_it); // Copy-constructible.
356 copy_it = default_it; // Copy-assignable.
357 } // Destructible.
358
359 TestSet set1;
360 VIXL_CHECK(set1.empty() && (set1.size() == 0));
361
362 TestSet set2;
363 VIXL_CHECK(set2.empty() && (set2.size() == 0));
364
365 // Test with only preallocated elements in the set.
366 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
367 set1.insert(Obj(i, 1));
368 set2.insert(Obj(i, 2));
369 }
370
371 TestSet::iterator it1_a = set1.begin();
372 TestSet::iterator it1_b = set1.begin();
373
374 // Incrementable (whilst valid).
375 it1_a++;
376 ++it1_b;
377
378 // Testable for equivalence.
379 VIXL_CHECK(it1_a == it1_b);
380 VIXL_CHECK(set1.begin() != set1.end());
381 VIXL_CHECK(set2.begin() != set2.end());
382 VIXL_CHECK(set1.begin() != set2.begin());
383 VIXL_CHECK(set1.end() != set2.end());
384
385 // Dereferencable.
386 VIXL_CHECK((*it1_a++).key_ == 1);
387 VIXL_CHECK(((*it1_a).key_ == 2) && ((*it1_a).val_ == 1));
388 *it1_b = Obj(42, 1);
389 VIXL_CHECK((it1_b->key_ == 42) && (it1_b->val_ == 1));
390
391 #if __cplusplus >= 201103L
392 // Swappable.
393 std::swap(it1_a, it1_b);
394 VIXL_CHECK(it1_a->key_ == 42);
395 VIXL_CHECK(it1_b->key_ == 2);
396 #endif
397 }
398
399
400 } // namespace vixl
401