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