[llvm] [ADT] Improve unit test coverage for FoldingSet (PR #217214)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 18 22:20:28 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-adt

Author: Kazu Hirata (kazutakahirata)

<details>
<summary>Changes</summary>

This patch adds unit tests covering the following previously uncovered
areas of FoldingSet, FoldingSetVector, and ContextualFoldingSet:

- Move semantics (move constructor and move assignment operator of
  FoldingSet).

- Iterators (begin()/end(), exact element traversal, and pre/post
  increment operators).

- FoldingSetVector (basic operations including deduplication, lookup with
  an insertion token, deterministic iteration order, and clear()).

- ContextualFoldingSet (similar basic operations with contextual node
  profiling).

Assisted-by: Antigravity


---
Full diff: https://github.com/llvm/llvm-project/pull/217214.diff


1 Files Affected:

- (modified) llvm/unittests/ADT/FoldingSet.cpp (+176) 


``````````diff
diff --git a/llvm/unittests/ADT/FoldingSet.cpp b/llvm/unittests/ADT/FoldingSet.cpp
index 0101c85667202..c88df15453c76 100644
--- a/llvm/unittests/ADT/FoldingSet.cpp
+++ b/llvm/unittests/ADT/FoldingSet.cpp
@@ -11,10 +11,16 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/FoldingSet.h"
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include <string>
+#include <vector>
 
 using namespace llvm;
+using testing::ElementsAre;
+using testing::IsEmpty;
+using testing::SizeIs;
+using testing::UnorderedElementsAre;
 
 namespace {
 
@@ -188,4 +194,174 @@ TEST(FoldingSetTest, SmallReserveChangesNothing) {
   EXPECT_EQ(Trivial.capacity(), OldCapacity);
 }
 
+TEST(FoldingSetTest, MoveConstructor) {
+  FoldingSet<TrivialPair> A;
+  TrivialPair T1(10, 100);
+  TrivialPair T2(20, 200);
+  A.InsertNode(&T1);
+  A.InsertNode(&T2);
+  EXPECT_THAT(A, SizeIs(2));
+
+  FoldingSet<TrivialPair> B(std::move(A));
+  EXPECT_THAT(B, SizeIs(2));
+  EXPECT_THAT(B, testing::Not(IsEmpty()));
+
+  void *InsertPos = nullptr;
+  FoldingSetNodeID ID1, ID2;
+  T1.Profile(ID1);
+  T2.Profile(ID2);
+  EXPECT_EQ(&T1, B.FindNodeOrInsertPos(ID1, InsertPos));
+  EXPECT_EQ(&T2, B.FindNodeOrInsertPos(ID2, InsertPos));
+}
+
+TEST(FoldingSetTest, MoveAssignment) {
+  FoldingSet<TrivialPair> A;
+  FoldingSet<TrivialPair> B;
+  TrivialPair T1(10, 100);
+  TrivialPair T2(20, 200);
+  TrivialPair T3(30, 300);
+  B.InsertNode(&T1);
+  A.InsertNode(&T2);
+  A.InsertNode(&T3);
+
+  B = std::move(A);
+  EXPECT_THAT(B, SizeIs(2));
+  EXPECT_THAT(B, testing::Not(IsEmpty()));
+
+  void *InsertPos = nullptr;
+  FoldingSetNodeID ID2, ID3;
+  T2.Profile(ID2);
+  T3.Profile(ID3);
+  EXPECT_EQ(&T2, B.FindNodeOrInsertPos(ID2, InsertPos));
+  EXPECT_EQ(&T3, B.FindNodeOrInsertPos(ID3, InsertPos));
+}
+
+TEST(FoldingSetTest, Iterator) {
+  FoldingSet<TrivialPair> Set;
+  EXPECT_EQ(Set.begin(), Set.end());
+
+  TrivialPair T1(1, 10);
+  TrivialPair T2(2, 20);
+  TrivialPair T3(3, 30);
+  Set.InsertNode(&T1);
+  Set.InsertNode(&T2);
+  Set.InsertNode(&T3);
+
+  {
+    std::vector<const TrivialPair *> Elements;
+    for (const TrivialPair &Item : Set)
+      Elements.push_back(&Item);
+    EXPECT_THAT(Elements, UnorderedElementsAre(&T1, &T2, &T3));
+  }
+
+  ASSERT_NE(Set.begin(), Set.end());
+  auto It = Set.begin();
+  auto ItCopy = It++;
+  EXPECT_NE(It, ItCopy);
+}
+
+TEST(FoldingSetTest, FoldingSetVectorBasic) {
+  FoldingSetVector<TrivialPair> Vec;
+  EXPECT_THAT(Vec, IsEmpty());
+  EXPECT_THAT(Vec, SizeIs(0));
+
+  TrivialPair T1(10, 100);
+  TrivialPair T1Copy(10, 100);
+  TrivialPair T2(20, 200);
+  TrivialPair T3(30, 300);
+
+  EXPECT_EQ(&T1, Vec.GetOrInsertNode(&T1));
+  EXPECT_EQ(&T1, Vec.GetOrInsertNode(&T1Copy));
+  EXPECT_THAT(Vec, SizeIs(1));
+
+  // Insert a new node using an insertion token.
+  FoldingSetNodeID ID2;
+  T2.Profile(ID2);
+  void *InsertPos = nullptr;
+  EXPECT_EQ(nullptr, Vec.FindNodeOrInsertPos(ID2, InsertPos));
+  ASSERT_NE(nullptr, InsertPos);
+  Vec.InsertNode(&T2, InsertPos);
+  EXPECT_THAT(Vec, SizeIs(2));
+
+  Vec.InsertNode(&T3);
+  EXPECT_THAT(Vec, SizeIs(3));
+  EXPECT_THAT(Vec, testing::Not(IsEmpty()));
+
+  // Verify deterministic iteration order matching insertion order.
+  {
+    std::vector<const TrivialPair *> Elements;
+    for (const TrivialPair &Item : Vec)
+      Elements.push_back(&Item);
+    EXPECT_THAT(Elements, ElementsAre(&T1, &T2, &T3));
+  }
+
+  Vec.clear();
+  EXPECT_THAT(Vec, IsEmpty());
+  EXPECT_THAT(Vec, SizeIs(0));
+}
+
+struct TestContext {
+  unsigned Value = 0;
+};
+
+struct ContextualPair : public FoldingSetNode {
+  unsigned Key = 0;
+  unsigned Value = 0;
+  ContextualPair(unsigned K, unsigned V) : FoldingSetNode(), Key(K), Value(V) {}
+
+  void Profile(FoldingSetNodeID &ID, TestContext Context) const {
+    ID.AddInteger(Key ^ Context.Value);
+    ID.AddInteger(Value ^ Context.Value);
+  }
+};
+
+TEST(FoldingSetTest, ContextualFoldingSetBasic) {
+  TestContext ContextVal{0xABCD};
+  ContextualFoldingSet<ContextualPair, TestContext> Set(ContextVal);
+  EXPECT_EQ(ContextVal.Value, Set.getContext().Value);
+  EXPECT_THAT(Set, IsEmpty());
+  EXPECT_THAT(Set, SizeIs(0));
+
+  ContextualPair T1(10, 100);
+  ContextualPair T1Copy(10, 100);
+  ContextualPair T2(20, 200);
+
+  EXPECT_EQ(&T1, Set.GetOrInsertNode(&T1));
+  EXPECT_EQ(&T1, Set.GetOrInsertNode(&T1Copy));
+  EXPECT_THAT(Set, SizeIs(1));
+
+  // Insert a new node using an insertion token.
+  void *InsertPos = nullptr;
+  FoldingSetNodeID ID2;
+  T2.Profile(ID2, ContextVal);
+  EXPECT_EQ(nullptr, Set.FindNodeOrInsertPos(ID2, InsertPos));
+  ASSERT_NE(nullptr, InsertPos);
+  Set.InsertNode(&T2, InsertPos);
+  EXPECT_THAT(Set, SizeIs(2));
+
+  EXPECT_EQ(&T2, Set.FindNodeOrInsertPos(ID2, InsertPos));
+
+  {
+    std::vector<const ContextualPair *> Elements;
+    for (const ContextualPair &Item : Set)
+      Elements.push_back(&Item);
+    EXPECT_THAT(Elements, UnorderedElementsAre(&T1, &T2));
+  }
+
+  EXPECT_TRUE(Set.RemoveNode(&T1));
+  EXPECT_THAT(Set, SizeIs(1));
+  EXPECT_FALSE(Set.RemoveNode(&T1));
+
+  {
+    std::vector<const ContextualPair *> Elements;
+    for (const ContextualPair &Item : Set)
+      Elements.push_back(&Item);
+    EXPECT_THAT(Elements, UnorderedElementsAre(&T2));
+  }
+
+  Set.clear();
+  EXPECT_THAT(Set, IsEmpty());
+  EXPECT_THAT(Set, SizeIs(0));
+}
+
 } // namespace

``````````

</details>


https://github.com/llvm/llvm-project/pull/217214


More information about the llvm-commits mailing list