xref: /llvm-project/llvm/unittests/ADT/ScopedHashTableTest.cpp (revision c94ce0cca25229cd0e38560ad6e56a1a2f9a0c8b)
11cc926b8SPavel Samolysov //===- ScopedHashTableTest.cpp - ScopedHashTable unit tests ---------------===//
21cc926b8SPavel Samolysov //
31cc926b8SPavel Samolysov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41cc926b8SPavel Samolysov // See https://llvm.org/LICENSE.txt for license information.
51cc926b8SPavel Samolysov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61cc926b8SPavel Samolysov //
71cc926b8SPavel Samolysov //===----------------------------------------------------------------------===//
81cc926b8SPavel Samolysov 
91cc926b8SPavel Samolysov #include "llvm/ADT/ScopedHashTable.h"
101cc926b8SPavel Samolysov #include "llvm/ADT/StringRef.h"
111cc926b8SPavel Samolysov #include "gtest/gtest.h"
121cc926b8SPavel Samolysov #include <memory>
131cc926b8SPavel Samolysov #include <stack>
141cc926b8SPavel Samolysov 
151cc926b8SPavel Samolysov using ::llvm::ScopedHashTable;
161cc926b8SPavel Samolysov using ::llvm::ScopedHashTableScope;
171cc926b8SPavel Samolysov using ::llvm::StringLiteral;
181cc926b8SPavel Samolysov using ::llvm::StringRef;
191cc926b8SPavel Samolysov 
201cc926b8SPavel Samolysov using ::testing::Test;
211cc926b8SPavel Samolysov 
221cc926b8SPavel Samolysov class ScopedHashTableTest : public Test {
231cc926b8SPavel Samolysov protected:
241cc926b8SPavel Samolysov   ScopedHashTableTest() { symbolTable.insert(kGlobalName, kGlobalValue); }
251cc926b8SPavel Samolysov 
261cc926b8SPavel Samolysov   ScopedHashTable<StringRef, StringRef> symbolTable{};
271cc926b8SPavel Samolysov   ScopedHashTableScope<StringRef, StringRef> globalScope{symbolTable};
281cc926b8SPavel Samolysov 
291cc926b8SPavel Samolysov   static constexpr StringLiteral kGlobalName = "global";
301cc926b8SPavel Samolysov   static constexpr StringLiteral kGlobalValue = "gvalue";
311cc926b8SPavel Samolysov   static constexpr StringLiteral kLocalName = "local";
321cc926b8SPavel Samolysov   static constexpr StringLiteral kLocalValue = "lvalue";
331cc926b8SPavel Samolysov   static constexpr StringLiteral kLocalValue2 = "lvalue2";
341cc926b8SPavel Samolysov };
351cc926b8SPavel Samolysov 
361cc926b8SPavel Samolysov TEST_F(ScopedHashTableTest, AccessWithNoActiveScope) {
371cc926b8SPavel Samolysov   EXPECT_EQ(symbolTable.count(kGlobalName), 1U);
381cc926b8SPavel Samolysov }
391cc926b8SPavel Samolysov 
401cc926b8SPavel Samolysov TEST_F(ScopedHashTableTest, AccessWithAScope) {
41*c94ce0ccSKazu Hirata   [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> varScope(
42*c94ce0ccSKazu Hirata       symbolTable);
431cc926b8SPavel Samolysov   EXPECT_EQ(symbolTable.count(kGlobalName), 1U);
441cc926b8SPavel Samolysov }
451cc926b8SPavel Samolysov 
461cc926b8SPavel Samolysov TEST_F(ScopedHashTableTest, InsertInScope) {
47*c94ce0ccSKazu Hirata   [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> varScope(
48*c94ce0ccSKazu Hirata       symbolTable);
491cc926b8SPavel Samolysov   symbolTable.insert(kLocalName, kLocalValue);
501cc926b8SPavel Samolysov   EXPECT_EQ(symbolTable.count(kLocalName), 1U);
511cc926b8SPavel Samolysov }
521cc926b8SPavel Samolysov 
531cc926b8SPavel Samolysov TEST_F(ScopedHashTableTest, InsertInLinearSortedScope) {
54*c94ce0ccSKazu Hirata   [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> varScope(
55*c94ce0ccSKazu Hirata       symbolTable);
56*c94ce0ccSKazu Hirata   [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> varScope2(
57*c94ce0ccSKazu Hirata       symbolTable);
58*c94ce0ccSKazu Hirata   [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> varScope3(
59*c94ce0ccSKazu Hirata       symbolTable);
601cc926b8SPavel Samolysov   symbolTable.insert(kLocalName, kLocalValue);
611cc926b8SPavel Samolysov   EXPECT_EQ(symbolTable.count(kLocalName), 1U);
621cc926b8SPavel Samolysov }
631cc926b8SPavel Samolysov 
641cc926b8SPavel Samolysov TEST_F(ScopedHashTableTest, InsertInOutedScope) {
651cc926b8SPavel Samolysov   {
66*c94ce0ccSKazu Hirata     [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> varScope(
67*c94ce0ccSKazu Hirata         symbolTable);
681cc926b8SPavel Samolysov     symbolTable.insert(kLocalName, kLocalValue);
691cc926b8SPavel Samolysov   }
701cc926b8SPavel Samolysov   EXPECT_EQ(symbolTable.count(kLocalName), 0U);
711cc926b8SPavel Samolysov }
721cc926b8SPavel Samolysov 
731cc926b8SPavel Samolysov TEST_F(ScopedHashTableTest, OverrideInScope) {
74*c94ce0ccSKazu Hirata   [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> funScope(
75*c94ce0ccSKazu Hirata       symbolTable);
761cc926b8SPavel Samolysov   symbolTable.insert(kLocalName, kLocalValue);
771cc926b8SPavel Samolysov   {
78*c94ce0ccSKazu Hirata     [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> varScope(
79*c94ce0ccSKazu Hirata         symbolTable);
801cc926b8SPavel Samolysov     symbolTable.insert(kLocalName, kLocalValue2);
811cc926b8SPavel Samolysov     EXPECT_EQ(symbolTable.lookup(kLocalName), kLocalValue2);
821cc926b8SPavel Samolysov   }
831cc926b8SPavel Samolysov   EXPECT_EQ(symbolTable.lookup(kLocalName), kLocalValue);
841cc926b8SPavel Samolysov }
851cc926b8SPavel Samolysov 
861cc926b8SPavel Samolysov TEST_F(ScopedHashTableTest, GetCurScope) {
871cc926b8SPavel Samolysov   EXPECT_EQ(symbolTable.getCurScope(), &globalScope);
881cc926b8SPavel Samolysov   {
89*c94ce0ccSKazu Hirata     ScopedHashTableScope<StringRef, StringRef> funScope(symbolTable);
90*c94ce0ccSKazu Hirata     ScopedHashTableScope<StringRef, StringRef> funScope2(symbolTable);
911cc926b8SPavel Samolysov     EXPECT_EQ(symbolTable.getCurScope(), &funScope2);
921cc926b8SPavel Samolysov     {
93*c94ce0ccSKazu Hirata       ScopedHashTableScope<StringRef, StringRef> blockScope(symbolTable);
941cc926b8SPavel Samolysov       EXPECT_EQ(symbolTable.getCurScope(), &blockScope);
951cc926b8SPavel Samolysov     }
961cc926b8SPavel Samolysov     EXPECT_EQ(symbolTable.getCurScope(), &funScope2);
971cc926b8SPavel Samolysov   }
981cc926b8SPavel Samolysov   EXPECT_EQ(symbolTable.getCurScope(), &globalScope);
991cc926b8SPavel Samolysov }
1001cc926b8SPavel Samolysov 
1011cc926b8SPavel Samolysov TEST_F(ScopedHashTableTest, PopScope) {
1021cc926b8SPavel Samolysov   using SymbolTableScopeTy = ScopedHashTable<StringRef, StringRef>::ScopeTy;
1031cc926b8SPavel Samolysov 
1041cc926b8SPavel Samolysov   std::stack<StringRef> ExpectedValues;
1051cc926b8SPavel Samolysov   std::stack<std::unique_ptr<SymbolTableScopeTy>> Scopes;
1061cc926b8SPavel Samolysov 
1071cc926b8SPavel Samolysov   Scopes.emplace(std::make_unique<SymbolTableScopeTy>(symbolTable));
1081cc926b8SPavel Samolysov   ExpectedValues.emplace(kLocalValue);
1091cc926b8SPavel Samolysov   symbolTable.insert(kGlobalName, kLocalValue);
1101cc926b8SPavel Samolysov 
1111cc926b8SPavel Samolysov   Scopes.emplace(std::make_unique<SymbolTableScopeTy>(symbolTable));
1121cc926b8SPavel Samolysov   ExpectedValues.emplace(kLocalValue2);
1131cc926b8SPavel Samolysov   symbolTable.insert(kGlobalName, kLocalValue2);
1141cc926b8SPavel Samolysov 
1151cc926b8SPavel Samolysov   while (symbolTable.getCurScope() != &globalScope) {
1161cc926b8SPavel Samolysov     EXPECT_EQ(symbolTable.getCurScope(), Scopes.top().get());
1171cc926b8SPavel Samolysov     EXPECT_EQ(symbolTable.lookup(kGlobalName), ExpectedValues.top());
1181cc926b8SPavel Samolysov     ExpectedValues.pop();
1191cc926b8SPavel Samolysov     Scopes.pop(); // destructs the SymbolTableScopeTy instance implicitly
1201cc926b8SPavel Samolysov                   // calling Scopes.top()->~SymbolTableScopeTy();
1211cc926b8SPavel Samolysov     EXPECT_NE(symbolTable.getCurScope(), nullptr);
1221cc926b8SPavel Samolysov   }
1231cc926b8SPavel Samolysov   ASSERT_TRUE(ExpectedValues.empty());
1241cc926b8SPavel Samolysov   ASSERT_TRUE(Scopes.empty());
1251cc926b8SPavel Samolysov   EXPECT_EQ(symbolTable.lookup(kGlobalName), kGlobalValue);
1261cc926b8SPavel Samolysov }
1271cc926b8SPavel Samolysov 
1281cc926b8SPavel Samolysov TEST_F(ScopedHashTableTest, DISABLED_PopScopeOnStack) {
1291cc926b8SPavel Samolysov   using SymbolTableScopeTy = ScopedHashTable<StringRef, StringRef>::ScopeTy;
1301cc926b8SPavel Samolysov   SymbolTableScopeTy funScope(symbolTable);
1311cc926b8SPavel Samolysov   symbolTable.insert(kGlobalName, kLocalValue);
1321cc926b8SPavel Samolysov   SymbolTableScopeTy funScope2(symbolTable);
1331cc926b8SPavel Samolysov   symbolTable.insert(kGlobalName, kLocalValue2);
1341cc926b8SPavel Samolysov 
1351cc926b8SPavel Samolysov   std::stack<StringRef> expectedValues{{kLocalValue, kLocalValue2}};
1361cc926b8SPavel Samolysov   std::stack<SymbolTableScopeTy *> expectedScopes{{&funScope, &funScope2}};
1371cc926b8SPavel Samolysov 
1381cc926b8SPavel Samolysov   while (symbolTable.getCurScope() != &globalScope) {
1391cc926b8SPavel Samolysov     EXPECT_EQ(symbolTable.getCurScope(), expectedScopes.top());
1401cc926b8SPavel Samolysov     expectedScopes.pop();
1411cc926b8SPavel Samolysov     EXPECT_EQ(symbolTable.lookup(kGlobalName), expectedValues.top());
1421cc926b8SPavel Samolysov     expectedValues.pop();
1431cc926b8SPavel Samolysov     symbolTable.getCurScope()->~SymbolTableScopeTy();
1441cc926b8SPavel Samolysov     EXPECT_NE(symbolTable.getCurScope(), nullptr);
1451cc926b8SPavel Samolysov   }
1461cc926b8SPavel Samolysov 
1471cc926b8SPavel Samolysov   // We have imbalanced scopes here:
1481cc926b8SPavel Samolysov   // Assertion `HT.CurScope == this && "Scope imbalance!"' failed
1491cc926b8SPavel Samolysov   // HT.CurScope is a pointer to the `globalScope` while
1501cc926b8SPavel Samolysov   // `SymbolTableScopeTy.this` is still a pointer to `funScope2`.
1511cc926b8SPavel Samolysov   // There is no way to write an assert on an assert in googletest so that we
1521cc926b8SPavel Samolysov   // mark the test case as DISABLED.
1531cc926b8SPavel Samolysov }
154