Thomas Preud'homme | e038fa7 | 2019-04-15 10:10:11 +0000 | [diff] [blame] | 1 | //===- llvm/unittest/Support/FileCheckTest.cpp - FileCheck 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-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "llvm/Support/FileCheck.h" |
| 10 | #include "gtest/gtest.h" |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 11 | #include <unordered_set> |
Thomas Preud'homme | e038fa7 | 2019-04-15 10:10:11 +0000 | [diff] [blame] | 12 | |
| 13 | using namespace llvm; |
| 14 | namespace { |
| 15 | |
| 16 | class FileCheckTest : public ::testing::Test {}; |
| 17 | |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 18 | TEST_F(FileCheckTest, Literal) { |
| 19 | // Eval returns the literal's value. |
| 20 | FileCheckExpressionLiteral Ten(10); |
| 21 | Expected<uint64_t> Value = Ten.eval(); |
| 22 | EXPECT_TRUE(bool(Value)); |
| 23 | EXPECT_EQ(10U, *Value); |
| 24 | |
| 25 | // Max value can be correctly represented. |
| 26 | FileCheckExpressionLiteral Max(std::numeric_limits<uint64_t>::max()); |
| 27 | Value = Max.eval(); |
| 28 | EXPECT_TRUE(bool(Value)); |
| 29 | EXPECT_EQ(std::numeric_limits<uint64_t>::max(), *Value); |
| 30 | } |
| 31 | |
| 32 | static std::string toString(const std::unordered_set<std::string> &Set) { |
| 33 | bool First = true; |
| 34 | std::string Str; |
| 35 | for (StringRef S : Set) { |
| 36 | Str += Twine(First ? "{" + S : ", " + S).str(); |
| 37 | First = false; |
| 38 | } |
| 39 | Str += '}'; |
| 40 | return Str; |
| 41 | } |
| 42 | |
| 43 | static void |
| 44 | expectUndefErrors(std::unordered_set<std::string> ExpectedUndefVarNames, |
| 45 | Error Err) { |
| 46 | handleAllErrors(std::move(Err), [&](const FileCheckUndefVarError &E) { |
| 47 | ExpectedUndefVarNames.erase(E.getVarName()); |
| 48 | }); |
| 49 | EXPECT_TRUE(ExpectedUndefVarNames.empty()) << toString(ExpectedUndefVarNames); |
| 50 | } |
| 51 | |
| 52 | static void expectUndefError(const Twine &ExpectedUndefVarName, Error Err) { |
| 53 | expectUndefErrors({ExpectedUndefVarName.str()}, std::move(Err)); |
| 54 | } |
| 55 | |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 56 | TEST_F(FileCheckTest, NumericVariable) { |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 57 | // Undefined variable: getValue and eval fail, error returned by eval holds |
| 58 | // the name of the undefined variable and setValue does not trigger assert. |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 59 | FileCheckNumericVariable FooVar = FileCheckNumericVariable(1, "FOO"); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 60 | EXPECT_EQ("FOO", FooVar.getName()); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 61 | FileCheckNumericVariableUse FooVarUse = |
| 62 | FileCheckNumericVariableUse("FOO", &FooVar); |
| 63 | EXPECT_FALSE(FooVar.getValue()); |
| 64 | Expected<uint64_t> EvalResult = FooVarUse.eval(); |
| 65 | EXPECT_FALSE(EvalResult); |
| 66 | expectUndefError("FOO", EvalResult.takeError()); |
Thomas Preud'homme | 2bf04f2 | 2019-07-10 12:49:28 +0000 | [diff] [blame] | 67 | FooVar.setValue(42); |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 68 | |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 69 | // Defined variable: getValue and eval return value set. |
| 70 | Optional<uint64_t> Value = FooVar.getValue(); |
| 71 | EXPECT_TRUE(bool(Value)); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 72 | EXPECT_EQ(42U, *Value); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 73 | EvalResult = FooVarUse.eval(); |
| 74 | EXPECT_TRUE(bool(EvalResult)); |
| 75 | EXPECT_EQ(42U, *EvalResult); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 76 | |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 77 | // Clearing variable: getValue and eval fail. Error returned by eval holds |
| 78 | // the name of the cleared variable. |
Thomas Preud'homme | 2bf04f2 | 2019-07-10 12:49:28 +0000 | [diff] [blame] | 79 | FooVar.clearValue(); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 80 | Value = FooVar.getValue(); |
| 81 | EXPECT_FALSE(Value); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 82 | EvalResult = FooVarUse.eval(); |
| 83 | EXPECT_FALSE(EvalResult); |
| 84 | expectUndefError("FOO", EvalResult.takeError()); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 85 | } |
| 86 | |
| 87 | uint64_t doAdd(uint64_t OpL, uint64_t OpR) { return OpL + OpR; } |
| 88 | |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 89 | TEST_F(FileCheckTest, Binop) { |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 90 | FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 42); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 91 | std::unique_ptr<FileCheckNumericVariableUse> FooVarUse = |
| 92 | llvm::make_unique<FileCheckNumericVariableUse>("FOO", &FooVar); |
| 93 | FileCheckNumericVariable BarVar = FileCheckNumericVariable("BAR", 18); |
| 94 | std::unique_ptr<FileCheckNumericVariableUse> BarVarUse = |
| 95 | llvm::make_unique<FileCheckNumericVariableUse>("BAR", &BarVar); |
| 96 | FileCheckASTBinop Binop = |
| 97 | FileCheckASTBinop(doAdd, std::move(FooVarUse), std::move(BarVarUse)); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 98 | |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 99 | // Defined variable: eval returns right value. |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 100 | Expected<uint64_t> Value = Binop.eval(); |
Thomas Preud'homme | f64b7f6 | 2019-07-10 15:31:19 +0000 | [diff] [blame] | 101 | EXPECT_TRUE(bool(Value)); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 102 | EXPECT_EQ(60U, *Value); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 103 | |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 104 | // 1 undefined variable: eval fails, error contains name of undefined |
| 105 | // variable. |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 106 | FooVar.clearValue(); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 107 | Value = Binop.eval(); |
| 108 | EXPECT_FALSE(Value); |
| 109 | expectUndefError("FOO", Value.takeError()); |
| 110 | |
| 111 | // 2 undefined variables: eval fails, error contains names of all undefined |
| 112 | // variables. |
| 113 | BarVar.clearValue(); |
| 114 | Value = Binop.eval(); |
| 115 | EXPECT_FALSE(Value); |
| 116 | expectUndefErrors({"FOO", "BAR"}, Value.takeError()); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 117 | } |
| 118 | |
Thomas Preud'homme | 5a33047 | 2019-04-29 13:32:36 +0000 | [diff] [blame] | 119 | TEST_F(FileCheckTest, ValidVarNameStart) { |
| 120 | EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('a')); |
| 121 | EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('G')); |
| 122 | EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('_')); |
| 123 | EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('2')); |
| 124 | EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('$')); |
| 125 | EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('@')); |
| 126 | EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('+')); |
| 127 | EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('-')); |
| 128 | EXPECT_FALSE(FileCheckPattern::isValidVarNameStart(':')); |
| 129 | } |
Thomas Preud'homme | e038fa7 | 2019-04-15 10:10:11 +0000 | [diff] [blame] | 130 | |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 131 | static StringRef bufferize(SourceMgr &SM, StringRef Str) { |
| 132 | std::unique_ptr<MemoryBuffer> Buffer = |
| 133 | MemoryBuffer::getMemBufferCopy(Str, "TestBuffer"); |
| 134 | StringRef StrBufferRef = Buffer->getBuffer(); |
| 135 | SM.AddNewSourceBuffer(std::move(Buffer), SMLoc()); |
| 136 | return StrBufferRef; |
| 137 | } |
| 138 | |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 139 | TEST_F(FileCheckTest, ParseVar) { |
| 140 | SourceMgr SM; |
| 141 | StringRef OrigVarName = bufferize(SM, "GoodVar42"); |
| 142 | StringRef VarName = OrigVarName; |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 143 | Expected<FileCheckPattern::VariableProperties> ParsedVarResult = |
| 144 | FileCheckPattern::parseVariable(VarName, SM); |
| 145 | EXPECT_TRUE(bool(ParsedVarResult)); |
| 146 | EXPECT_EQ(ParsedVarResult->Name, OrigVarName); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 147 | EXPECT_TRUE(VarName.empty()); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 148 | EXPECT_FALSE(ParsedVarResult->IsPseudo); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 149 | |
| 150 | VarName = OrigVarName = bufferize(SM, "$GoodGlobalVar"); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 151 | ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM); |
| 152 | EXPECT_TRUE(bool(ParsedVarResult)); |
| 153 | EXPECT_EQ(ParsedVarResult->Name, OrigVarName); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 154 | EXPECT_TRUE(VarName.empty()); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 155 | EXPECT_FALSE(ParsedVarResult->IsPseudo); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 156 | |
| 157 | VarName = OrigVarName = bufferize(SM, "@GoodPseudoVar"); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 158 | ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM); |
| 159 | EXPECT_TRUE(bool(ParsedVarResult)); |
| 160 | EXPECT_EQ(ParsedVarResult->Name, OrigVarName); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 161 | EXPECT_TRUE(VarName.empty()); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 162 | EXPECT_TRUE(ParsedVarResult->IsPseudo); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 163 | |
| 164 | VarName = bufferize(SM, "42BadVar"); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 165 | ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM); |
| 166 | EXPECT_TRUE(errorToBool(ParsedVarResult.takeError())); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 167 | |
| 168 | VarName = bufferize(SM, "$@"); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 169 | ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM); |
| 170 | EXPECT_TRUE(errorToBool(ParsedVarResult.takeError())); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 171 | |
| 172 | VarName = OrigVarName = bufferize(SM, "B@dVar"); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 173 | ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM); |
| 174 | EXPECT_TRUE(bool(ParsedVarResult)); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 175 | EXPECT_EQ(VarName, OrigVarName.substr(1)); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 176 | EXPECT_EQ(ParsedVarResult->Name, "B"); |
| 177 | EXPECT_FALSE(ParsedVarResult->IsPseudo); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 178 | |
| 179 | VarName = OrigVarName = bufferize(SM, "B$dVar"); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 180 | ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM); |
| 181 | EXPECT_TRUE(bool(ParsedVarResult)); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 182 | EXPECT_EQ(VarName, OrigVarName.substr(1)); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 183 | EXPECT_EQ(ParsedVarResult->Name, "B"); |
| 184 | EXPECT_FALSE(ParsedVarResult->IsPseudo); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 185 | |
| 186 | VarName = bufferize(SM, "BadVar+"); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 187 | ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM); |
| 188 | EXPECT_TRUE(bool(ParsedVarResult)); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 189 | EXPECT_EQ(VarName, "+"); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 190 | EXPECT_EQ(ParsedVarResult->Name, "BadVar"); |
| 191 | EXPECT_FALSE(ParsedVarResult->IsPseudo); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 192 | |
| 193 | VarName = bufferize(SM, "BadVar-"); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 194 | ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM); |
| 195 | EXPECT_TRUE(bool(ParsedVarResult)); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 196 | EXPECT_EQ(VarName, "-"); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 197 | EXPECT_EQ(ParsedVarResult->Name, "BadVar"); |
| 198 | EXPECT_FALSE(ParsedVarResult->IsPseudo); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 199 | |
| 200 | VarName = bufferize(SM, "BadVar:"); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 201 | ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM); |
| 202 | EXPECT_TRUE(bool(ParsedVarResult)); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 203 | EXPECT_EQ(VarName, ":"); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 204 | EXPECT_EQ(ParsedVarResult->Name, "BadVar"); |
| 205 | EXPECT_FALSE(ParsedVarResult->IsPseudo); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 206 | } |
| 207 | |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 208 | class PatternTester { |
Thomas Preud'homme | 15cb1f1 | 2019-04-29 17:46:26 +0000 | [diff] [blame] | 209 | private: |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 210 | size_t LineNumber = 1; |
Thomas Preud'homme | 15cb1f1 | 2019-04-29 17:46:26 +0000 | [diff] [blame] | 211 | SourceMgr SM; |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 212 | FileCheckRequest Req; |
Thomas Preud'homme | 15cb1f1 | 2019-04-29 17:46:26 +0000 | [diff] [blame] | 213 | FileCheckPatternContext Context; |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 214 | FileCheckPattern P = |
| 215 | FileCheckPattern(Check::CheckPlain, &Context, LineNumber++); |
Thomas Preud'homme | 15cb1f1 | 2019-04-29 17:46:26 +0000 | [diff] [blame] | 216 | |
| 217 | public: |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 218 | PatternTester() { |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 219 | std::vector<std::string> GlobalDefines; |
| 220 | GlobalDefines.emplace_back(std::string("#FOO=42")); |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 221 | GlobalDefines.emplace_back(std::string("BAR=BAZ")); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 222 | EXPECT_FALSE( |
| 223 | errorToBool(Context.defineCmdlineVariables(GlobalDefines, SM))); |
Thomas Preud'homme | 56f6308 | 2019-07-05 16:25:46 +0000 | [diff] [blame] | 224 | Context.createLineVariable(); |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 225 | // Call parsePattern to have @LINE defined. |
| 226 | P.parsePattern("N/A", "CHECK", SM, Req); |
| 227 | // parsePattern does not expect to be called twice for the same line and |
| 228 | // will set FixedStr and RegExStr incorrectly if it is. Therefore prepare |
| 229 | // a pattern for a different line. |
| 230 | initNextPattern(); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 231 | } |
| 232 | |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 233 | void initNextPattern() { |
| 234 | P = FileCheckPattern(Check::CheckPlain, &Context, LineNumber++); |
| 235 | } |
| 236 | |
| 237 | bool parseNumVarDefExpect(StringRef Expr) { |
| 238 | StringRef ExprBufferRef = bufferize(SM, Expr); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 239 | return errorToBool(FileCheckPattern::parseNumericVariableDefinition( |
Thomas Preud'homme | 56f6308 | 2019-07-05 16:25:46 +0000 | [diff] [blame] | 240 | ExprBufferRef, &Context, LineNumber, SM) |
| 241 | .takeError()); |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 242 | } |
| 243 | |
| 244 | bool parseSubstExpect(StringRef Expr) { |
| 245 | StringRef ExprBufferRef = bufferize(SM, Expr); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 246 | Optional<FileCheckNumericVariable *> DefinedNumericVariable; |
| 247 | return errorToBool(P.parseNumericSubstitutionBlock( |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 248 | ExprBufferRef, DefinedNumericVariable, false, SM) |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 249 | .takeError()); |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 250 | } |
| 251 | |
| 252 | bool parsePatternExpect(StringRef Pattern) { |
| 253 | StringRef PatBufferRef = bufferize(SM, Pattern); |
| 254 | return P.parsePattern(PatBufferRef, "CHECK", SM, Req); |
| 255 | } |
| 256 | |
| 257 | bool matchExpect(StringRef Buffer) { |
| 258 | StringRef BufferRef = bufferize(SM, Buffer); |
| 259 | size_t MatchLen; |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 260 | return errorToBool(P.match(BufferRef, MatchLen, SM).takeError()); |
Thomas Preud'homme | 15cb1f1 | 2019-04-29 17:46:26 +0000 | [diff] [blame] | 261 | } |
| 262 | }; |
| 263 | |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 264 | TEST_F(FileCheckTest, ParseNumericVariableDefinition) { |
| 265 | PatternTester Tester; |
Thomas Preud'homme | 15cb1f1 | 2019-04-29 17:46:26 +0000 | [diff] [blame] | 266 | |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 267 | // Invalid definition of pseudo. |
| 268 | EXPECT_TRUE(Tester.parseNumVarDefExpect("@LINE")); |
Thomas Preud'homme | 15cb1f1 | 2019-04-29 17:46:26 +0000 | [diff] [blame] | 269 | |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 270 | // Conflict with pattern variable. |
| 271 | EXPECT_TRUE(Tester.parseNumVarDefExpect("BAR")); |
Thomas Preud'homme | 15cb1f1 | 2019-04-29 17:46:26 +0000 | [diff] [blame] | 272 | |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 273 | // Defined variable. |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 274 | EXPECT_FALSE(Tester.parseNumVarDefExpect("FOO")); |
| 275 | } |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 276 | |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 277 | TEST_F(FileCheckTest, ParseExpr) { |
| 278 | PatternTester Tester; |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 279 | |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 280 | // Variable definition. |
| 281 | |
| 282 | // Definition of invalid variable. |
| 283 | EXPECT_TRUE(Tester.parseSubstExpect("10VAR:")); |
| 284 | EXPECT_TRUE(Tester.parseSubstExpect("@FOO:")); |
| 285 | EXPECT_TRUE(Tester.parseSubstExpect("@LINE:")); |
| 286 | |
| 287 | // Garbage after name of variable being defined. |
| 288 | EXPECT_TRUE(Tester.parseSubstExpect("VAR GARBAGE:")); |
| 289 | |
| 290 | // Variable defined to numeric expression. |
| 291 | EXPECT_TRUE(Tester.parseSubstExpect("VAR1: FOO")); |
| 292 | |
| 293 | // Acceptable variable definition. |
| 294 | EXPECT_FALSE(Tester.parseSubstExpect("VAR1:")); |
| 295 | EXPECT_FALSE(Tester.parseSubstExpect(" VAR2:")); |
| 296 | EXPECT_FALSE(Tester.parseSubstExpect("VAR3 :")); |
| 297 | EXPECT_FALSE(Tester.parseSubstExpect("VAR3: ")); |
| 298 | |
| 299 | // Numeric expression. |
| 300 | |
| 301 | // Unacceptable variable. |
| 302 | EXPECT_TRUE(Tester.parseSubstExpect("10VAR")); |
| 303 | EXPECT_TRUE(Tester.parseSubstExpect("@FOO")); |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 304 | |
| 305 | // Only valid variable. |
| 306 | EXPECT_FALSE(Tester.parseSubstExpect("@LINE")); |
| 307 | EXPECT_FALSE(Tester.parseSubstExpect("FOO")); |
Thomas Preud'homme | fe7ac17 | 2019-07-05 16:25:33 +0000 | [diff] [blame] | 308 | EXPECT_FALSE(Tester.parseSubstExpect("UNDEF")); |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 309 | |
| 310 | // Use variable defined on same line. |
| 311 | EXPECT_FALSE(Tester.parsePatternExpect("[[#LINE1VAR:]]")); |
| 312 | EXPECT_TRUE(Tester.parseSubstExpect("LINE1VAR")); |
Thomas Preud'homme | 15cb1f1 | 2019-04-29 17:46:26 +0000 | [diff] [blame] | 313 | |
| 314 | // Unsupported operator. |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 315 | EXPECT_TRUE(Tester.parseSubstExpect("@LINE/2")); |
Thomas Preud'homme | 15cb1f1 | 2019-04-29 17:46:26 +0000 | [diff] [blame] | 316 | |
| 317 | // Missing offset operand. |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 318 | EXPECT_TRUE(Tester.parseSubstExpect("@LINE+")); |
Thomas Preud'homme | 15cb1f1 | 2019-04-29 17:46:26 +0000 | [diff] [blame] | 319 | |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 320 | // Valid expression. |
| 321 | EXPECT_FALSE(Tester.parseSubstExpect("@LINE+5")); |
| 322 | EXPECT_FALSE(Tester.parseSubstExpect("FOO+4")); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 323 | Tester.initNextPattern(); |
| 324 | EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO+FOO]]")); |
| 325 | EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO+3-FOO]]")); |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 326 | } |
| 327 | |
| 328 | TEST_F(FileCheckTest, ParsePattern) { |
| 329 | PatternTester Tester; |
| 330 | |
| 331 | // Space in pattern variable expression. |
| 332 | EXPECT_TRUE(Tester.parsePatternExpect("[[ BAR]]")); |
| 333 | |
| 334 | // Invalid variable name. |
| 335 | EXPECT_TRUE(Tester.parsePatternExpect("[[42INVALID]]")); |
| 336 | |
| 337 | // Invalid pattern variable definition. |
| 338 | EXPECT_TRUE(Tester.parsePatternExpect("[[@PAT:]]")); |
| 339 | EXPECT_TRUE(Tester.parsePatternExpect("[[PAT+2:]]")); |
| 340 | |
| 341 | // Collision with numeric variable. |
| 342 | EXPECT_TRUE(Tester.parsePatternExpect("[[FOO:]]")); |
| 343 | |
| 344 | // Valid use of pattern variable. |
| 345 | EXPECT_FALSE(Tester.parsePatternExpect("[[BAR]]")); |
| 346 | |
| 347 | // Valid pattern variable definition. |
| 348 | EXPECT_FALSE(Tester.parsePatternExpect("[[PAT:[0-9]+]]")); |
| 349 | |
| 350 | // Invalid numeric expressions. |
| 351 | EXPECT_TRUE(Tester.parsePatternExpect("[[#42INVALID]]")); |
| 352 | EXPECT_TRUE(Tester.parsePatternExpect("[[#@FOO]]")); |
| 353 | EXPECT_TRUE(Tester.parsePatternExpect("[[#@LINE/2]]")); |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 354 | EXPECT_TRUE(Tester.parsePatternExpect("[[#YUP:@LINE]]")); |
| 355 | |
| 356 | // Valid numeric expressions and numeric variable definition. |
| 357 | EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO]]")); |
| 358 | EXPECT_FALSE(Tester.parsePatternExpect("[[#@LINE+2]]")); |
| 359 | EXPECT_FALSE(Tester.parsePatternExpect("[[#NUMVAR:]]")); |
| 360 | } |
| 361 | |
| 362 | TEST_F(FileCheckTest, Match) { |
| 363 | PatternTester Tester; |
| 364 | |
| 365 | // Check matching a definition only matches a number. |
| 366 | Tester.parsePatternExpect("[[#NUMVAR:]]"); |
| 367 | EXPECT_TRUE(Tester.matchExpect("FAIL")); |
| 368 | EXPECT_FALSE(Tester.matchExpect("18")); |
| 369 | |
| 370 | // Check matching the variable defined matches the correct number only |
| 371 | Tester.initNextPattern(); |
| 372 | Tester.parsePatternExpect("[[#NUMVAR]] [[#NUMVAR+2]]"); |
| 373 | EXPECT_TRUE(Tester.matchExpect("19 21")); |
| 374 | EXPECT_TRUE(Tester.matchExpect("18 21")); |
| 375 | EXPECT_FALSE(Tester.matchExpect("18 20")); |
Thomas Preud'homme | f6ea43b | 2019-07-10 12:49:17 +0000 | [diff] [blame] | 376 | |
| 377 | // Check matching a numeric expression using @LINE after match failure uses |
| 378 | // the correct value for @LINE. |
| 379 | Tester.initNextPattern(); |
| 380 | EXPECT_FALSE(Tester.parsePatternExpect("[[#@LINE]]")); |
| 381 | // Ok, @LINE is 4 now. |
| 382 | EXPECT_FALSE(Tester.matchExpect("4")); |
| 383 | Tester.initNextPattern(); |
| 384 | // @LINE is now 5, match with substitution failure. |
| 385 | EXPECT_FALSE(Tester.parsePatternExpect("[[#UNKNOWN]]")); |
| 386 | EXPECT_TRUE(Tester.matchExpect("FOO")); |
| 387 | Tester.initNextPattern(); |
| 388 | // Check that @LINE is 6 as expected. |
| 389 | EXPECT_FALSE(Tester.parsePatternExpect("[[#@LINE]]")); |
| 390 | EXPECT_FALSE(Tester.matchExpect("6")); |
Thomas Preud'homme | 15cb1f1 | 2019-04-29 17:46:26 +0000 | [diff] [blame] | 391 | } |
| 392 | |
Thomas Preud'homme | 288ed91 | 2019-05-02 00:04:38 +0000 | [diff] [blame] | 393 | TEST_F(FileCheckTest, Substitution) { |
| 394 | SourceMgr SM; |
| 395 | FileCheckPatternContext Context; |
| 396 | std::vector<std::string> GlobalDefines; |
| 397 | GlobalDefines.emplace_back(std::string("FOO=BAR")); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 398 | EXPECT_FALSE(errorToBool(Context.defineCmdlineVariables(GlobalDefines, SM))); |
Thomas Preud'homme | 288ed91 | 2019-05-02 00:04:38 +0000 | [diff] [blame] | 399 | |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 400 | // Substitution of an undefined string variable fails and error holds that |
| 401 | // variable's name. |
Thomas Preud'homme | f3b9bb3 | 2019-05-23 00:10:29 +0000 | [diff] [blame] | 402 | FileCheckStringSubstitution StringSubstitution = |
| 403 | FileCheckStringSubstitution(&Context, "VAR404", 42); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 404 | Expected<std::string> SubstValue = StringSubstitution.getResult(); |
Thomas Preud'homme | f64b7f6 | 2019-07-10 15:31:19 +0000 | [diff] [blame] | 405 | EXPECT_FALSE(bool(SubstValue)); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 406 | expectUndefError("VAR404", SubstValue.takeError()); |
Thomas Preud'homme | 288ed91 | 2019-05-02 00:04:38 +0000 | [diff] [blame] | 407 | |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 408 | // Substitutions of defined pseudo and non-pseudo numeric variables return |
| 409 | // the right value. |
| 410 | FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 42); |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 411 | FileCheckNumericVariable NVar = FileCheckNumericVariable("N", 10); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 412 | auto LineVarUse = |
| 413 | llvm::make_unique<FileCheckNumericVariableUse>("@LINE", &LineVar); |
| 414 | auto NVarUse = llvm::make_unique<FileCheckNumericVariableUse>("N", &NVar); |
| 415 | FileCheckNumericSubstitution SubstitutionLine = FileCheckNumericSubstitution( |
| 416 | &Context, "@LINE", std::move(LineVarUse), 12); |
Thomas Preud'homme | f3b9bb3 | 2019-05-23 00:10:29 +0000 | [diff] [blame] | 417 | FileCheckNumericSubstitution SubstitutionN = |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 418 | FileCheckNumericSubstitution(&Context, "N", std::move(NVarUse), 30); |
| 419 | SubstValue = SubstitutionLine.getResult(); |
| 420 | EXPECT_TRUE(bool(SubstValue)); |
| 421 | EXPECT_EQ("42", *SubstValue); |
| 422 | SubstValue = SubstitutionN.getResult(); |
| 423 | EXPECT_TRUE(bool(SubstValue)); |
| 424 | EXPECT_EQ("10", *SubstValue); |
Thomas Preud'homme | 288ed91 | 2019-05-02 00:04:38 +0000 | [diff] [blame] | 425 | |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 426 | // Substitution of an undefined numeric variable fails, error holds name of |
| 427 | // undefined variable. |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 428 | LineVar.clearValue(); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 429 | SubstValue = SubstitutionLine.getResult(); |
Thomas Preud'homme | f64b7f6 | 2019-07-10 15:31:19 +0000 | [diff] [blame] | 430 | EXPECT_FALSE(bool(SubstValue)); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 431 | expectUndefError("@LINE", SubstValue.takeError()); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 432 | NVar.clearValue(); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 433 | SubstValue = SubstitutionN.getResult(); |
Thomas Preud'homme | f64b7f6 | 2019-07-10 15:31:19 +0000 | [diff] [blame] | 434 | EXPECT_FALSE(bool(SubstValue)); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 435 | expectUndefError("N", SubstValue.takeError()); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 436 | |
Thomas Preud'homme | 1a944d2 | 2019-05-23 00:10:14 +0000 | [diff] [blame] | 437 | // Substitution of a defined string variable returns the right value. |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 438 | FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Context, 1); |
Thomas Preud'homme | f3b9bb3 | 2019-05-23 00:10:29 +0000 | [diff] [blame] | 439 | StringSubstitution = FileCheckStringSubstitution(&Context, "FOO", 42); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 440 | SubstValue = StringSubstitution.getResult(); |
| 441 | EXPECT_TRUE(bool(SubstValue)); |
| 442 | EXPECT_EQ("BAR", *SubstValue); |
Thomas Preud'homme | 288ed91 | 2019-05-02 00:04:38 +0000 | [diff] [blame] | 443 | } |
| 444 | |
Thomas Preud'homme | 5a33047 | 2019-04-29 13:32:36 +0000 | [diff] [blame] | 445 | TEST_F(FileCheckTest, FileCheckContext) { |
| 446 | FileCheckPatternContext Cxt = FileCheckPatternContext(); |
| 447 | std::vector<std::string> GlobalDefines; |
| 448 | SourceMgr SM; |
| 449 | |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 450 | // Missing equal sign. |
Thomas Preud'homme | 5a33047 | 2019-04-29 13:32:36 +0000 | [diff] [blame] | 451 | GlobalDefines.emplace_back(std::string("LocalVar")); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 452 | EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM))); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 453 | GlobalDefines.clear(); |
| 454 | GlobalDefines.emplace_back(std::string("#LocalNumVar")); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 455 | EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM))); |
Thomas Preud'homme | 5a33047 | 2019-04-29 13:32:36 +0000 | [diff] [blame] | 456 | |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 457 | // Empty variable name. |
Thomas Preud'homme | 5a33047 | 2019-04-29 13:32:36 +0000 | [diff] [blame] | 458 | GlobalDefines.clear(); |
| 459 | GlobalDefines.emplace_back(std::string("=18")); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 460 | EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM))); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 461 | GlobalDefines.clear(); |
| 462 | GlobalDefines.emplace_back(std::string("#=18")); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 463 | EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM))); |
Thomas Preud'homme | 5a33047 | 2019-04-29 13:32:36 +0000 | [diff] [blame] | 464 | |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 465 | // Invalid variable name. |
Thomas Preud'homme | 5a33047 | 2019-04-29 13:32:36 +0000 | [diff] [blame] | 466 | GlobalDefines.clear(); |
| 467 | GlobalDefines.emplace_back(std::string("18LocalVar=18")); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 468 | EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM))); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 469 | GlobalDefines.clear(); |
| 470 | GlobalDefines.emplace_back(std::string("#18LocalNumVar=18")); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 471 | EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM))); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 472 | |
| 473 | // Name conflict between pattern and numeric variable. |
| 474 | GlobalDefines.clear(); |
| 475 | GlobalDefines.emplace_back(std::string("LocalVar=18")); |
| 476 | GlobalDefines.emplace_back(std::string("#LocalVar=36")); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 477 | EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM))); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 478 | Cxt = FileCheckPatternContext(); |
| 479 | GlobalDefines.clear(); |
| 480 | GlobalDefines.emplace_back(std::string("#LocalNumVar=18")); |
| 481 | GlobalDefines.emplace_back(std::string("LocalNumVar=36")); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 482 | EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM))); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 483 | Cxt = FileCheckPatternContext(); |
| 484 | |
| 485 | // Invalid numeric value for numeric variable. |
| 486 | GlobalDefines.clear(); |
| 487 | GlobalDefines.emplace_back(std::string("#LocalNumVar=x")); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 488 | EXPECT_TRUE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM))); |
Thomas Preud'homme | 5a33047 | 2019-04-29 13:32:36 +0000 | [diff] [blame] | 489 | |
| 490 | // Define local variables from command-line. |
| 491 | GlobalDefines.clear(); |
Thomas Preud'homme | e038fa7 | 2019-04-15 10:10:11 +0000 | [diff] [blame] | 492 | GlobalDefines.emplace_back(std::string("LocalVar=FOO")); |
Thomas Preud'homme | 5a33047 | 2019-04-29 13:32:36 +0000 | [diff] [blame] | 493 | GlobalDefines.emplace_back(std::string("EmptyVar=")); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 494 | GlobalDefines.emplace_back(std::string("#LocalNumVar=18")); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 495 | EXPECT_FALSE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM))); |
Thomas Preud'homme | e038fa7 | 2019-04-15 10:10:11 +0000 | [diff] [blame] | 496 | |
| 497 | // Check defined variables are present and undefined is absent. |
| 498 | StringRef LocalVarStr = "LocalVar"; |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 499 | StringRef LocalNumVarRef = bufferize(SM, "LocalNumVar"); |
Thomas Preud'homme | 5a33047 | 2019-04-29 13:32:36 +0000 | [diff] [blame] | 500 | StringRef EmptyVarStr = "EmptyVar"; |
Thomas Preud'homme | e038fa7 | 2019-04-15 10:10:11 +0000 | [diff] [blame] | 501 | StringRef UnknownVarStr = "UnknownVar"; |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 502 | Expected<StringRef> LocalVar = Cxt.getPatternVarValue(LocalVarStr); |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 503 | FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Cxt, 1); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 504 | Optional<FileCheckNumericVariable *> DefinedNumericVariable; |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 505 | Expected<std::unique_ptr<FileCheckExpressionAST>> ExpressionAST = |
| 506 | P.parseNumericSubstitutionBlock(LocalNumVarRef, DefinedNumericVariable, |
| 507 | /*IsLegacyLineExpr=*/false, SM); |
Thomas Preud'homme | f64b7f6 | 2019-07-10 15:31:19 +0000 | [diff] [blame] | 508 | EXPECT_TRUE(bool(LocalVar)); |
Thomas Preud'homme | e038fa7 | 2019-04-15 10:10:11 +0000 | [diff] [blame] | 509 | EXPECT_EQ(*LocalVar, "FOO"); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 510 | Expected<StringRef> EmptyVar = Cxt.getPatternVarValue(EmptyVarStr); |
| 511 | Expected<StringRef> UnknownVar = Cxt.getPatternVarValue(UnknownVarStr); |
| 512 | EXPECT_TRUE(bool(ExpressionAST)); |
| 513 | Expected<uint64_t> ExpressionVal = (*ExpressionAST)->eval(); |
Thomas Preud'homme | f64b7f6 | 2019-07-10 15:31:19 +0000 | [diff] [blame] | 514 | EXPECT_TRUE(bool(ExpressionVal)); |
Thomas Preud'homme | a2ef1ba | 2019-06-19 23:47:24 +0000 | [diff] [blame] | 515 | EXPECT_EQ(*ExpressionVal, 18U); |
Thomas Preud'homme | f64b7f6 | 2019-07-10 15:31:19 +0000 | [diff] [blame] | 516 | EXPECT_TRUE(bool(EmptyVar)); |
Thomas Preud'homme | 5a33047 | 2019-04-29 13:32:36 +0000 | [diff] [blame] | 517 | EXPECT_EQ(*EmptyVar, ""); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 518 | EXPECT_TRUE(errorToBool(UnknownVar.takeError())); |
Thomas Preud'homme | e038fa7 | 2019-04-15 10:10:11 +0000 | [diff] [blame] | 519 | |
| 520 | // Clear local variables and check they become absent. |
| 521 | Cxt.clearLocalVars(); |
Thomas Preud'homme | 288ed91 | 2019-05-02 00:04:38 +0000 | [diff] [blame] | 522 | LocalVar = Cxt.getPatternVarValue(LocalVarStr); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 523 | EXPECT_TRUE(errorToBool(LocalVar.takeError())); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 524 | // Check a numeric expression's evaluation fails if called after clearing of |
| 525 | // local variables, if it was created before. This is important because local |
| 526 | // variable clearing due to --enable-var-scope happens after numeric |
| 527 | // expressions are linked to the numeric variables they use. |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 528 | EXPECT_TRUE(errorToBool((*ExpressionAST)->eval().takeError())); |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 529 | P = FileCheckPattern(Check::CheckPlain, &Cxt, 2); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 530 | ExpressionAST = P.parseNumericSubstitutionBlock( |
| 531 | LocalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, SM); |
| 532 | EXPECT_TRUE(bool(ExpressionAST)); |
| 533 | ExpressionVal = (*ExpressionAST)->eval(); |
Thomas Preud'homme | fe7ac17 | 2019-07-05 16:25:33 +0000 | [diff] [blame] | 534 | EXPECT_TRUE(errorToBool(ExpressionVal.takeError())); |
Thomas Preud'homme | 288ed91 | 2019-05-02 00:04:38 +0000 | [diff] [blame] | 535 | EmptyVar = Cxt.getPatternVarValue(EmptyVarStr); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 536 | EXPECT_TRUE(errorToBool(EmptyVar.takeError())); |
Thomas Preud'homme | fe7ac17 | 2019-07-05 16:25:33 +0000 | [diff] [blame] | 537 | // Clear again because parseNumericSubstitutionBlock would have created a |
| 538 | // dummy variable and stored it in GlobalNumericVariableTable. |
| 539 | Cxt.clearLocalVars(); |
Thomas Preud'homme | e038fa7 | 2019-04-15 10:10:11 +0000 | [diff] [blame] | 540 | |
| 541 | // Redefine global variables and check variables are defined again. |
| 542 | GlobalDefines.emplace_back(std::string("$GlobalVar=BAR")); |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 543 | GlobalDefines.emplace_back(std::string("#$GlobalNumVar=36")); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 544 | EXPECT_FALSE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM))); |
Thomas Preud'homme | e038fa7 | 2019-04-15 10:10:11 +0000 | [diff] [blame] | 545 | StringRef GlobalVarStr = "$GlobalVar"; |
Thomas Preud'homme | 7b4ecdd | 2019-05-14 11:58:30 +0000 | [diff] [blame] | 546 | StringRef GlobalNumVarRef = bufferize(SM, "$GlobalNumVar"); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 547 | Expected<StringRef> GlobalVar = Cxt.getPatternVarValue(GlobalVarStr); |
Thomas Preud'homme | f64b7f6 | 2019-07-10 15:31:19 +0000 | [diff] [blame] | 548 | EXPECT_TRUE(bool(GlobalVar)); |
Thomas Preud'homme | e038fa7 | 2019-04-15 10:10:11 +0000 | [diff] [blame] | 549 | EXPECT_EQ(*GlobalVar, "BAR"); |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 550 | P = FileCheckPattern(Check::CheckPlain, &Cxt, 3); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 551 | ExpressionAST = P.parseNumericSubstitutionBlock( |
| 552 | GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, SM); |
| 553 | EXPECT_TRUE(bool(ExpressionAST)); |
| 554 | ExpressionVal = (*ExpressionAST)->eval(); |
Thomas Preud'homme | f64b7f6 | 2019-07-10 15:31:19 +0000 | [diff] [blame] | 555 | EXPECT_TRUE(bool(ExpressionVal)); |
Thomas Preud'homme | a2ef1ba | 2019-06-19 23:47:24 +0000 | [diff] [blame] | 556 | EXPECT_EQ(*ExpressionVal, 36U); |
Thomas Preud'homme | e038fa7 | 2019-04-15 10:10:11 +0000 | [diff] [blame] | 557 | |
| 558 | // Clear local variables and check global variables remain defined. |
| 559 | Cxt.clearLocalVars(); |
Thomas Preud'homme | baae41f | 2019-06-19 23:47:10 +0000 | [diff] [blame] | 560 | EXPECT_FALSE(errorToBool(Cxt.getPatternVarValue(GlobalVarStr).takeError())); |
Thomas Preud'homme | 71d3f22 | 2019-06-06 13:21:06 +0000 | [diff] [blame] | 561 | P = FileCheckPattern(Check::CheckPlain, &Cxt, 4); |
Thomas Preud'homme | 2a7f520 | 2019-07-13 13:24:30 +0000 | [diff] [blame^] | 562 | ExpressionAST = P.parseNumericSubstitutionBlock( |
| 563 | GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, SM); |
| 564 | EXPECT_TRUE(bool(ExpressionAST)); |
| 565 | ExpressionVal = (*ExpressionAST)->eval(); |
Thomas Preud'homme | f64b7f6 | 2019-07-10 15:31:19 +0000 | [diff] [blame] | 566 | EXPECT_TRUE(bool(ExpressionVal)); |
Thomas Preud'homme | a2ef1ba | 2019-06-19 23:47:24 +0000 | [diff] [blame] | 567 | EXPECT_EQ(*ExpressionVal, 36U); |
Thomas Preud'homme | e038fa7 | 2019-04-15 10:10:11 +0000 | [diff] [blame] | 568 | } |
| 569 | } // namespace |