// Copyright 2014, ARM Limited // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither the name of ARM Limited nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "test-runner.h" #include "vixl/invalset.h" namespace vixl { // This file contains tests for the `InvalSet` and `InvalSetIterator` classes. #define TEST(name) TEST_(INVALSET_##name) typedef ptrdiff_t KeyType; typedef ptrdiff_t ValType; // We test with an object for which the key and the value are distinct. class Obj { public: Obj() {} Obj(KeyType key, ValType val) : key_(key), val_(val) {} KeyType key_; ValType val_; bool operator==(const Obj& other) const { return (key_ == other.key_) && (val_ == other.val_); } bool operator<(const Obj& other) const { return (key_ < other.key_) || ((key_ == other.key_) && (val_ < other.val_)); } bool operator<=(const Obj& other) const { return (key_ <= other.key_) || ((key_ == other.key_) && (val_ <= other.val_)); } bool operator>(const Obj& other) const { return (key_ > other.key_) || ((key_ == other.key_) && (val_ > other.val_)); } }; static const unsigned kNPreallocatedElements = 8; static const KeyType kInvalidKey = PTRDIFF_MAX; static const size_t kReclaimFrom = 1000; static const unsigned kReclaimFactor = 10; typedef InvalSet<Obj, kNPreallocatedElements, KeyType, kInvalidKey, kReclaimFrom, kReclaimFactor> TestSet; template<> inline KeyType InvalSet<Obj, kNPreallocatedElements, KeyType, kInvalidKey, kReclaimFrom, kReclaimFactor>::Key(const Obj& obj) { return obj.key_; } template<> inline void InvalSet<Obj, kNPreallocatedElements, KeyType, kInvalidKey, kReclaimFrom, kReclaimFactor>::SetKey(Obj* obj, KeyType key) { obj->key_ = key; } TEST(basic_test) { TestSet set; VIXL_CHECK(set.empty() && (set.size() == 0)); for (unsigned i = 0; i < kNPreallocatedElements; i++) { set.insert(Obj(i, i)); } VIXL_CHECK(set.size() == kNPreallocatedElements); set.insert(Obj(-123, 456)); set.insert(Obj(2718, 2871828)); VIXL_CHECK(set.size() == kNPreallocatedElements + 2); VIXL_CHECK(set.min_element() == Obj(-123, 456)); set.erase(Obj(-123, 456)); VIXL_CHECK(set.min_element_key() == 0); set.clear(); VIXL_CHECK(set.empty() && (set.size() == 0)); } TEST(valid_element) { VIXL_CHECK(TestSet::IsValid(Obj(0, 0))); VIXL_CHECK(TestSet::IsValid(Obj(-1, 0))); VIXL_CHECK(TestSet::IsValid(Obj(kInvalidKey - 1, 0))); VIXL_CHECK(!TestSet::IsValid(Obj(kInvalidKey, 0))); } TEST(insert) { TestSet set; VIXL_CHECK(set.empty() && (set.size() == 0)); for (unsigned i = 0; i < kNPreallocatedElements; i++) { set.insert(Obj(i, i)); } VIXL_CHECK(set.size() == kNPreallocatedElements); set.insert(Obj(-123, 1)); VIXL_CHECK(set.size() == kNPreallocatedElements + 1); set.insert(Obj(-123, 2)); set.insert(Obj(-123, 3)); VIXL_CHECK(set.size() == kNPreallocatedElements + 3); set.clear(); VIXL_CHECK(set.empty() && (set.size() == 0)); } TEST(erase) { TestSet set; VIXL_CHECK(set.empty() && (set.size() == 0)); // Test with only preallocated elements in the set. VIXL_STATIC_ASSERT(kNPreallocatedElements >= 2); set.insert(Obj(2718, 0)); set.erase(Obj(2718, 0)); VIXL_CHECK(set.empty() && (set.size() == 0)); set.insert(Obj(2718, 0)); VIXL_CHECK(set.size() == 1); set.insert(Obj(2718, 1)); VIXL_CHECK(set.size() == 2); set.erase(Obj(2718, 0)); VIXL_CHECK(set.size() == 1); // Test with more elements. for (unsigned i = 0; i < 100 * kNPreallocatedElements; i++) { set.insert(Obj(i * i, i % 30)); set.insert(Obj(i, -1)); } size_t max_size = set.size(); set.erase(Obj(100, -1)); VIXL_CHECK(set.size() == max_size - 1); for (size_t i = 2; i <= max_size; i++) { set.erase(set.min_element()); VIXL_CHECK(set.size() == max_size - i); } VIXL_CHECK(set.empty() && (set.size() == 0)); } TEST(min) { TestSet set; VIXL_CHECK(set.empty() && (set.size() == 0)); // Test with only preallocated elements in the set. VIXL_STATIC_ASSERT(kNPreallocatedElements >= 4); set.insert(Obj(-1, -1)); set.insert(Obj(-1, 0)); set.insert(Obj(0, 0)); set.insert(Obj(1, 0)); VIXL_CHECK(set.min_element() == Obj(-1, -1)); VIXL_CHECK(set.min_element_key() == -1); VIXL_CHECK(set.min_element().key_ == set.min_element_key()); // Test with more elements. set.clear(); int max_index = 100 * kNPreallocatedElements; for (int i = 0; i <= max_index; i++) { // Insert elements out of order. int sign = ((i % 2) == 0) ? -1 : 1; set.insert(Obj(sign * i, i)); } VIXL_CHECK(set.min_element() == Obj(-max_index, max_index)); VIXL_CHECK(set.min_element().key_ == set.min_element_key()); set.erase(Obj(0, 0)); VIXL_CHECK(set.min_element() == Obj(-max_index, max_index)); set.erase(set.min_element()); VIXL_CHECK(set.min_element() == Obj(-(max_index - 2), max_index - 2)); set.clear(); VIXL_CHECK(set.empty() && (set.size() == 0)); } TEST(iterator) { TestSet set; VIXL_CHECK(set.empty() && (set.size() == 0)); // Test with only preallocated elements in the set. for (unsigned i = 0; i < kNPreallocatedElements; i++) { set.insert(Obj(i, i)); } size_t size = 0; for (InvalSetIterator<TestSet> it(&set); !it.Done(); it.Advance()) { size++; } VIXL_CHECK(size == set.size()); // Test with more elements. for (unsigned i = kNPreallocatedElements; i < 4 * kNPreallocatedElements; i++) { set.insert(Obj(i, i)); } size = 0; for (InvalSetIterator<TestSet> it(&set); !it.Done(); it.Advance()) { size++; } VIXL_CHECK(size == set.size()); // Test after an element has been deleted. size = 0; set.erase(Obj(0, 0)); for (InvalSetIterator<TestSet> it(&set); !it.Done(); it.Advance()) { size++; } VIXL_CHECK(size == set.size()); } } // namespace vixl