diff options
Diffstat (limited to 'llvm/unittests/Support/FileCheckTest.cpp')
-rw-r--r-- | llvm/unittests/Support/FileCheckTest.cpp | 166 |
1 files changed, 113 insertions, 53 deletions
diff --git a/llvm/unittests/Support/FileCheckTest.cpp b/llvm/unittests/Support/FileCheckTest.cpp index 2b7b2707be8..147ed68e223 100644 --- a/llvm/unittests/Support/FileCheckTest.cpp +++ b/llvm/unittests/Support/FileCheckTest.cpp @@ -49,15 +49,21 @@ expectUndefErrors(std::unordered_set<std::string> ExpectedUndefVarNames, EXPECT_TRUE(ExpectedUndefVarNames.empty()) << toString(ExpectedUndefVarNames); } +// Return whether Err contains any FileCheckUndefVarError whose associated name +// is not ExpectedUndefVarName. static void expectUndefError(const Twine &ExpectedUndefVarName, Error Err) { expectUndefErrors({ExpectedUndefVarName.str()}, std::move(Err)); } +uint64_t doAdd(uint64_t OpL, uint64_t OpR) { return OpL + OpR; } + TEST_F(FileCheckTest, NumericVariable) { - // Undefined variable: getValue and eval fail, error returned by eval holds - // the name of the undefined variable. + // Undefined variable: isValueKnownAtMatchTime returns false, getValue and + // eval fail, error returned by eval holds the name of the undefined + // variable. FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 1); EXPECT_EQ("FOO", FooVar.getName()); + EXPECT_FALSE(FooVar.isValueKnownAtMatchTime()); FileCheckNumericVariableUse FooVarUse = FileCheckNumericVariableUse("FOO", &FooVar); EXPECT_FALSE(FooVar.getValue()); @@ -67,7 +73,9 @@ TEST_F(FileCheckTest, NumericVariable) { FooVar.setValue(42); - // Defined variable: getValue and eval return value set. + // Defined variable: isValueKnownAtMatchTime returns true, getValue and eval + // return value set. + EXPECT_TRUE(FooVar.isValueKnownAtMatchTime()); Optional<uint64_t> Value = FooVar.getValue(); EXPECT_TRUE(bool(Value)); EXPECT_EQ(42U, *Value); @@ -75,24 +83,51 @@ TEST_F(FileCheckTest, NumericVariable) { EXPECT_TRUE(bool(EvalResult)); EXPECT_EQ(42U, *EvalResult); + // Variable defined by numeric expression: isValueKnownAtMatchTime + // returns true, getValue and eval return value of expression, setValue + // clears expression. + std::unique_ptr<FileCheckNumericVariableUse> FooVarUsePtr = + llvm::make_unique<FileCheckNumericVariableUse>("FOO", &FooVar); + std::unique_ptr<FileCheckExpressionLiteral> One = + llvm::make_unique<FileCheckExpressionLiteral>(1); + FileCheckASTBinop Binop = + FileCheckASTBinop(doAdd, std::move(FooVarUsePtr), std::move(One)); + FileCheckNumericVariable FoobarExprVar = + FileCheckNumericVariable("FOOBAR", 2, &Binop); + EXPECT_TRUE(FoobarExprVar.isValueKnownAtMatchTime()); + EXPECT_FALSE(FoobarExprVar.getValue()); + FileCheckNumericVariableUse FoobarExprVarUse = + FileCheckNumericVariableUse("FOOBAR", &FoobarExprVar); + EvalResult = FoobarExprVarUse.eval(); + EXPECT_TRUE(bool(EvalResult)); + EXPECT_EQ(43U, *EvalResult); + EXPECT_TRUE(FoobarExprVar.getExpressionAST()); + FoobarExprVar.setValue(43); + EXPECT_FALSE(FoobarExprVar.getExpressionAST()); + FoobarExprVar = FileCheckNumericVariable("FOOBAR", 2, &Binop); + EXPECT_TRUE(FoobarExprVar.getExpressionAST()); + // Clearing variable: getValue and eval fail. Error returned by eval holds // the name of the cleared variable. FooVar.clearValue(); - Value = FooVar.getValue(); - EXPECT_FALSE(Value); + FoobarExprVar.clearValue(); + EXPECT_FALSE(FoobarExprVar.getExpressionAST()); + EXPECT_FALSE(FooVar.getValue()); + EXPECT_FALSE(FoobarExprVar.getValue()); EvalResult = FooVarUse.eval(); EXPECT_FALSE(EvalResult); expectUndefError("FOO", EvalResult.takeError()); + EvalResult = FoobarExprVarUse.eval(); + EXPECT_FALSE(EvalResult); + expectUndefError("FOOBAR", EvalResult.takeError()); } -uint64_t doAdd(uint64_t OpL, uint64_t OpR) { return OpL + OpR; } - TEST_F(FileCheckTest, Binop) { - FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO"); + FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 1); FooVar.setValue(42); std::unique_ptr<FileCheckNumericVariableUse> FooVarUse = llvm::make_unique<FileCheckNumericVariableUse>("FOO", &FooVar); - FileCheckNumericVariable BarVar = FileCheckNumericVariable("BAR"); + FileCheckNumericVariable BarVar = FileCheckNumericVariable("BAR", 2); BarVar.setValue(18); std::unique_ptr<FileCheckNumericVariableUse> BarVarUse = llvm::make_unique<FileCheckNumericVariableUse>("BAR", &BarVar); @@ -237,19 +272,13 @@ public: P = FileCheckPattern(Check::CheckPlain, &Context, LineNumber++); } - bool parseNumVarDefExpect(StringRef Expr) { - StringRef ExprBufferRef = bufferize(SM, Expr); - return errorToBool(FileCheckPattern::parseNumericVariableDefinition( - ExprBufferRef, &Context, LineNumber, SM) - .takeError()); - } - bool parseSubstExpect(StringRef Expr) { StringRef ExprBufferRef = bufferize(SM, Expr); Optional<FileCheckNumericVariable *> DefinedNumericVariable; - return errorToBool(P.parseNumericSubstitutionBlock( - ExprBufferRef, DefinedNumericVariable, false, SM) - .takeError()); + return errorToBool( + P.parseNumericSubstitutionBlock(ExprBufferRef, DefinedNumericVariable, + false, LineNumber - 1, &Context, SM) + .takeError()); } bool parsePatternExpect(StringRef Pattern) { @@ -264,19 +293,6 @@ public: } }; -TEST_F(FileCheckTest, ParseNumericVariableDefinition) { - PatternTester Tester; - - // Invalid definition of pseudo. - EXPECT_TRUE(Tester.parseNumVarDefExpect("@LINE")); - - // Conflict with pattern variable. - EXPECT_TRUE(Tester.parseNumVarDefExpect("BAR")); - - // Defined variable. - EXPECT_FALSE(Tester.parseNumVarDefExpect("FOO")); -} - TEST_F(FileCheckTest, ParseExpr) { PatternTester Tester; @@ -287,17 +303,18 @@ TEST_F(FileCheckTest, ParseExpr) { EXPECT_TRUE(Tester.parseSubstExpect("@FOO:")); EXPECT_TRUE(Tester.parseSubstExpect("@LINE:")); + // Conflict with pattern variable. + EXPECT_TRUE(Tester.parseSubstExpect("BAR:")); + // Garbage after name of variable being defined. EXPECT_TRUE(Tester.parseSubstExpect("VAR GARBAGE:")); - // Variable defined to numeric expression. - EXPECT_TRUE(Tester.parseSubstExpect("VAR1: FOO")); - // Acceptable variable definition. EXPECT_FALSE(Tester.parseSubstExpect("VAR1:")); EXPECT_FALSE(Tester.parseSubstExpect(" VAR2:")); EXPECT_FALSE(Tester.parseSubstExpect("VAR3 :")); EXPECT_FALSE(Tester.parseSubstExpect("VAR3: ")); + EXPECT_FALSE(Tester.parsePatternExpect("[[#FOOBAR: FOO+1]]")); // Numeric expression. @@ -310,9 +327,21 @@ TEST_F(FileCheckTest, ParseExpr) { EXPECT_FALSE(Tester.parseSubstExpect("FOO")); EXPECT_FALSE(Tester.parseSubstExpect("UNDEF")); - // Use variable defined on same line. - EXPECT_FALSE(Tester.parsePatternExpect("[[#LINE1VAR:]]")); - EXPECT_TRUE(Tester.parseSubstExpect("LINE1VAR")); + // Valid empty expression. + EXPECT_FALSE(Tester.parseSubstExpect("")); + + // Valid use of variable defined on the same line from expression. Note that + // the same pattern object is used for the parsePatternExpect and + // parseSubstExpect since no initNextPattern is called, thus appearing as + // being on the same line from the pattern's point of view. + EXPECT_FALSE(Tester.parsePatternExpect("[[#LINE1VAR:FOO+1]]")); + EXPECT_FALSE(Tester.parseSubstExpect("LINE1VAR")); + + // Invalid use of variable defined on same line from input. As above, the + // absence of a call to initNextPattern makes it appear to be on the same + // line from the pattern's point of view. + EXPECT_FALSE(Tester.parsePatternExpect("[[#LINE2VAR:]]")); + EXPECT_TRUE(Tester.parseSubstExpect("LINE2VAR")); // Unsupported operator. EXPECT_TRUE(Tester.parseSubstExpect("@LINE/2")); @@ -323,6 +352,7 @@ TEST_F(FileCheckTest, ParseExpr) { // Valid expression. EXPECT_FALSE(Tester.parseSubstExpect("@LINE+5")); EXPECT_FALSE(Tester.parseSubstExpect("FOO+4")); + EXPECT_FALSE(Tester.parseSubstExpect("FOOBAR")); Tester.initNextPattern(); EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO+FOO]]")); EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO+3-FOO]]")); @@ -354,7 +384,6 @@ TEST_F(FileCheckTest, ParsePattern) { EXPECT_TRUE(Tester.parsePatternExpect("[[#42INVALID]]")); EXPECT_TRUE(Tester.parsePatternExpect("[[#@FOO]]")); EXPECT_TRUE(Tester.parsePatternExpect("[[#@LINE/2]]")); - EXPECT_TRUE(Tester.parsePatternExpect("[[#YUP:@LINE]]")); // Valid numeric expressions and numeric variable definition. EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO]]")); @@ -365,9 +394,16 @@ TEST_F(FileCheckTest, ParsePattern) { TEST_F(FileCheckTest, Match) { PatternTester Tester; + // Check matching an empty expression only matches a number. + Tester.parsePatternExpect("[[#]]"); + EXPECT_TRUE(Tester.matchExpect("FAIL")); + EXPECT_FALSE(Tester.matchExpect("18")); + // Check matching a definition only matches a number. + Tester.initNextPattern(); Tester.parsePatternExpect("[[#NUMVAR:]]"); EXPECT_TRUE(Tester.matchExpect("FAIL")); + EXPECT_TRUE(Tester.matchExpect("")); EXPECT_FALSE(Tester.matchExpect("18")); // Check matching the variable defined matches the correct number only @@ -381,16 +417,16 @@ TEST_F(FileCheckTest, Match) { // the correct value for @LINE. Tester.initNextPattern(); EXPECT_FALSE(Tester.parsePatternExpect("[[#@LINE]]")); - // Ok, @LINE is 4 now. - EXPECT_FALSE(Tester.matchExpect("4")); + // Ok, @LINE is 5 now. + EXPECT_FALSE(Tester.matchExpect("5")); Tester.initNextPattern(); - // @LINE is now 5, match with substitution failure. + // @LINE is now 6, match with substitution failure. EXPECT_FALSE(Tester.parsePatternExpect("[[#UNKNOWN]]")); EXPECT_TRUE(Tester.matchExpect("FOO")); Tester.initNextPattern(); - // Check that @LINE is 6 as expected. + // Check that @LINE is 7 as expected. EXPECT_FALSE(Tester.parsePatternExpect("[[#@LINE]]")); - EXPECT_FALSE(Tester.matchExpect("6")); + EXPECT_FALSE(Tester.matchExpect("7")); } TEST_F(FileCheckTest, Substitution) { @@ -410,9 +446,9 @@ TEST_F(FileCheckTest, Substitution) { // Substitutions of defined pseudo and non-pseudo numeric variables return // the right value. - FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE"); + FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 1); + FileCheckNumericVariable NVar = FileCheckNumericVariable("N", 1); LineVar.setValue(42); - FileCheckNumericVariable NVar = FileCheckNumericVariable("N"); NVar.setValue(10); auto LineVarUse = llvm::make_unique<FileCheckNumericVariableUse>("@LINE", &LineVar); @@ -494,22 +530,29 @@ TEST_F(FileCheckTest, FileCheckContext) { // Define local variables from command-line. GlobalDefines.clear(); + // Clear local variables to remove dummy numeric variable x that + // parseNumericSubstitutionBlock would have created and stored in + // GlobalNumericVariableTable. + Cxt.clearLocalVars(); GlobalDefines.emplace_back(std::string("LocalVar=FOO")); GlobalDefines.emplace_back(std::string("EmptyVar=")); - GlobalDefines.emplace_back(std::string("#LocalNumVar=18")); + GlobalDefines.emplace_back(std::string("#LocalNumVar1=18")); + GlobalDefines.emplace_back(std::string("#LocalNumVar2=LocalNumVar1+2")); EXPECT_FALSE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM))); // Check defined variables are present and undefined is absent. StringRef LocalVarStr = "LocalVar"; - StringRef LocalNumVarRef = bufferize(SM, "LocalNumVar"); + StringRef LocalNumVar1Ref = bufferize(SM, "LocalNumVar1"); + StringRef LocalNumVar2Ref = bufferize(SM, "LocalNumVar2"); StringRef EmptyVarStr = "EmptyVar"; StringRef UnknownVarStr = "UnknownVar"; Expected<StringRef> LocalVar = Cxt.getPatternVarValue(LocalVarStr); FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Cxt, 1); Optional<FileCheckNumericVariable *> DefinedNumericVariable; Expected<std::unique_ptr<FileCheckExpressionAST>> ExpressionAST = - P.parseNumericSubstitutionBlock(LocalNumVarRef, DefinedNumericVariable, - /*IsLegacyLineExpr=*/false, SM); + P.parseNumericSubstitutionBlock(LocalNumVar1Ref, DefinedNumericVariable, + /*IsLegacyLineExpr=*/false, + /*LineNumber=*/1, &Cxt, SM); EXPECT_TRUE(bool(LocalVar)); EXPECT_EQ(*LocalVar, "FOO"); Expected<StringRef> EmptyVar = Cxt.getPatternVarValue(EmptyVarStr); @@ -518,6 +561,14 @@ TEST_F(FileCheckTest, FileCheckContext) { Expected<uint64_t> ExpressionVal = (*ExpressionAST)->eval(); EXPECT_TRUE(bool(ExpressionVal)); EXPECT_EQ(*ExpressionVal, 18U); + ExpressionAST = + P.parseNumericSubstitutionBlock(LocalNumVar2Ref, DefinedNumericVariable, + /*IsLegacyLineExpr=*/false, + /*LineNumber=*/1, &Cxt, SM); + EXPECT_TRUE(bool(ExpressionAST)); + ExpressionVal = (*ExpressionAST)->eval(); + EXPECT_TRUE(bool(ExpressionVal)); + EXPECT_EQ(*ExpressionVal, 20U); EXPECT_TRUE(bool(EmptyVar)); EXPECT_EQ(*EmptyVar, ""); EXPECT_TRUE(errorToBool(UnknownVar.takeError())); @@ -533,7 +584,14 @@ TEST_F(FileCheckTest, FileCheckContext) { EXPECT_TRUE(errorToBool((*ExpressionAST)->eval().takeError())); P = FileCheckPattern(Check::CheckPlain, &Cxt, 2); ExpressionAST = P.parseNumericSubstitutionBlock( - LocalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, SM); + LocalNumVar1Ref, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, + /*LineNumber=*/2, &Cxt, SM); + EXPECT_TRUE(bool(ExpressionAST)); + ExpressionVal = (*ExpressionAST)->eval(); + EXPECT_TRUE(errorToBool(ExpressionVal.takeError())); + ExpressionAST = P.parseNumericSubstitutionBlock( + LocalNumVar2Ref, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, + /*LineNumber=*/2, &Cxt, SM); EXPECT_TRUE(bool(ExpressionAST)); ExpressionVal = (*ExpressionAST)->eval(); EXPECT_TRUE(errorToBool(ExpressionVal.takeError())); @@ -554,7 +612,8 @@ TEST_F(FileCheckTest, FileCheckContext) { EXPECT_EQ(*GlobalVar, "BAR"); P = FileCheckPattern(Check::CheckPlain, &Cxt, 3); ExpressionAST = P.parseNumericSubstitutionBlock( - GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, SM); + GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, + /*LineNumber=*/3, &Cxt, SM); EXPECT_TRUE(bool(ExpressionAST)); ExpressionVal = (*ExpressionAST)->eval(); EXPECT_TRUE(bool(ExpressionVal)); @@ -565,7 +624,8 @@ TEST_F(FileCheckTest, FileCheckContext) { EXPECT_FALSE(errorToBool(Cxt.getPatternVarValue(GlobalVarStr).takeError())); P = FileCheckPattern(Check::CheckPlain, &Cxt, 4); ExpressionAST = P.parseNumericSubstitutionBlock( - GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, SM); + GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, + /*LineNumber=*/4, &Cxt, SM); EXPECT_TRUE(bool(ExpressionAST)); ExpressionVal = (*ExpressionAST)->eval(); EXPECT_TRUE(bool(ExpressionVal)); |