blob: 749ddcc4b491353e6e80e044d54d6622f2bf7918 [file] [log] [blame]
armvixl5289c592015-03-02 13:52:04 +00001// Copyright 2014, ARM Limited
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 "test-runner.h"
28
Alexandre Rames1f9074d2016-05-23 15:50:01 +010029#include "invalset-vixl.h"
armvixl5289c592015-03-02 13:52:04 +000030
31namespace vixl {
32
33// This file contains tests for the `InvalSet` and `InvalSetIterator` classes.
34
35#define TEST(name) TEST_(INVALSET_##name)
36
37typedef ptrdiff_t KeyType;
38typedef ptrdiff_t ValType;
39
40// We test with an object for which the key and the value are distinct.
41class Obj {
42 public:
43 Obj() {}
44 Obj(KeyType key, ValType val) : key_(key), val_(val) {}
45 KeyType key_;
46 ValType val_;
47
48 bool operator==(const Obj& other) const {
49 return (key_ == other.key_) && (val_ == other.val_);
50 }
51 bool operator<(const Obj& other) const {
52 return (key_ < other.key_) ||
53 ((key_ == other.key_) && (val_ < other.val_));
54 }
55 bool operator<=(const Obj& other) const {
56 return (key_ <= other.key_) ||
57 ((key_ == other.key_) && (val_ <= other.val_));
58 }
59 bool operator>(const Obj& other) const {
60 return (key_ > other.key_) ||
61 ((key_ == other.key_) && (val_ > other.val_));
62 }
63};
64
65static const unsigned kNPreallocatedElements = 8;
66static const KeyType kInvalidKey = PTRDIFF_MAX;
67static const size_t kReclaimFrom = 1000;
68static const unsigned kReclaimFactor = 10;
69
70typedef InvalSet<Obj,
71 kNPreallocatedElements,
72 KeyType,
73 kInvalidKey,
74 kReclaimFrom,
75 kReclaimFactor> TestSet;
76
77template<>
78inline KeyType InvalSet<Obj,
79 kNPreallocatedElements,
80 KeyType,
81 kInvalidKey,
82 kReclaimFrom,
armvixl0f35e362016-05-10 13:57:58 +010083 kReclaimFactor>::GetKey(const Obj& obj) {
armvixl5289c592015-03-02 13:52:04 +000084 return obj.key_;
85}
86template<>
87inline void InvalSet<Obj,
88 kNPreallocatedElements,
89 KeyType,
90 kInvalidKey,
91 kReclaimFrom,
92 kReclaimFactor>::SetKey(Obj* obj, KeyType key) {
93 obj->key_ = key;
94}
95
96
97TEST(basic_test) {
98 TestSet set;
99 VIXL_CHECK(set.empty() && (set.size() == 0));
100
101 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
102 set.insert(Obj(i, i));
103 }
104 VIXL_CHECK(set.size() == kNPreallocatedElements);
105
106 set.insert(Obj(-123, 456));
107 set.insert(Obj(2718, 2871828));
108 VIXL_CHECK(set.size() == kNPreallocatedElements + 2);
armvixl0f35e362016-05-10 13:57:58 +0100109 VIXL_CHECK(set.GetMinElement() == Obj(-123, 456));
armvixl5289c592015-03-02 13:52:04 +0000110
111 set.erase(Obj(-123, 456));
armvixl0f35e362016-05-10 13:57:58 +0100112 VIXL_CHECK(set.GetMinElementKey() == 0);
armvixl5289c592015-03-02 13:52:04 +0000113
114 set.clear();
115 VIXL_CHECK(set.empty() && (set.size() == 0));
116}
117
118
119TEST(valid_element) {
120 VIXL_CHECK(TestSet::IsValid(Obj(0, 0)));
121 VIXL_CHECK(TestSet::IsValid(Obj(-1, 0)));
122 VIXL_CHECK(TestSet::IsValid(Obj(kInvalidKey - 1, 0)));
123 VIXL_CHECK(!TestSet::IsValid(Obj(kInvalidKey, 0)));
124}
125
126
127TEST(insert) {
128 TestSet set;
129 VIXL_CHECK(set.empty() && (set.size() == 0));
130
131 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
132 set.insert(Obj(i, i));
133 }
134 VIXL_CHECK(set.size() == kNPreallocatedElements);
135 set.insert(Obj(-123, 1));
136 VIXL_CHECK(set.size() == kNPreallocatedElements + 1);
137 set.insert(Obj(-123, 2));
138 set.insert(Obj(-123, 3));
139 VIXL_CHECK(set.size() == kNPreallocatedElements + 3);
140
141 set.clear();
142 VIXL_CHECK(set.empty() && (set.size() == 0));
143}
144
145
146TEST(erase) {
147 TestSet set;
148 VIXL_CHECK(set.empty() && (set.size() == 0));
149
150 // Test with only preallocated elements in the set.
151 VIXL_STATIC_ASSERT(kNPreallocatedElements >= 2);
152 set.insert(Obj(2718, 0));
153 set.erase(Obj(2718, 0));
154 VIXL_CHECK(set.empty() && (set.size() == 0));
155 set.insert(Obj(2718, 0));
156 VIXL_CHECK(set.size() == 1);
157 set.insert(Obj(2718, 1));
158 VIXL_CHECK(set.size() == 2);
159 set.erase(Obj(2718, 0));
160 VIXL_CHECK(set.size() == 1);
161
162 // Test with more elements.
163 for (unsigned i = 0; i < 100 * kNPreallocatedElements; i++) {
164 set.insert(Obj(i * i, i % 30));
165 set.insert(Obj(i, -1));
166 }
167 size_t max_size = set.size();
168 set.erase(Obj(100, -1));
169 VIXL_CHECK(set.size() == max_size - 1);
170 for (size_t i = 2; i <= max_size; i++) {
armvixl0f35e362016-05-10 13:57:58 +0100171 set.erase(set.GetMinElement());
armvixl5289c592015-03-02 13:52:04 +0000172 VIXL_CHECK(set.size() == max_size - i);
173 }
174
175 VIXL_CHECK(set.empty() && (set.size() == 0));
176}
177
178
179TEST(min) {
180 TestSet set;
181 VIXL_CHECK(set.empty() && (set.size() == 0));
182
183 // Test with only preallocated elements in the set.
184 VIXL_STATIC_ASSERT(kNPreallocatedElements >= 4);
185 set.insert(Obj(-1, -1));
186 set.insert(Obj(-1, 0));
187 set.insert(Obj(0, 0));
188 set.insert(Obj(1, 0));
armvixl0f35e362016-05-10 13:57:58 +0100189 VIXL_CHECK(set.GetMinElement() == Obj(-1, -1));
190 VIXL_CHECK(set.GetMinElementKey() == -1);
191 VIXL_CHECK(set.GetMinElement().key_ == set.GetMinElementKey());
armvixl5289c592015-03-02 13:52:04 +0000192
193 // Test with more elements.
194 set.clear();
195 int max_index = 100 * kNPreallocatedElements;
196 for (int i = 0; i <= max_index; i++) {
197 // Insert elements out of order.
198 int sign = ((i % 2) == 0) ? -1 : 1;
199 set.insert(Obj(sign * i, i));
200 }
armvixl0f35e362016-05-10 13:57:58 +0100201 VIXL_CHECK(set.GetMinElement() == Obj(-max_index, max_index));
202 VIXL_CHECK(set.GetMinElement().key_ == set.GetMinElementKey());
armvixl5289c592015-03-02 13:52:04 +0000203
204 set.erase(Obj(0, 0));
armvixl0f35e362016-05-10 13:57:58 +0100205 VIXL_CHECK(set.GetMinElement() == Obj(-max_index, max_index));
206 set.erase(set.GetMinElement());
207 VIXL_CHECK(set.GetMinElement() == Obj(-(max_index - 2), max_index - 2));
armvixl5289c592015-03-02 13:52:04 +0000208
209 set.clear();
210 VIXL_CHECK(set.empty() && (set.size() == 0));
211}
212
213
214TEST(iterator) {
215 TestSet set;
216 VIXL_CHECK(set.empty() && (set.size() == 0));
217
armvixl0f35e362016-05-10 13:57:58 +0100218 // Ensure that set.begin() == set.end() for the empty set.
219 VIXL_CHECK(set.begin() == set.end());
220
armvixl5289c592015-03-02 13:52:04 +0000221 // Test with only preallocated elements in the set.
armvixl0f35e362016-05-10 13:57:58 +0100222 size_t expected_total = 0;
armvixl5289c592015-03-02 13:52:04 +0000223 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
224 set.insert(Obj(i, i));
armvixl0f35e362016-05-10 13:57:58 +0100225 expected_total += i;
armvixl5289c592015-03-02 13:52:04 +0000226 }
227
228 size_t size = 0;
armvixl0f35e362016-05-10 13:57:58 +0100229 size_t total = 0;
230 for (InvalSetIterator<TestSet> it = set.begin(); it != set.end(); ++it) {
231 total += it->val_;
armvixl5289c592015-03-02 13:52:04 +0000232 size++;
233 }
234 VIXL_CHECK(size == set.size());
armvixl0f35e362016-05-10 13:57:58 +0100235 VIXL_CHECK(total == expected_total);
armvixl5289c592015-03-02 13:52:04 +0000236
237 // Test with more elements.
238 for (unsigned i = kNPreallocatedElements;
239 i < 4 * kNPreallocatedElements;
240 i++) {
241 set.insert(Obj(i, i));
armvixl0f35e362016-05-10 13:57:58 +0100242 expected_total += i;
armvixl5289c592015-03-02 13:52:04 +0000243 }
244
245 size = 0;
armvixl0f35e362016-05-10 13:57:58 +0100246 total = 0;
247 for (InvalSetIterator<TestSet> it = set.begin(); it != set.end(); ++it) {
248 total += it->val_;
armvixl5289c592015-03-02 13:52:04 +0000249 size++;
250 }
251 VIXL_CHECK(size == set.size());
armvixl0f35e362016-05-10 13:57:58 +0100252 VIXL_CHECK(total == expected_total);
armvixl5289c592015-03-02 13:52:04 +0000253
armvixl0f35e362016-05-10 13:57:58 +0100254 // Test after elements have been deleted.
255 // - Select an interesting list of elements to erase.
256 std::vector<Obj> to_erase;
257 unsigned step = 0;
258 for (unsigned i = 0; i < set.size(); i += step, step++) {
259 to_erase.push_back(Obj(i, i));
armvixl5289c592015-03-02 13:52:04 +0000260 }
armvixl0f35e362016-05-10 13:57:58 +0100261 to_erase.push_back(Obj(set.size() - 1, set.size() - 1)); // The last element.
262 to_erase.push_back(Obj(set.size(), set.size())); // Not in the set.
263
264 // - Erase one at a time, retesting after each one.
265 while (!to_erase.empty()) {
266 size_t erased = set.erase(to_erase.back());
267 if (erased > 0) {
268 VIXL_CHECK(erased == 1);
269 expected_total -= to_erase.back().val_;
270 } else {
271 }
272 to_erase.pop_back();
273
274 size = 0;
275 total = 0;
276 for (InvalSetIterator<TestSet> it = set.begin(); it != set.end(); ++it) {
277 total += it->val_;
278 size++;
279 }
280 VIXL_CHECK(size == set.size());
281 VIXL_CHECK(total == expected_total);
282 }
armvixl5289c592015-03-02 13:52:04 +0000283}
284
armvixl0f35e362016-05-10 13:57:58 +0100285
286#if __cplusplus >= 201103L
287TEST(iterator_cxx11) {
288 TestSet set;
289 VIXL_CHECK(set.empty() && (set.size() == 0));
290
291 // Test with only preallocated elements in the set.
292 size_t expected_total = 0;
293 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
294 set.insert(Obj(i, i));
295 expected_total += i;
296 }
297
298 size_t size = 0;
299 size_t total = 0;
300 for (auto object : set) {
301 total += object.val_;
302 size++;
303 }
304 VIXL_CHECK(size == set.size());
305 VIXL_CHECK(total == expected_total);
306
307 // Test with more elements.
308 for (unsigned i = kNPreallocatedElements;
309 i < 4 * kNPreallocatedElements;
310 i++) {
311 set.insert(Obj(i, i));
312 expected_total += i;
313 }
314
315 size = 0;
316 total = 0;
317 for (auto object : set) {
318 total += object.val_;
319 size++;
320 }
321 VIXL_CHECK(size == set.size());
322 VIXL_CHECK(total == expected_total);
323
324 // Test after elements have been deleted.
325 // - Select an interesting list of elements to erase.
326 std::vector<Obj> to_erase;
327 unsigned step = 0;
328 for (unsigned i = 0; i < set.size(); i += step, step++) {
329 to_erase.push_back(Obj(i, i));
330 }
331 to_erase.push_back(Obj(set.size() - 1, set.size() - 1)); // The last element.
332 to_erase.push_back(Obj(set.size(), set.size())); // Not in the set.
333
334 // - Erase one at a time, retesting after each one.
335 while (!to_erase.empty()) {
336 size_t erased = set.erase(to_erase.back());
337 if (erased > 0) {
338 VIXL_CHECK(erased == 1);
339 expected_total -= to_erase.back().val_;
340 } else {
341 }
342 to_erase.pop_back();
343
344 size = 0;
345 total = 0;
346 for (auto object : set) {
347 total += object.val_;
348 size++;
349 }
350 VIXL_CHECK(size == set.size());
351 VIXL_CHECK(total == expected_total);
352 }
353}
354#endif
355
356
357TEST(stl_forward_iterator) {
358 {
359 TestSet::iterator default_it; // Default-constructible.
360 TestSet::iterator copy_it(default_it); // Copy-constructible.
361 copy_it = default_it; // Copy-assignable.
362 } // Destructible.
363
364 TestSet set1;
365 VIXL_CHECK(set1.empty() && (set1.size() == 0));
366
367 TestSet set2;
368 VIXL_CHECK(set2.empty() && (set2.size() == 0));
369
370 // Test with only preallocated elements in the set.
371 for (unsigned i = 0; i < kNPreallocatedElements; i++) {
372 set1.insert(Obj(i, 1));
373 set2.insert(Obj(i, 2));
374 }
375
376 TestSet::iterator it1_a = set1.begin();
377 TestSet::iterator it1_b = set1.begin();
378
379 // Incrementable (whilst valid).
380 it1_a++;
381 ++it1_b;
382
383 // Testable for equivalence.
384 VIXL_CHECK(it1_a == it1_b);
385 VIXL_CHECK(set1.begin() != set1.end());
386 VIXL_CHECK(set2.begin() != set2.end());
387 VIXL_CHECK(set1.begin() != set2.begin());
388 VIXL_CHECK(set1.end() != set2.end());
389
390 // Dereferencable.
391 VIXL_CHECK((*it1_a++).key_ == 1);
392 VIXL_CHECK(((*it1_a).key_ == 2) && ((*it1_a).val_ == 1));
393 *it1_b = Obj(42, 1);
394 VIXL_CHECK((it1_b->key_ == 42) && (it1_b->val_ == 1));
395
396#if __cplusplus >= 201103L
397 // Swappable.
398 std::swap(it1_a, it1_b);
399 VIXL_CHECK(it1_a->key_ == 42);
400 VIXL_CHECK(it1_b->key_ == 2);
401#endif
402}
403
404
armvixl5289c592015-03-02 13:52:04 +0000405} // namespace vixl