blob: fc864ab1131b2a57c6f660d3339a72cff18f7a78 [file] [log] [blame]
//===----- 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";
}
}
} // namespace