FileCheckTest.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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. #include "llvm/Support/FileCheck.h"
  9. #include "gtest/gtest.h"
  10. using namespace llvm;
  11. namespace {
  12. class FileCheckTest : public ::testing::Test {};
  13. TEST_F(FileCheckTest, NumericVariable) {
  14. FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 42);
  15. EXPECT_EQ("FOO", FooVar.getName());
  16. // Defined variable: getValue returns a value, setValue fails and value
  17. // remains unchanged.
  18. llvm::Optional<uint64_t> Value = FooVar.getValue();
  19. EXPECT_TRUE(Value);
  20. EXPECT_EQ(42U, *Value);
  21. EXPECT_TRUE(FooVar.setValue(43));
  22. Value = FooVar.getValue();
  23. EXPECT_TRUE(Value);
  24. EXPECT_EQ(42U, *Value);
  25. // Clearing variable: getValue fails, clearValue again fails.
  26. EXPECT_FALSE(FooVar.clearValue());
  27. Value = FooVar.getValue();
  28. EXPECT_FALSE(Value);
  29. EXPECT_TRUE(FooVar.clearValue());
  30. // Undefined variable: setValue works, getValue returns value set.
  31. EXPECT_FALSE(FooVar.setValue(43));
  32. Value = FooVar.getValue();
  33. EXPECT_TRUE(Value);
  34. EXPECT_EQ(43U, *Value);
  35. }
  36. uint64_t doAdd(uint64_t OpL, uint64_t OpR) { return OpL + OpR; }
  37. TEST_F(FileCheckTest, NumExpr) {
  38. FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 42);
  39. FileCheckNumExpr NumExpr = FileCheckNumExpr(doAdd, &FooVar, 18);
  40. // Defined variable: eval returns right value, no undefined variable
  41. // returned.
  42. llvm::Optional<uint64_t> Value = NumExpr.eval();
  43. EXPECT_TRUE(Value);
  44. EXPECT_EQ(60U, *Value);
  45. StringRef UndefVar = NumExpr.getUndefVarName();
  46. EXPECT_EQ("", UndefVar);
  47. // Undefined variable: eval fails, undefined variable returned. We call
  48. // getUndefVarName first to check that it can be called without calling
  49. // eval() first.
  50. FooVar.clearValue();
  51. UndefVar = NumExpr.getUndefVarName();
  52. EXPECT_EQ("FOO", UndefVar);
  53. Value = NumExpr.eval();
  54. EXPECT_FALSE(Value);
  55. }
  56. TEST_F(FileCheckTest, ValidVarNameStart) {
  57. EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('a'));
  58. EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('G'));
  59. EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('_'));
  60. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('2'));
  61. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('$'));
  62. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('@'));
  63. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('+'));
  64. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('-'));
  65. EXPECT_FALSE(FileCheckPattern::isValidVarNameStart(':'));
  66. }
  67. TEST_F(FileCheckTest, ParseVar) {
  68. StringRef VarName = "GoodVar42";
  69. bool IsPseudo = true;
  70. unsigned TrailIdx = 0;
  71. EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
  72. EXPECT_FALSE(IsPseudo);
  73. EXPECT_EQ(TrailIdx, VarName.size());
  74. VarName = "$GoodGlobalVar";
  75. IsPseudo = true;
  76. TrailIdx = 0;
  77. EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
  78. EXPECT_FALSE(IsPseudo);
  79. EXPECT_EQ(TrailIdx, VarName.size());
  80. VarName = "@GoodPseudoVar";
  81. IsPseudo = true;
  82. TrailIdx = 0;
  83. EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
  84. EXPECT_TRUE(IsPseudo);
  85. EXPECT_EQ(TrailIdx, VarName.size());
  86. VarName = "42BadVar";
  87. EXPECT_TRUE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
  88. VarName = "$@";
  89. EXPECT_TRUE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
  90. VarName = "B@dVar";
  91. IsPseudo = true;
  92. TrailIdx = 0;
  93. EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
  94. EXPECT_FALSE(IsPseudo);
  95. EXPECT_EQ(TrailIdx, 1U);
  96. VarName = "B$dVar";
  97. IsPseudo = true;
  98. TrailIdx = 0;
  99. EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
  100. EXPECT_FALSE(IsPseudo);
  101. EXPECT_EQ(TrailIdx, 1U);
  102. VarName = "BadVar+";
  103. IsPseudo = true;
  104. TrailIdx = 0;
  105. EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
  106. EXPECT_FALSE(IsPseudo);
  107. EXPECT_EQ(TrailIdx, VarName.size() - 1);
  108. VarName = "BadVar-";
  109. IsPseudo = true;
  110. TrailIdx = 0;
  111. EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
  112. EXPECT_FALSE(IsPseudo);
  113. EXPECT_EQ(TrailIdx, VarName.size() - 1);
  114. VarName = "BadVar:";
  115. IsPseudo = true;
  116. TrailIdx = 0;
  117. EXPECT_FALSE(FileCheckPattern::parseVariable(VarName, IsPseudo, TrailIdx));
  118. EXPECT_FALSE(IsPseudo);
  119. EXPECT_EQ(TrailIdx, VarName.size() - 1);
  120. }
  121. static StringRef bufferize(SourceMgr &SM, StringRef Str) {
  122. std::unique_ptr<MemoryBuffer> Buffer =
  123. MemoryBuffer::getMemBufferCopy(Str, "TestBuffer");
  124. StringRef StrBufferRef = Buffer->getBuffer();
  125. SM.AddNewSourceBuffer(std::move(Buffer), SMLoc());
  126. return StrBufferRef;
  127. }
  128. class ExprTester {
  129. private:
  130. SourceMgr SM;
  131. FileCheckRequest Req;
  132. FileCheckPatternContext Context;
  133. FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Context);
  134. public:
  135. ExprTester() {
  136. std::vector<std::string> GlobalDefines;
  137. GlobalDefines.emplace_back(std::string("#FOO=42"));
  138. Context.defineCmdlineVariables(GlobalDefines, SM);
  139. // Call ParsePattern to have @LINE defined.
  140. P.ParsePattern("N/A", "CHECK", SM, 1, Req);
  141. }
  142. bool parseExpect(std::string &VarName, std::string &Trailer) {
  143. bool IsPseudo = VarName[0] == '@';
  144. std::string NameTrailer = VarName + Trailer;
  145. StringRef NameTrailerRef = bufferize(SM, NameTrailer);
  146. StringRef VarNameRef = NameTrailerRef.substr(0, VarName.size());
  147. StringRef TrailerRef = NameTrailerRef.substr(VarName.size());
  148. return P.parseNumericSubstitution(VarNameRef, IsPseudo, TrailerRef, SM) ==
  149. nullptr;
  150. }
  151. };
  152. TEST_F(FileCheckTest, ParseExpr) {
  153. ExprTester Tester;
  154. // @LINE with offset.
  155. std::string VarName = "@LINE";
  156. std::string Trailer = "+3";
  157. EXPECT_FALSE(Tester.parseExpect(VarName, Trailer));
  158. // @LINE only.
  159. Trailer = "";
  160. EXPECT_FALSE(Tester.parseExpect(VarName, Trailer));
  161. // Defined variable.
  162. VarName = "FOO";
  163. EXPECT_FALSE(Tester.parseExpect(VarName, Trailer));
  164. // Undefined variable.
  165. VarName = "UNDEF";
  166. EXPECT_TRUE(Tester.parseExpect(VarName, Trailer));
  167. // Wrong Pseudovar.
  168. VarName = "@FOO";
  169. EXPECT_TRUE(Tester.parseExpect(VarName, Trailer));
  170. // Unsupported operator.
  171. VarName = "@LINE";
  172. Trailer = "/2";
  173. EXPECT_TRUE(Tester.parseExpect(VarName, Trailer));
  174. // Missing offset operand.
  175. VarName = "@LINE";
  176. Trailer = "+";
  177. EXPECT_TRUE(Tester.parseExpect(VarName, Trailer));
  178. // Cannot parse offset operand.
  179. VarName = "@LINE";
  180. Trailer = "+x";
  181. EXPECT_TRUE(Tester.parseExpect(VarName, Trailer));
  182. // Unexpected string at end of numeric expression.
  183. VarName = "@LINE";
  184. Trailer = "+5x";
  185. EXPECT_TRUE(Tester.parseExpect(VarName, Trailer));
  186. }
  187. TEST_F(FileCheckTest, Substitution) {
  188. SourceMgr SM;
  189. FileCheckPatternContext Context;
  190. std::vector<std::string> GlobalDefines;
  191. GlobalDefines.emplace_back(std::string("FOO=BAR"));
  192. Context.defineCmdlineVariables(GlobalDefines, SM);
  193. // Substitution of an undefined string variable fails.
  194. FileCheckStringSubstitution StringSubstitution =
  195. FileCheckStringSubstitution(&Context, "VAR404", 42);
  196. EXPECT_FALSE(StringSubstitution.getResult());
  197. // Substitutions of defined pseudo and non-pseudo numeric variables return
  198. // the right value.
  199. FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 42);
  200. FileCheckNumericVariable NVar = FileCheckNumericVariable("@N", 10);
  201. FileCheckNumExpr NumExprLine = FileCheckNumExpr(doAdd, &LineVar, 0);
  202. FileCheckNumExpr NumExprN = FileCheckNumExpr(doAdd, &NVar, 3);
  203. FileCheckNumericSubstitution SubstitutionLine =
  204. FileCheckNumericSubstitution(&Context, "@LINE", &NumExprLine, 12);
  205. FileCheckNumericSubstitution SubstitutionN =
  206. FileCheckNumericSubstitution(&Context, "N", &NumExprN, 30);
  207. llvm::Optional<std::string> Value = SubstitutionLine.getResult();
  208. EXPECT_TRUE(Value);
  209. EXPECT_EQ("42", *Value);
  210. Value = SubstitutionN.getResult();
  211. EXPECT_TRUE(Value);
  212. EXPECT_EQ("13", *Value);
  213. // Substitution of an undefined numeric variable fails.
  214. LineVar.clearValue();
  215. EXPECT_FALSE(SubstitutionLine.getResult());
  216. NVar.clearValue();
  217. EXPECT_FALSE(SubstitutionN.getResult());
  218. // Substitution of a defined string variable returns the right value.
  219. FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Context);
  220. StringSubstitution = FileCheckStringSubstitution(&Context, "FOO", 42);
  221. Value = StringSubstitution.getResult();
  222. EXPECT_TRUE(Value);
  223. EXPECT_EQ("BAR", *Value);
  224. }
  225. TEST_F(FileCheckTest, UndefVars) {
  226. SourceMgr SM;
  227. FileCheckPatternContext Context;
  228. std::vector<std::string> GlobalDefines;
  229. GlobalDefines.emplace_back(std::string("FOO=BAR"));
  230. Context.defineCmdlineVariables(GlobalDefines, SM);
  231. // getUndefVarName() on a string substitution with an undefined variable
  232. // returns that variable.
  233. FileCheckStringSubstitution StringSubstitution =
  234. FileCheckStringSubstitution(&Context, "VAR404", 42);
  235. StringRef UndefVar = StringSubstitution.getUndefVarName();
  236. EXPECT_EQ("VAR404", UndefVar);
  237. // getUndefVarName() on a string substitution with a defined variable returns
  238. // an empty string.
  239. StringSubstitution = FileCheckStringSubstitution(&Context, "FOO", 42);
  240. UndefVar = StringSubstitution.getUndefVarName();
  241. EXPECT_EQ("", UndefVar);
  242. // getUndefVarName() on a numeric substitution with a defined variable
  243. // returns an empty string.
  244. FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 42);
  245. FileCheckNumExpr NumExpr = FileCheckNumExpr(doAdd, &LineVar, 0);
  246. FileCheckNumericSubstitution NumericSubstitution =
  247. FileCheckNumericSubstitution(&Context, "@LINE", &NumExpr, 12);
  248. UndefVar = NumericSubstitution.getUndefVarName();
  249. EXPECT_EQ("", UndefVar);
  250. // getUndefVarName() on a numeric substitution with an undefined variable
  251. // returns that variable.
  252. LineVar.clearValue();
  253. UndefVar = NumericSubstitution.getUndefVarName();
  254. EXPECT_EQ("@LINE", UndefVar);
  255. }
  256. TEST_F(FileCheckTest, FileCheckContext) {
  257. FileCheckPatternContext Cxt = FileCheckPatternContext();
  258. std::vector<std::string> GlobalDefines;
  259. SourceMgr SM;
  260. // Missing equal sign.
  261. GlobalDefines.emplace_back(std::string("LocalVar"));
  262. EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
  263. GlobalDefines.clear();
  264. GlobalDefines.emplace_back(std::string("#LocalNumVar"));
  265. EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
  266. // Empty variable name.
  267. GlobalDefines.clear();
  268. GlobalDefines.emplace_back(std::string("=18"));
  269. EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
  270. GlobalDefines.clear();
  271. GlobalDefines.emplace_back(std::string("#=18"));
  272. EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
  273. // Invalid variable name.
  274. GlobalDefines.clear();
  275. GlobalDefines.emplace_back(std::string("18LocalVar=18"));
  276. EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
  277. GlobalDefines.clear();
  278. GlobalDefines.emplace_back(std::string("#18LocalNumVar=18"));
  279. EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
  280. // Name conflict between pattern and numeric variable.
  281. GlobalDefines.clear();
  282. GlobalDefines.emplace_back(std::string("LocalVar=18"));
  283. GlobalDefines.emplace_back(std::string("#LocalVar=36"));
  284. EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
  285. Cxt = FileCheckPatternContext();
  286. GlobalDefines.clear();
  287. GlobalDefines.emplace_back(std::string("#LocalNumVar=18"));
  288. GlobalDefines.emplace_back(std::string("LocalNumVar=36"));
  289. EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
  290. Cxt = FileCheckPatternContext();
  291. // Invalid numeric value for numeric variable.
  292. GlobalDefines.clear();
  293. GlobalDefines.emplace_back(std::string("#LocalNumVar=x"));
  294. EXPECT_TRUE(Cxt.defineCmdlineVariables(GlobalDefines, SM));
  295. // Define local variables from command-line.
  296. GlobalDefines.clear();
  297. GlobalDefines.emplace_back(std::string("LocalVar=FOO"));
  298. GlobalDefines.emplace_back(std::string("EmptyVar="));
  299. GlobalDefines.emplace_back(std::string("#LocalNumVar=18"));
  300. bool GotError = Cxt.defineCmdlineVariables(GlobalDefines, SM);
  301. EXPECT_FALSE(GotError);
  302. // Check defined variables are present and undefined is absent.
  303. StringRef LocalVarStr = "LocalVar";
  304. StringRef LocalNumVarRef = bufferize(SM, "LocalNumVar");
  305. StringRef EmptyVarStr = "EmptyVar";
  306. StringRef UnknownVarStr = "UnknownVar";
  307. llvm::Optional<StringRef> LocalVar = Cxt.getPatternVarValue(LocalVarStr);
  308. FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Cxt);
  309. FileCheckNumExpr *NumExpr =
  310. P.parseNumericSubstitution(LocalNumVarRef, false /*IsPseudo*/, "", SM);
  311. llvm::Optional<StringRef> EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
  312. llvm::Optional<StringRef> UnknownVar = Cxt.getPatternVarValue(UnknownVarStr);
  313. EXPECT_TRUE(LocalVar);
  314. EXPECT_EQ(*LocalVar, "FOO");
  315. EXPECT_TRUE(NumExpr);
  316. llvm::Optional<uint64_t> NumExprVal = NumExpr->eval();
  317. EXPECT_TRUE(NumExprVal);
  318. EXPECT_EQ(*NumExprVal, 18U);
  319. EXPECT_TRUE(EmptyVar);
  320. EXPECT_EQ(*EmptyVar, "");
  321. EXPECT_FALSE(UnknownVar);
  322. // Clear local variables and check they become absent.
  323. Cxt.clearLocalVars();
  324. LocalVar = Cxt.getPatternVarValue(LocalVarStr);
  325. EXPECT_FALSE(LocalVar);
  326. // Check a numeric expression's evaluation fails if called after clearing of
  327. // local variables, if it was created before. This is important because local
  328. // variable clearing due to --enable-var-scope happens after numeric
  329. // expressions are linked to the numeric variables they use.
  330. EXPECT_FALSE(NumExpr->eval());
  331. P = FileCheckPattern(Check::CheckPlain, &Cxt);
  332. NumExpr =
  333. P.parseNumericSubstitution(LocalNumVarRef, false /*IsPseudo*/, "", SM);
  334. EXPECT_FALSE(NumExpr);
  335. EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
  336. EXPECT_FALSE(EmptyVar);
  337. // Redefine global variables and check variables are defined again.
  338. GlobalDefines.emplace_back(std::string("$GlobalVar=BAR"));
  339. GlobalDefines.emplace_back(std::string("#$GlobalNumVar=36"));
  340. GotError = Cxt.defineCmdlineVariables(GlobalDefines, SM);
  341. EXPECT_FALSE(GotError);
  342. StringRef GlobalVarStr = "$GlobalVar";
  343. StringRef GlobalNumVarRef = bufferize(SM, "$GlobalNumVar");
  344. llvm::Optional<StringRef> GlobalVar = Cxt.getPatternVarValue(GlobalVarStr);
  345. EXPECT_TRUE(GlobalVar);
  346. EXPECT_EQ(*GlobalVar, "BAR");
  347. P = FileCheckPattern(Check::CheckPlain, &Cxt);
  348. NumExpr =
  349. P.parseNumericSubstitution(GlobalNumVarRef, false /*IsPseudo*/, "", SM);
  350. EXPECT_TRUE(NumExpr);
  351. NumExprVal = NumExpr->eval();
  352. EXPECT_TRUE(NumExprVal);
  353. EXPECT_EQ(*NumExprVal, 36U);
  354. // Clear local variables and check global variables remain defined.
  355. Cxt.clearLocalVars();
  356. GlobalVar = Cxt.getPatternVarValue(GlobalVarStr);
  357. EXPECT_TRUE(GlobalVar);
  358. P = FileCheckPattern(Check::CheckPlain, &Cxt);
  359. NumExpr =
  360. P.parseNumericSubstitution(GlobalNumVarRef, false /*IsPseudo*/, "", SM);
  361. EXPECT_TRUE(NumExpr);
  362. NumExprVal = NumExpr->eval();
  363. EXPECT_TRUE(NumExprVal);
  364. EXPECT_EQ(*NumExprVal, 36U);
  365. }
  366. } // namespace