//===------ ADT/SparseSetTest.cpp - SparseSet unit tests - -----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/ADT/SparseMultiSet.h" #include "gtest/gtest.h" using namespace llvm; namespace { typedef SparseMultiSet USet; // Empty set tests. TEST(SparseMultiSetTest, EmptySet) { USet Set; EXPECT_TRUE(Set.empty()); EXPECT_EQ(0u, Set.size()); Set.setUniverse(10); // Lookups on empty set. EXPECT_TRUE(Set.find(0) == Set.end()); EXPECT_TRUE(Set.find(9) == Set.end()); // Same thing on a const reference. const USet &CSet = Set; EXPECT_TRUE(CSet.empty()); EXPECT_EQ(0u, CSet.size()); EXPECT_TRUE(CSet.find(0) == CSet.end()); USet::const_iterator I = CSet.find(5); EXPECT_TRUE(I == CSet.end()); } // Single entry set tests. TEST(SparseMultiSetTest, SingleEntrySet) { USet Set; Set.setUniverse(10); USet::iterator I = Set.insert(5); EXPECT_TRUE(I != Set.end()); EXPECT_TRUE(*I == 5); EXPECT_FALSE(Set.empty()); EXPECT_EQ(1u, Set.size()); EXPECT_TRUE(Set.find(0) == Set.end()); EXPECT_TRUE(Set.find(9) == Set.end()); EXPECT_FALSE(Set.contains(0)); EXPECT_TRUE(Set.contains(5)); // Extra insert. I = Set.insert(5); EXPECT_TRUE(I != Set.end()); EXPECT_TRUE(I == ++Set.find(5)); I--; EXPECT_TRUE(I == Set.find(5)); // Erase non-existent element. I = Set.find(1); EXPECT_TRUE(I == Set.end()); EXPECT_EQ(2u, Set.size()); EXPECT_EQ(5u, *Set.find(5)); // Erase iterator. I = Set.find(5); EXPECT_TRUE(I != Set.end()); I = Set.erase(I); EXPECT_TRUE(I != Set.end()); I = Set.erase(I); EXPECT_TRUE(I == Set.end()); EXPECT_TRUE(Set.empty()); } // Multiple entry set tests. TEST(SparseMultiSetTest, MultipleEntrySet) { USet Set; Set.setUniverse(10); Set.insert(5); Set.insert(5); Set.insert(5); Set.insert(3); Set.insert(2); Set.insert(1); Set.insert(4); EXPECT_EQ(7u, Set.size()); // Erase last element by key. EXPECT_TRUE(Set.erase(Set.find(4)) == Set.end()); EXPECT_EQ(6u, Set.size()); EXPECT_FALSE(Set.contains(4)); EXPECT_TRUE(Set.find(4) == Set.end()); // Erase first element by key. EXPECT_EQ(3u, Set.count(5)); EXPECT_TRUE(Set.find(5) != Set.end()); EXPECT_TRUE(Set.erase(Set.find(5)) != Set.end()); EXPECT_EQ(5u, Set.size()); EXPECT_EQ(2u, Set.count(5)); Set.insert(6); Set.insert(7); EXPECT_EQ(7u, Set.size()); // Erase tail by iterator. EXPECT_TRUE(Set.getTail(6) == Set.getHead(6)); USet::iterator I = Set.erase(Set.find(6)); EXPECT_TRUE(I == Set.end()); EXPECT_EQ(6u, Set.size()); // Erase tails by iterator. EXPECT_EQ(2u, Set.count(5)); I = Set.getTail(5); I = Set.erase(I); EXPECT_TRUE(I == Set.end()); --I; EXPECT_EQ(1u, Set.count(5)); EXPECT_EQ(5u, *I); I = Set.erase(I); EXPECT_TRUE(I == Set.end()); EXPECT_EQ(0u, Set.count(5)); Set.insert(8); Set.insert(8); Set.insert(8); Set.insert(8); Set.insert(8); // Erase all the 8s EXPECT_EQ(5, std::distance(Set.getHead(8), Set.end())); Set.eraseAll(8); EXPECT_EQ(0, std::distance(Set.getHead(8), Set.end())); // Clear and resize the universe. Set.clear(); EXPECT_EQ(0u, Set.size()); EXPECT_FALSE(Set.contains(3)); Set.setUniverse(1000); // Add more than 256 elements. for (unsigned i = 100; i != 800; ++i) Set.insert(i); for (unsigned i = 0; i != 10; ++i) Set.eraseAll(i); for (unsigned i = 100; i != 800; ++i) EXPECT_EQ(1u, Set.count(i)); EXPECT_FALSE(Set.contains(99)); EXPECT_FALSE(Set.contains(800)); EXPECT_EQ(700u, Set.size()); } // Test out iterators TEST(SparseMultiSetTest, Iterators) { USet Set; Set.setUniverse(100); Set.insert(0); Set.insert(1); Set.insert(2); Set.insert(0); Set.insert(1); Set.insert(0); USet::RangePair RangePair = Set.equal_range(0); USet::iterator B = RangePair.first; USet::iterator E = RangePair.second; // Move the iterators around, going to end and coming back. EXPECT_EQ(3, std::distance(B, E)); EXPECT_EQ(B, --(--(--E))); EXPECT_EQ(++(++(++E)), Set.end()); EXPECT_EQ(B, --(--(--E))); EXPECT_EQ(++(++(++E)), Set.end()); // Insert into the tail, and move around again Set.insert(0); EXPECT_EQ(B, --(--(--(--E)))); EXPECT_EQ(++(++(++(++E))), Set.end()); EXPECT_EQ(B, --(--(--(--E)))); EXPECT_EQ(++(++(++(++E))), Set.end()); // Erase a tail, and move around again USet::iterator Erased = Set.erase(Set.getTail(0)); EXPECT_EQ(Erased, E); EXPECT_EQ(B, --(--(--E))); USet Set2; Set2.setUniverse(11); Set2.insert(3); EXPECT_TRUE(!Set2.contains(0)); EXPECT_TRUE(!Set.contains(3)); EXPECT_EQ(Set2.getHead(3), Set2.getTail(3)); EXPECT_EQ(Set2.getHead(0), Set2.getTail(0)); B = Set2.find(3); EXPECT_EQ(Set2.find(3), --(++B)); } struct Alt { unsigned Value; explicit Alt(unsigned x) : Value(x) {} unsigned getSparseSetIndex() const { return Value - 1000; } }; TEST(SparseMultiSetTest, AltStructSet) { typedef SparseMultiSet ASet; ASet Set; Set.setUniverse(10); Set.insert(Alt(1005)); ASet::iterator I = Set.find(5); ASSERT_TRUE(I != Set.end()); EXPECT_EQ(1005u, I->Value); Set.insert(Alt(1006)); Set.insert(Alt(1006)); I = Set.erase(Set.find(6)); ASSERT_TRUE(I != Set.end()); EXPECT_EQ(1006u, I->Value); I = Set.erase(Set.find(6)); ASSERT_TRUE(I == Set.end()); EXPECT_TRUE(Set.contains(5)); EXPECT_FALSE(Set.contains(6)); } } // namespace