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