• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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