1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00
llvm-mirror/unittests/Support/FileCheckTest.cpp

423 lines
15 KiB
C++
Raw Normal View History

//===- llvm/unittest/Support/FileCheckTest.cpp - FileCheck tests --===//
//
// 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/Support/FileCheck.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
class FileCheckTest : public ::testing::Test {};
TEST_F(FileCheckTest, NumericVariable) {
FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 42);
EXPECT_EQ("FOO", FooVar.getName());
// Defined variable: getValue returns a value, setValue fails and value
// remains unchanged.
llvm::Optional<uint64_t> Value = FooVar.getValue();
EXPECT_TRUE(Value);
EXPECT_EQ(42U, *Value);
EXPECT_TRUE(FooVar.setValue(43));
Value = FooVar.getValue();
EXPECT_TRUE(Value);
EXPECT_EQ(42U, *Value);
// Clearing variable: getValue fails, clearValue again fails.
EXPECT_FALSE(FooVar.clearValue());
Value = FooVar.getValue();
EXPECT_FALSE(Value);
EXPECT_TRUE(FooVar.clearValue());
// Undefined variable: setValue works, getValue returns value set.
EXPECT_FALSE(FooVar.setValue(43));
Value = FooVar.getValue();
EXPECT_TRUE(Value);
EXPECT_EQ(43U, *Value);
}
uint64_t doAdd(uint64_t OpL, uint64_t OpR) { return OpL + OpR; }
TEST_F(FileCheckTest, NumExpr) {
FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 42);
FileCheckNumExpr NumExpr = FileCheckNumExpr(doAdd, &FooVar, 18);
// Defined variable: eval returns right value, no undefined variable
// returned.
llvm::Optional<uint64_t> Value = NumExpr.eval();
EXPECT_TRUE(Value);
EXPECT_EQ(60U, *Value);
StringRef UndefVar = NumExpr.getUndefVarName();
EXPECT_EQ("", UndefVar);
// Undefined variable: eval fails, undefined variable returned. We call
// getUndefVarName first to check that it can be called without calling
// eval() first.
FooVar.clearValue();
UndefVar = NumExpr.getUndefVarName();
EXPECT_EQ("FOO", UndefVar);
Value = NumExpr.eval();
EXPECT_FALSE(Value);
}
TEST_F(FileCheckTest, ValidVarNameStart) {
EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('a'));
EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('G'));
EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('_'));
EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('2'));
EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('$'));
EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('@'));
EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('+'));
EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('-'));
EXPECT_FALSE(FileCheckPattern::isValidVarNameStart(':'));
}
TEST_F(FileCheckTest, ParseVar) {
StringRef VarName = "GoodVar42";
bool IsPseudo = true;
unsigned TrailIdx = 0;
EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
EXPECT_FALSE(IsPseudo);
EXPECT_EQ(TrailIdx, VarName.size());
VarName = "$GoodGlobalVar";
IsPseudo = true;
TrailIdx = 0;
EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
EXPECT_FALSE(IsPseudo);
EXPECT_EQ(TrailIdx, VarName.size());
VarName = "@GoodPseudoVar";
IsPseudo = true;
TrailIdx = 0;
EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
EXPECT_TRUE(IsPseudo);
EXPECT_EQ(TrailIdx, VarName.size());
VarName = "42BadVar";
EXPECT_TRUE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
VarName = "$@";
EXPECT_TRUE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
VarName = "B@dVar";
IsPseudo = true;
TrailIdx = 0;
EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
EXPECT_FALSE(IsPseudo);
EXPECT_EQ(TrailIdx, 1U);
VarName = "B$dVar";
IsPseudo = true;
TrailIdx = 0;
EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
EXPECT_FALSE(IsPseudo);
EXPECT_EQ(TrailIdx, 1U);
VarName = "BadVar+";
IsPseudo = true;
TrailIdx = 0;
EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
EXPECT_FALSE(IsPseudo);
EXPECT_EQ(TrailIdx, VarName.size() - 1);
VarName = "BadVar-";
IsPseudo = true;
TrailIdx = 0;
EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
EXPECT_FALSE(IsPseudo);
EXPECT_EQ(TrailIdx, VarName.size() - 1);
VarName = "BadVar:";
IsPseudo = true;
TrailIdx = 0;
EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
EXPECT_FALSE(IsPseudo);
EXPECT_EQ(TrailIdx, VarName.size() - 1);
}
static StringRef bufferize(SourceMgr &SM, StringRef Str) {
std::unique_ptr<MemoryBuffer> Buffer =
MemoryBuffer::getMemBufferCopy(Str, "TestBuffer");
StringRef StrBufferRef = Buffer->getBuffer();
SM.AddNewSourceBuffer(std::move(Buffer), SMLoc());
return StrBufferRef;
}
class ExprTester {
private:
SourceMgr SM;
FileCheckRequest Req;
FileCheckPatternContext Context;
FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Context);
public:
ExprTester() {
std::vector<std::string> GlobalDefines;
GlobalDefines.emplace_back(std::string("#FOO=42"));
Context.defineCmdlineVariables(GlobalDefines, SM);
// Call ParsePattern to have @LINE defined.
P.ParsePattern("N/A", "CHECK", SM, 1, Req);
}
bool parseExpect(std::string &VarName, std::string &Trailer) {
bool IsPseudo = VarName[0] == '@';
std::string NameTrailer = VarName + Trailer;
StringRef NameTrailerRef = bufferize(SM, NameTrailer);
StringRef VarNameRef = NameTrailerRef.substr(0, VarName.size());
StringRef TrailerRef = NameTrailerRef.substr(VarName.size());
return P.parseNumericExpression(VarNameRef, IsPseudo, TrailerRef, SM) ==
nullptr;
}
};
TEST_F(FileCheckTest, ParseExpr) {
ExprTester Tester;
// @LINE with offset.
std::string VarName = "@LINE";
std::string Trailer = "+3";
EXPECT_FALSE(Tester.parseExpect(VarName, Trailer));
// @LINE only.
Trailer = "";
EXPECT_FALSE(Tester.parseExpect(VarName, Trailer));
// Defined variable.
VarName = "FOO";
EXPECT_FALSE(Tester.parseExpect(VarName, Trailer));
// Undefined variable.
VarName = "UNDEF";
EXPECT_TRUE(Tester.parseExpect(VarName, Trailer));
// Wrong Pseudovar.
VarName = "@FOO";
EXPECT_TRUE(Tester.parseExpect(VarName, Trailer));
// Unsupported operator.
VarName = "@LINE";
Trailer = "/2";
EXPECT_TRUE(Tester.parseExpect(VarName, Trailer));
// Missing offset operand.
VarName = "@LINE";
Trailer = "+";
EXPECT_TRUE(Tester.parseExpect(VarName, Trailer));
// Cannot parse offset operand.
VarName = "@LINE";
Trailer = "+x";
EXPECT_TRUE(Tester.parseExpect(VarName, Trailer));
// Unexpected string at end of numeric expression.
VarName = "@LINE";
Trailer = "+5x";
EXPECT_TRUE(Tester.parseExpect(VarName, Trailer));
}
TEST_F(FileCheckTest, Substitution) {
SourceMgr SM;
FileCheckPatternContext Context;
std::vector<std::string> GlobalDefines;
GlobalDefines.emplace_back(std::string("FOO=BAR"));
Context.defineCmdlineVariables(GlobalDefines, SM);
// Substitution of undefined pattern variable fails.
FileCheckPatternSubstitution PatternSubstitution =
FileCheckPatternSubstitution(&Context, "VAR404", 42);
EXPECT_FALSE(PatternSubstitution.getResult());
// Substitutions of defined pseudo and non-pseudo numeric variables return
// the right value.
FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 42);
FileCheckNumericVariable NVar = FileCheckNumericVariable("@N", 10);
FileCheckNumExpr NumExprLine = FileCheckNumExpr(doAdd, &LineVar, 0);
FileCheckNumExpr NumExprN = FileCheckNumExpr(doAdd, &NVar, 3);
FileCheckPatternSubstitution SubstitutionLine =
FileCheckPatternSubstitution(&Context, "@LINE", &NumExprLine, 12);
FileCheckPatternSubstitution SubstitutionN =
FileCheckPatternSubstitution(&Context, "N", &NumExprN, 30);
llvm::Optional<std::string> Value = SubstitutionLine.getResult();
EXPECT_TRUE(Value);
EXPECT_EQ("42", *Value);
Value = SubstitutionN.getResult();
EXPECT_TRUE(Value);
EXPECT_EQ("13", *Value);
// Substitution of undefined numeric variable fails.
LineVar.clearValue();
EXPECT_FALSE(SubstitutionLine.getResult());
NVar.clearValue();
EXPECT_FALSE(SubstitutionN.getResult());
// Substitution of defined pattern variable returns the right value.
FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Context);
PatternSubstitution = FileCheckPatternSubstitution(&Context, "FOO", 42);
Value = PatternSubstitution.getResult();
EXPECT_TRUE(Value);
EXPECT_EQ("BAR", *Value);
}
TEST_F(FileCheckTest, UndefVars) {
SourceMgr SM;
FileCheckPatternContext Context;
std::vector<std::string> GlobalDefines;
GlobalDefines.emplace_back(std::string("FOO=BAR"));
Context.defineCmdlineVariables(GlobalDefines, SM);
// getUndefVarName() on a pattern variable substitution with an undefined
// variable returns that variable.
FileCheckPatternSubstitution Substitution =
FileCheckPatternSubstitution(&Context, "VAR404", 42);
StringRef UndefVar = Substitution.getUndefVarName();
EXPECT_EQ("VAR404", UndefVar);
// getUndefVarName() on a pattern variable substitution with a defined
// variable returns an empty string.
Substitution = FileCheckPatternSubstitution(&Context, "FOO", 42);
UndefVar = Substitution.getUndefVarName();
EXPECT_EQ("", UndefVar);
// getUndefVarName() on a numeric expression substitution with a defined
// variable returns an empty string.
FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 42);
FileCheckNumExpr NumExpr = FileCheckNumExpr(doAdd, &LineVar, 0);
Substitution = FileCheckPatternSubstitution(&Context, "@LINE", &NumExpr, 12);
UndefVar = Substitution.getUndefVarName();
EXPECT_EQ("", UndefVar);
// getUndefVarName() on a numeric expression substitution with an undefined
// variable returns that variable.
LineVar.clearValue();
UndefVar = Substitution.getUndefVarName();
EXPECT_EQ("@LINE", UndefVar);
}
TEST_F(FileCheckTest, FileCheckContext) {
FileCheckPatternContext Cxt = FileCheckPatternContext();
std::vector<std::string> GlobalDefines;
SourceMgr SM;
// Missing equal sign.
GlobalDefines.emplace_back(std::string("LocalVar"));
EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
GlobalDefines.clear();
GlobalDefines.emplace_back(std::string("#LocalNumVar"));
EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
// Empty variable name.
GlobalDefines.clear();
GlobalDefines.emplace_back(std::string("=18"));
EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
GlobalDefines.clear();
GlobalDefines.emplace_back(std::string("#=18"));
EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
// Invalid variable name.
GlobalDefines.clear();
GlobalDefines.emplace_back(std::string("18LocalVar=18"));
EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
GlobalDefines.clear();
GlobalDefines.emplace_back(std::string("#18LocalNumVar=18"));
EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
// Name conflict between pattern and numeric variable.
GlobalDefines.clear();
GlobalDefines.emplace_back(std::string("LocalVar=18"));
GlobalDefines.emplace_back(std::string("#LocalVar=36"));
EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
Cxt = FileCheckPatternContext();
GlobalDefines.clear();
GlobalDefines.emplace_back(std::string("#LocalNumVar=18"));
GlobalDefines.emplace_back(std::string("LocalNumVar=36"));
EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
Cxt = FileCheckPatternContext();
// Invalid numeric value for numeric variable.
GlobalDefines.clear();
GlobalDefines.emplace_back(std::string("#LocalNumVar=x"));
EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
// Define local variables from command-line.
GlobalDefines.clear();
GlobalDefines.emplace_back(std::string("LocalVar=FOO"));
GlobalDefines.emplace_back(std::string("EmptyVar="));
GlobalDefines.emplace_back(std::string("#LocalNumVar=18"));
bool GotError = Cxt.defineCmdlineVariables(GlobalDefines, SM);
EXPECT_FALSE(GotError);
// Check defined variables are present and undefined is absent.
StringRef LocalVarStr = "LocalVar";
StringRef LocalNumVarRef = bufferize(SM, "LocalNumVar");
StringRef EmptyVarStr = "EmptyVar";
StringRef UnknownVarStr = "UnknownVar";
llvm::Optional<StringRef> LocalVar = Cxt.getPatternVarValue(LocalVarStr);
FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Cxt);
FileCheckNumExpr *NumExpr =
P.parseNumericExpression(LocalNumVarRef, false /*IsPseudo*/, "", SM);
llvm::Optional<StringRef> EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
llvm::Optional<StringRef> UnknownVar = Cxt.getPatternVarValue(UnknownVarStr);
EXPECT_TRUE(LocalVar);
EXPECT_EQ(*LocalVar, "FOO");
EXPECT_TRUE(NumExpr);
llvm::Optional<uint64_t> NumExprVal = NumExpr->eval();
EXPECT_TRUE(NumExprVal);
EXPECT_EQ(*NumExprVal, 18U);
EXPECT_TRUE(EmptyVar);
EXPECT_EQ(*EmptyVar, "");
EXPECT_FALSE(UnknownVar);
// Clear local variables and check they become absent.
Cxt.clearLocalVars();
LocalVar = Cxt.getPatternVarValue(LocalVarStr);
EXPECT_FALSE(LocalVar);
// Check a numeric expression's evaluation fails if called after clearing of
// local variables, if it was created before. This is important because local
// variable clearing due to --enable-var-scope happens after numeric
// expressions are linked to the numeric variables they use.
EXPECT_FALSE(NumExpr->eval());
P = FileCheckPattern(Check::CheckPlain, &Cxt);
NumExpr =
P.parseNumericExpression(LocalNumVarRef, false /*IsPseudo*/, "", SM);
EXPECT_FALSE(NumExpr);
EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
EXPECT_FALSE(EmptyVar);
// Redefine global variables and check variables are defined again.
GlobalDefines.emplace_back(std::string("$GlobalVar=BAR"));
GlobalDefines.emplace_back(std::string("#$GlobalNumVar=36"));
GotError = Cxt.defineCmdlineVariables(GlobalDefines, SM);
EXPECT_FALSE(GotError);
StringRef GlobalVarStr = "$GlobalVar";
StringRef GlobalNumVarRef = bufferize(SM, "$GlobalNumVar");
llvm::Optional<StringRef> GlobalVar = Cxt.getPatternVarValue(GlobalVarStr);
EXPECT_TRUE(GlobalVar);
EXPECT_EQ(*GlobalVar, "BAR");
P = FileCheckPattern(Check::CheckPlain, &Cxt);
NumExpr =
P.parseNumericExpression(GlobalNumVarRef, false /*IsPseudo*/, "", SM);
EXPECT_TRUE(NumExpr);
NumExprVal = NumExpr->eval();
EXPECT_TRUE(NumExprVal);
EXPECT_EQ(*NumExprVal, 36U);
// Clear local variables and check global variables remain defined.
Cxt.clearLocalVars();
GlobalVar = Cxt.getPatternVarValue(GlobalVarStr);
EXPECT_TRUE(GlobalVar);
P = FileCheckPattern(Check::CheckPlain, &Cxt);
NumExpr =
P.parseNumericExpression(GlobalNumVarRef, false /*IsPseudo*/, "", SM);
EXPECT_TRUE(NumExpr);
NumExprVal = NumExpr->eval();
EXPECT_TRUE(NumExprVal);
EXPECT_EQ(*NumExprVal, 36U);
}
} // namespace