1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
//===----- SymbolStringPoolTest.cpp - Unit tests for SymbolStringPool -----===//
//
// 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/ExecutionEngine/Orc/SymbolStringPool.h"
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace llvm::orc;
namespace llvm::orc {
class SymbolStringPoolTest : public testing::Test {
public:
size_t getRefCount(const SymbolStringPtrBase &S) const {
return SP.getRefCount(S);
}
protected:
SymbolStringPool SP;
};
} // namespace llvm::orc
namespace {
TEST_F(SymbolStringPoolTest, UniquingAndComparisons) {
auto P1 = SP.intern("hello");
std::string S("hel");
S += "lo";
auto P2 = SP.intern(S);
auto P3 = SP.intern("goodbye");
EXPECT_EQ(P1, P2) << "Failed to unique entries";
EXPECT_NE(P1, P3) << "Unequal pooled symbol strings comparing equal";
// We want to test that less-than comparison of SymbolStringPtrs compiles,
// however we can't test the actual result as this is a pointer comparison and
// SymbolStringPtr doesn't expose the underlying address of the string.
(void)(P1 < P3);
}
TEST_F(SymbolStringPoolTest, Dereference) {
auto Foo = SP.intern("foo");
EXPECT_EQ(*Foo, "foo") << "Equality on dereferenced string failed";
}
TEST_F(SymbolStringPoolTest, ClearDeadEntries) {
{
auto P1 = SP.intern("s1");
SP.clearDeadEntries();
EXPECT_FALSE(SP.empty()) << "\"s1\" entry in pool should still be retained";
}
SP.clearDeadEntries();
EXPECT_TRUE(SP.empty()) << "pool should be empty";
}
TEST_F(SymbolStringPoolTest, DebugDump) {
auto A1 = SP.intern("a");
auto A2 = A1;
auto B = SP.intern("b");
std::string DumpString;
raw_string_ostream(DumpString) << SP;
EXPECT_EQ(DumpString, "a: 2\nb: 1\n");
}
TEST_F(SymbolStringPoolTest, NonOwningPointerBasics) {
auto A = SP.intern("a");
auto B = SP.intern("b");
NonOwningSymbolStringPtr ANP1(A); // Constuct from SymbolStringPtr.
NonOwningSymbolStringPtr ANP2(ANP1); // Copy-construct.
NonOwningSymbolStringPtr BNP(B);
// Equality comparisons.
EXPECT_EQ(A, ANP1);
EXPECT_EQ(ANP1, ANP2);
EXPECT_NE(ANP1, BNP);
EXPECT_EQ(*ANP1, "a"); // Dereference.
// Assignment.
ANP2 = ANP1;
ANP2 = A;
SymbolStringPtr S(ANP1); // Construct SymbolStringPtr from non-owning.
EXPECT_EQ(S, A);
DenseMap<SymbolStringPtr, int> M;
M[A] = 42;
EXPECT_EQ(M.find_as(ANP1)->second, 42);
EXPECT_EQ(M.find_as(BNP), M.end());
}
TEST_F(SymbolStringPoolTest, NonOwningPointerRefCounts) {
// Check that creating and destroying non-owning pointers doesn't affect
// ref-counts.
auto A = SP.intern("a");
EXPECT_EQ(getRefCount(A), 1U);
NonOwningSymbolStringPtr ANP(A);
EXPECT_EQ(getRefCount(ANP), 1U)
<< "Construction of NonOwningSymbolStringPtr from SymbolStringPtr "
"changed ref-count";
{
NonOwningSymbolStringPtr ANP2(ANP);
EXPECT_EQ(getRefCount(ANP2), 1U)
<< "Copy-construction of NonOwningSymbolStringPtr changed ref-count";
}
EXPECT_EQ(getRefCount(ANP), 1U)
<< "Destruction of NonOwningSymbolStringPtr changed ref-count";
{
NonOwningSymbolStringPtr ANP2;
ANP2 = ANP;
EXPECT_EQ(getRefCount(ANP2), 1U)
<< "Copy-assignment of NonOwningSymbolStringPtr changed ref-count";
}
{
NonOwningSymbolStringPtr ANP2(ANP);
NonOwningSymbolStringPtr ANP3(std::move(ANP2));
EXPECT_EQ(getRefCount(ANP3), 1U)
<< "Move-construction of NonOwningSymbolStringPtr changed ref-count";
}
{
NonOwningSymbolStringPtr ANP2(ANP);
NonOwningSymbolStringPtr ANP3;
ANP3 = std::move(ANP2);
EXPECT_EQ(getRefCount(ANP3), 1U)
<< "Copy-assignment of NonOwningSymbolStringPtr changed ref-count";
}
}
TEST_F(SymbolStringPoolTest, SymbolStringPoolEntryUnsafe) {
auto A = SP.intern("a");
EXPECT_EQ(getRefCount(A), 1U);
{
// Try creating an unsafe pool entry ref from the given SymbolStringPtr.
// This should not affect the ref-count.
auto AUnsafe = SymbolStringPoolEntryUnsafe::from(A);
EXPECT_EQ(getRefCount(A), 1U);
// Create a new SymbolStringPtr from the unsafe ref. This should increment
// the ref-count.
auto ACopy = AUnsafe.copyToSymbolStringPtr();
EXPECT_EQ(getRefCount(A), 2U);
}
{
// Create a copy of the original string. Move it into an unsafe ref, and
// then move it back. None of these operations should affect the ref-count.
auto ACopy = A;
EXPECT_EQ(getRefCount(A), 2U);
auto AUnsafe = SymbolStringPoolEntryUnsafe::take(std::move(ACopy));
EXPECT_EQ(getRefCount(A), 2U);
ACopy = AUnsafe.moveToSymbolStringPtr();
EXPECT_EQ(getRefCount(A), 2U);
}
// Test manual retain / release.
auto AUnsafe = SymbolStringPoolEntryUnsafe::from(A);
EXPECT_EQ(getRefCount(A), 1U);
AUnsafe.retain();
EXPECT_EQ(getRefCount(A), 2U);
AUnsafe.release();
EXPECT_EQ(getRefCount(A), 1U);
}
} // namespace
|