1 //===- ScopedHashTableTest.cpp - ScopedHashTable unit tests ---------------===//
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/ADT/ScopedHashTable.h"
10 #include "llvm/ADT/StringRef.h"
11 #include "gtest/gtest.h"
15 using ::llvm::ScopedHashTable
;
16 using ::llvm::ScopedHashTableScope
;
17 using ::llvm::StringLiteral
;
18 using ::llvm::StringRef
;
20 using ::testing::Test
;
22 class ScopedHashTableTest
: public Test
{
24 ScopedHashTableTest() { symbolTable
.insert(kGlobalName
, kGlobalValue
); }
26 ScopedHashTable
<StringRef
, StringRef
> symbolTable
{};
27 ScopedHashTableScope
<StringRef
, StringRef
> globalScope
{symbolTable
};
29 static constexpr StringLiteral kGlobalName
= "global";
30 static constexpr StringLiteral kGlobalValue
= "gvalue";
31 static constexpr StringLiteral kLocalName
= "local";
32 static constexpr StringLiteral kLocalValue
= "lvalue";
33 static constexpr StringLiteral kLocalValue2
= "lvalue2";
36 TEST_F(ScopedHashTableTest
, AccessWithNoActiveScope
) {
37 EXPECT_EQ(symbolTable
.count(kGlobalName
), 1U);
40 TEST_F(ScopedHashTableTest
, AccessWithAScope
) {
41 [[maybe_unused
]] ScopedHashTableScope
<StringRef
, StringRef
> varScope(
43 EXPECT_EQ(symbolTable
.count(kGlobalName
), 1U);
46 TEST_F(ScopedHashTableTest
, InsertInScope
) {
47 [[maybe_unused
]] ScopedHashTableScope
<StringRef
, StringRef
> varScope(
49 symbolTable
.insert(kLocalName
, kLocalValue
);
50 EXPECT_EQ(symbolTable
.count(kLocalName
), 1U);
53 TEST_F(ScopedHashTableTest
, InsertInLinearSortedScope
) {
54 [[maybe_unused
]] ScopedHashTableScope
<StringRef
, StringRef
> varScope(
56 [[maybe_unused
]] ScopedHashTableScope
<StringRef
, StringRef
> varScope2(
58 [[maybe_unused
]] ScopedHashTableScope
<StringRef
, StringRef
> varScope3(
60 symbolTable
.insert(kLocalName
, kLocalValue
);
61 EXPECT_EQ(symbolTable
.count(kLocalName
), 1U);
64 TEST_F(ScopedHashTableTest
, InsertInOutedScope
) {
66 [[maybe_unused
]] ScopedHashTableScope
<StringRef
, StringRef
> varScope(
68 symbolTable
.insert(kLocalName
, kLocalValue
);
70 EXPECT_EQ(symbolTable
.count(kLocalName
), 0U);
73 TEST_F(ScopedHashTableTest
, OverrideInScope
) {
74 [[maybe_unused
]] ScopedHashTableScope
<StringRef
, StringRef
> funScope(
76 symbolTable
.insert(kLocalName
, kLocalValue
);
78 [[maybe_unused
]] ScopedHashTableScope
<StringRef
, StringRef
> varScope(
80 symbolTable
.insert(kLocalName
, kLocalValue2
);
81 EXPECT_EQ(symbolTable
.lookup(kLocalName
), kLocalValue2
);
83 EXPECT_EQ(symbolTable
.lookup(kLocalName
), kLocalValue
);
86 TEST_F(ScopedHashTableTest
, GetCurScope
) {
87 EXPECT_EQ(symbolTable
.getCurScope(), &globalScope
);
89 ScopedHashTableScope
<StringRef
, StringRef
> funScope(symbolTable
);
90 ScopedHashTableScope
<StringRef
, StringRef
> funScope2(symbolTable
);
91 EXPECT_EQ(symbolTable
.getCurScope(), &funScope2
);
93 ScopedHashTableScope
<StringRef
, StringRef
> blockScope(symbolTable
);
94 EXPECT_EQ(symbolTable
.getCurScope(), &blockScope
);
96 EXPECT_EQ(symbolTable
.getCurScope(), &funScope2
);
98 EXPECT_EQ(symbolTable
.getCurScope(), &globalScope
);
101 TEST_F(ScopedHashTableTest
, PopScope
) {
102 using SymbolTableScopeTy
= ScopedHashTable
<StringRef
, StringRef
>::ScopeTy
;
104 std::stack
<StringRef
> ExpectedValues
;
105 std::stack
<std::unique_ptr
<SymbolTableScopeTy
>> Scopes
;
107 Scopes
.emplace(std::make_unique
<SymbolTableScopeTy
>(symbolTable
));
108 ExpectedValues
.emplace(kLocalValue
);
109 symbolTable
.insert(kGlobalName
, kLocalValue
);
111 Scopes
.emplace(std::make_unique
<SymbolTableScopeTy
>(symbolTable
));
112 ExpectedValues
.emplace(kLocalValue2
);
113 symbolTable
.insert(kGlobalName
, kLocalValue2
);
115 while (symbolTable
.getCurScope() != &globalScope
) {
116 EXPECT_EQ(symbolTable
.getCurScope(), Scopes
.top().get());
117 EXPECT_EQ(symbolTable
.lookup(kGlobalName
), ExpectedValues
.top());
118 ExpectedValues
.pop();
119 Scopes
.pop(); // destructs the SymbolTableScopeTy instance implicitly
120 // calling Scopes.top()->~SymbolTableScopeTy();
121 EXPECT_NE(symbolTable
.getCurScope(), nullptr);
123 ASSERT_TRUE(ExpectedValues
.empty());
124 ASSERT_TRUE(Scopes
.empty());
125 EXPECT_EQ(symbolTable
.lookup(kGlobalName
), kGlobalValue
);
128 TEST_F(ScopedHashTableTest
, DISABLED_PopScopeOnStack
) {
129 using SymbolTableScopeTy
= ScopedHashTable
<StringRef
, StringRef
>::ScopeTy
;
130 SymbolTableScopeTy
funScope(symbolTable
);
131 symbolTable
.insert(kGlobalName
, kLocalValue
);
132 SymbolTableScopeTy
funScope2(symbolTable
);
133 symbolTable
.insert(kGlobalName
, kLocalValue2
);
135 std::stack
<StringRef
> expectedValues
{{kLocalValue
, kLocalValue2
}};
136 std::stack
<SymbolTableScopeTy
*> expectedScopes
{{&funScope
, &funScope2
}};
138 while (symbolTable
.getCurScope() != &globalScope
) {
139 EXPECT_EQ(symbolTable
.getCurScope(), expectedScopes
.top());
140 expectedScopes
.pop();
141 EXPECT_EQ(symbolTable
.lookup(kGlobalName
), expectedValues
.top());
142 expectedValues
.pop();
143 symbolTable
.getCurScope()->~SymbolTableScopeTy();
144 EXPECT_NE(symbolTable
.getCurScope(), nullptr);
147 // We have imbalanced scopes here:
148 // Assertion `HT.CurScope == this && "Scope imbalance!"' failed
149 // HT.CurScope is a pointer to the `globalScope` while
150 // `SymbolTableScopeTy.this` is still a pointer to `funScope2`.
151 // There is no way to write an assert on an assert in googletest so that we
152 // mark the test case as DISABLED.