1 //===----- SymbolStringPoolTest.cpp - Unit tests for SymbolStringPool -----===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
10 #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
11 #include "gtest/gtest.h"
14 using namespace llvm::orc
;
18 class SymbolStringPoolTest
: public testing::Test
{
20 size_t getRefCount(const SymbolStringPtrBase
&S
) const {
21 return SP
.getRefCount(S
);
27 } // namespace llvm::orc
31 TEST_F(SymbolStringPoolTest
, UniquingAndComparisons
) {
32 auto P1
= SP
.intern("hello");
36 auto P2
= SP
.intern(S
);
38 auto P3
= SP
.intern("goodbye");
40 EXPECT_EQ(P1
, P2
) << "Failed to unique entries";
41 EXPECT_NE(P1
, P3
) << "Unequal pooled symbol strings comparing equal";
43 // We want to test that less-than comparison of SymbolStringPtrs compiles,
44 // however we can't test the actual result as this is a pointer comparison and
45 // SymbolStringPtr doesn't expose the underlying address of the string.
49 TEST_F(SymbolStringPoolTest
, Dereference
) {
50 auto Foo
= SP
.intern("foo");
51 EXPECT_EQ(*Foo
, "foo") << "Equality on dereferenced string failed";
54 TEST_F(SymbolStringPoolTest
, ClearDeadEntries
) {
56 auto P1
= SP
.intern("s1");
57 SP
.clearDeadEntries();
58 EXPECT_FALSE(SP
.empty()) << "\"s1\" entry in pool should still be retained";
60 SP
.clearDeadEntries();
61 EXPECT_TRUE(SP
.empty()) << "pool should be empty";
64 TEST_F(SymbolStringPoolTest
, DebugDump
) {
65 auto A1
= SP
.intern("a");
67 auto B
= SP
.intern("b");
69 std::string DumpString
;
70 raw_string_ostream(DumpString
) << SP
;
72 EXPECT_EQ(DumpString
, "a: 2\nb: 1\n");
75 TEST_F(SymbolStringPoolTest
, NonOwningPointerBasics
) {
76 auto A
= SP
.intern("a");
77 auto B
= SP
.intern("b");
79 NonOwningSymbolStringPtr
ANP1(A
); // Constuct from SymbolStringPtr.
80 NonOwningSymbolStringPtr
ANP2(ANP1
); // Copy-construct.
81 NonOwningSymbolStringPtr
BNP(B
);
83 // Equality comparisons.
85 EXPECT_EQ(ANP1
, ANP2
);
88 EXPECT_EQ(*ANP1
, "a"); // Dereference.
94 SymbolStringPtr
S(ANP1
); // Construct SymbolStringPtr from non-owning.
97 DenseMap
<SymbolStringPtr
, int> M
;
99 EXPECT_EQ(M
.find_as(ANP1
)->second
, 42);
100 EXPECT_EQ(M
.find_as(BNP
), M
.end());
103 TEST_F(SymbolStringPoolTest
, NonOwningPointerRefCounts
) {
104 // Check that creating and destroying non-owning pointers doesn't affect
106 auto A
= SP
.intern("a");
107 EXPECT_EQ(getRefCount(A
), 1U);
109 NonOwningSymbolStringPtr
ANP(A
);
110 EXPECT_EQ(getRefCount(ANP
), 1U)
111 << "Construction of NonOwningSymbolStringPtr from SymbolStringPtr "
115 NonOwningSymbolStringPtr
ANP2(ANP
);
116 EXPECT_EQ(getRefCount(ANP2
), 1U)
117 << "Copy-construction of NonOwningSymbolStringPtr changed ref-count";
120 EXPECT_EQ(getRefCount(ANP
), 1U)
121 << "Destruction of NonOwningSymbolStringPtr changed ref-count";
124 NonOwningSymbolStringPtr ANP2
;
126 EXPECT_EQ(getRefCount(ANP2
), 1U)
127 << "Copy-assignment of NonOwningSymbolStringPtr changed ref-count";
131 NonOwningSymbolStringPtr
ANP2(ANP
);
132 NonOwningSymbolStringPtr
ANP3(std::move(ANP2
));
133 EXPECT_EQ(getRefCount(ANP3
), 1U)
134 << "Move-construction of NonOwningSymbolStringPtr changed ref-count";
138 NonOwningSymbolStringPtr
ANP2(ANP
);
139 NonOwningSymbolStringPtr ANP3
;
140 ANP3
= std::move(ANP2
);
141 EXPECT_EQ(getRefCount(ANP3
), 1U)
142 << "Copy-assignment of NonOwningSymbolStringPtr changed ref-count";
146 TEST_F(SymbolStringPoolTest
, SymbolStringPoolEntryUnsafe
) {
148 auto A
= SP
.intern("a");
149 EXPECT_EQ(getRefCount(A
), 1U);
152 // Try creating an unsafe pool entry ref from the given SymbolStringPtr.
153 // This should not affect the ref-count.
154 auto AUnsafe
= SymbolStringPoolEntryUnsafe::from(A
);
155 EXPECT_EQ(getRefCount(A
), 1U);
157 // Create a new SymbolStringPtr from the unsafe ref. This should increment
159 auto ACopy
= AUnsafe
.copyToSymbolStringPtr();
160 EXPECT_EQ(getRefCount(A
), 2U);
164 // Create a copy of the original string. Move it into an unsafe ref, and
165 // then move it back. None of these operations should affect the ref-count.
167 EXPECT_EQ(getRefCount(A
), 2U);
168 auto AUnsafe
= SymbolStringPoolEntryUnsafe::take(std::move(ACopy
));
169 EXPECT_EQ(getRefCount(A
), 2U);
170 ACopy
= AUnsafe
.moveToSymbolStringPtr();
171 EXPECT_EQ(getRefCount(A
), 2U);
174 // Test manual retain / release.
175 auto AUnsafe
= SymbolStringPoolEntryUnsafe::from(A
);
176 EXPECT_EQ(getRefCount(A
), 1U);
178 EXPECT_EQ(getRefCount(A
), 2U);
180 EXPECT_EQ(getRefCount(A
), 1U);