154 lines · cpp
1//===- ScopedHashTableTest.cpp - ScopedHashTable unit tests ---------------===//2//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/ScopedHashTable.h"10#include "llvm/ADT/StringRef.h"11#include "gtest/gtest.h"12#include <memory>13#include <stack>14 15using ::llvm::ScopedHashTable;16using ::llvm::ScopedHashTableScope;17using ::llvm::StringLiteral;18using ::llvm::StringRef;19 20using ::testing::Test;21 22class ScopedHashTableTest : public Test {23protected:24 ScopedHashTableTest() { symbolTable.insert(kGlobalName, kGlobalValue); }25 26 ScopedHashTable<StringRef, StringRef> symbolTable{};27 ScopedHashTableScope<StringRef, StringRef> globalScope{symbolTable};28 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";34};35 36TEST_F(ScopedHashTableTest, AccessWithNoActiveScope) {37 EXPECT_EQ(symbolTable.count(kGlobalName), 1U);38}39 40TEST_F(ScopedHashTableTest, AccessWithAScope) {41 [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> varScope(42 symbolTable);43 EXPECT_EQ(symbolTable.count(kGlobalName), 1U);44}45 46TEST_F(ScopedHashTableTest, InsertInScope) {47 [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> varScope(48 symbolTable);49 symbolTable.insert(kLocalName, kLocalValue);50 EXPECT_EQ(symbolTable.count(kLocalName), 1U);51}52 53TEST_F(ScopedHashTableTest, InsertInLinearSortedScope) {54 [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> varScope(55 symbolTable);56 [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> varScope2(57 symbolTable);58 [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> varScope3(59 symbolTable);60 symbolTable.insert(kLocalName, kLocalValue);61 EXPECT_EQ(symbolTable.count(kLocalName), 1U);62}63 64TEST_F(ScopedHashTableTest, InsertInOutedScope) {65 {66 [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> varScope(67 symbolTable);68 symbolTable.insert(kLocalName, kLocalValue);69 }70 EXPECT_EQ(symbolTable.count(kLocalName), 0U);71}72 73TEST_F(ScopedHashTableTest, OverrideInScope) {74 [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> funScope(75 symbolTable);76 symbolTable.insert(kLocalName, kLocalValue);77 {78 [[maybe_unused]] ScopedHashTableScope<StringRef, StringRef> varScope(79 symbolTable);80 symbolTable.insert(kLocalName, kLocalValue2);81 EXPECT_EQ(symbolTable.lookup(kLocalName), kLocalValue2);82 }83 EXPECT_EQ(symbolTable.lookup(kLocalName), kLocalValue);84}85 86TEST_F(ScopedHashTableTest, GetCurScope) {87 EXPECT_EQ(symbolTable.getCurScope(), &globalScope);88 {89 ScopedHashTableScope<StringRef, StringRef> funScope(symbolTable);90 ScopedHashTableScope<StringRef, StringRef> funScope2(symbolTable);91 EXPECT_EQ(symbolTable.getCurScope(), &funScope2);92 {93 ScopedHashTableScope<StringRef, StringRef> blockScope(symbolTable);94 EXPECT_EQ(symbolTable.getCurScope(), &blockScope);95 }96 EXPECT_EQ(symbolTable.getCurScope(), &funScope2);97 }98 EXPECT_EQ(symbolTable.getCurScope(), &globalScope);99}100 101TEST_F(ScopedHashTableTest, PopScope) {102 using SymbolTableScopeTy = ScopedHashTable<StringRef, StringRef>::ScopeTy;103 104 std::stack<StringRef> ExpectedValues;105 std::stack<std::unique_ptr<SymbolTableScopeTy>> Scopes;106 107 Scopes.emplace(std::make_unique<SymbolTableScopeTy>(symbolTable));108 ExpectedValues.emplace(kLocalValue);109 symbolTable.insert(kGlobalName, kLocalValue);110 111 Scopes.emplace(std::make_unique<SymbolTableScopeTy>(symbolTable));112 ExpectedValues.emplace(kLocalValue2);113 symbolTable.insert(kGlobalName, kLocalValue2);114 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 implicitly120 // calling Scopes.top()->~SymbolTableScopeTy();121 EXPECT_NE(symbolTable.getCurScope(), nullptr);122 }123 ASSERT_TRUE(ExpectedValues.empty());124 ASSERT_TRUE(Scopes.empty());125 EXPECT_EQ(symbolTable.lookup(kGlobalName), kGlobalValue);126}127 128TEST_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);134 135 std::stack<StringRef> expectedValues{{kLocalValue, kLocalValue2}};136 std::stack<SymbolTableScopeTy *> expectedScopes{{&funScope, &funScope2}};137 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);145 }146 147 // We have imbalanced scopes here:148 // Assertion `HT.CurScope == this && "Scope imbalance!"' failed149 // HT.CurScope is a pointer to the `globalScope` while150 // `SymbolTableScopeTy.this` is still a pointer to `funScope2`.151 // There is no way to write an assert on an assert in googletest so that we152 // mark the test case as DISABLED.153}154