123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- //===- 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.parseNumericSubstitution(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 an undefined string variable fails.
- FileCheckStringSubstitution StringSubstitution =
- FileCheckStringSubstitution(&Context, "VAR404", 42);
- EXPECT_FALSE(StringSubstitution.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);
- FileCheckNumericSubstitution SubstitutionLine =
- FileCheckNumericSubstitution(&Context, "@LINE", &NumExprLine, 12);
- FileCheckNumericSubstitution SubstitutionN =
- FileCheckNumericSubstitution(&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 an undefined numeric variable fails.
- LineVar.clearValue();
- EXPECT_FALSE(SubstitutionLine.getResult());
- NVar.clearValue();
- EXPECT_FALSE(SubstitutionN.getResult());
- // Substitution of a defined string variable returns the right value.
- FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Context);
- StringSubstitution = FileCheckStringSubstitution(&Context, "FOO", 42);
- Value = StringSubstitution.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 string substitution with an undefined variable
- // returns that variable.
- FileCheckStringSubstitution StringSubstitution =
- FileCheckStringSubstitution(&Context, "VAR404", 42);
- StringRef UndefVar = StringSubstitution.getUndefVarName();
- EXPECT_EQ("VAR404", UndefVar);
- // getUndefVarName() on a string substitution with a defined variable returns
- // an empty string.
- StringSubstitution = FileCheckStringSubstitution(&Context, "FOO", 42);
- UndefVar = StringSubstitution.getUndefVarName();
- EXPECT_EQ("", UndefVar);
- // getUndefVarName() on a numeric substitution with a defined variable
- // returns an empty string.
- FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 42);
- FileCheckNumExpr NumExpr = FileCheckNumExpr(doAdd, &LineVar, 0);
- FileCheckNumericSubstitution NumericSubstitution =
- FileCheckNumericSubstitution(&Context, "@LINE", &NumExpr, 12);
- UndefVar = NumericSubstitution.getUndefVarName();
- EXPECT_EQ("", UndefVar);
- // getUndefVarName() on a numeric substitution with an undefined variable
- // returns that variable.
- LineVar.clearValue();
- UndefVar = NumericSubstitution.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.parseNumericSubstitution(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.parseNumericSubstitution(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.parseNumericSubstitution(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.parseNumericSubstitution(GlobalNumVarRef, false /*IsPseudo*/, "", SM);
- EXPECT_TRUE(NumExpr);
- NumExprVal = NumExpr->eval();
- EXPECT_TRUE(NumExprVal);
- EXPECT_EQ(*NumExprVal, 36U);
- }
- } // namespace
|