GtestMatchers.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. //===- GtestMatchers.cpp - AST Matchers for Gtest ---------------*- C++ -*-===//
  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. // This file implements several matchers for popular gtest macros. In general,
  10. // AST matchers cannot match calls to macros. However, we can simulate such
  11. // matches if the macro definition has identifiable elements that themselves can
  12. // be matched. In that case, we can match on those elements and then check that
  13. // the match occurs within an expansion of the desired macro. The more uncommon
  14. // the identified elements, the more efficient this process will be.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #include "clang/ASTMatchers/GtestMatchers.h"
  18. #include "clang/AST/ASTConsumer.h"
  19. #include "clang/AST/ASTContext.h"
  20. #include "clang/AST/RecursiveASTVisitor.h"
  21. #include "clang/ASTMatchers/ASTMatchFinder.h"
  22. #include "llvm/ADT/DenseMap.h"
  23. #include "llvm/ADT/StringMap.h"
  24. #include "llvm/ADT/StringRef.h"
  25. namespace clang {
  26. namespace ast_matchers {
  27. namespace {
  28. enum class MacroType {
  29. Expect,
  30. Assert,
  31. On,
  32. };
  33. } // namespace
  34. static DeclarationMatcher getComparisonDecl(GtestCmp Cmp) {
  35. switch (Cmp) {
  36. case GtestCmp::Eq:
  37. return cxxMethodDecl(hasName("Compare"),
  38. ofClass(cxxRecordDecl(isSameOrDerivedFrom(
  39. hasName("::testing::internal::EqHelper")))));
  40. case GtestCmp::Ne:
  41. return functionDecl(hasName("::testing::internal::CmpHelperNE"));
  42. case GtestCmp::Ge:
  43. return functionDecl(hasName("::testing::internal::CmpHelperGE"));
  44. case GtestCmp::Gt:
  45. return functionDecl(hasName("::testing::internal::CmpHelperGT"));
  46. case GtestCmp::Le:
  47. return functionDecl(hasName("::testing::internal::CmpHelperLE"));
  48. case GtestCmp::Lt:
  49. return functionDecl(hasName("::testing::internal::CmpHelperLT"));
  50. }
  51. llvm_unreachable("Unhandled GtestCmp enum");
  52. }
  53. static llvm::StringRef getMacroTypeName(MacroType Macro) {
  54. switch (Macro) {
  55. case MacroType::Expect:
  56. return "EXPECT";
  57. case MacroType::Assert:
  58. return "ASSERT";
  59. case MacroType::On:
  60. return "ON";
  61. }
  62. llvm_unreachable("Unhandled MacroType enum");
  63. }
  64. static llvm::StringRef getComparisonTypeName(GtestCmp Cmp) {
  65. switch (Cmp) {
  66. case GtestCmp::Eq:
  67. return "EQ";
  68. case GtestCmp::Ne:
  69. return "NE";
  70. case GtestCmp::Ge:
  71. return "GE";
  72. case GtestCmp::Gt:
  73. return "GT";
  74. case GtestCmp::Le:
  75. return "LE";
  76. case GtestCmp::Lt:
  77. return "LT";
  78. }
  79. llvm_unreachable("Unhandled GtestCmp enum");
  80. }
  81. static std::string getMacroName(MacroType Macro, GtestCmp Cmp) {
  82. return (getMacroTypeName(Macro) + "_" + getComparisonTypeName(Cmp)).str();
  83. }
  84. static std::string getMacroName(MacroType Macro, llvm::StringRef Operation) {
  85. return (getMacroTypeName(Macro) + "_" + Operation).str();
  86. }
  87. // Under the hood, ON_CALL is expanded to a call to `InternalDefaultActionSetAt`
  88. // to set a default action spec to the underlying function mocker, while
  89. // EXPECT_CALL is expanded to a call to `InternalExpectedAt` to set a new
  90. // expectation spec.
  91. static llvm::StringRef getSpecSetterName(MacroType Macro) {
  92. switch (Macro) {
  93. case MacroType::On:
  94. return "InternalDefaultActionSetAt";
  95. case MacroType::Expect:
  96. return "InternalExpectedAt";
  97. default:
  98. llvm_unreachable("Unhandled MacroType enum");
  99. }
  100. llvm_unreachable("Unhandled MacroType enum");
  101. }
  102. // In general, AST matchers cannot match calls to macros. However, we can
  103. // simulate such matches if the macro definition has identifiable elements that
  104. // themselves can be matched. In that case, we can match on those elements and
  105. // then check that the match occurs within an expansion of the desired
  106. // macro. The more uncommon the identified elements, the more efficient this
  107. // process will be.
  108. //
  109. // We use this approach to implement the derived matchers gtestAssert and
  110. // gtestExpect.
  111. static internal::BindableMatcher<Stmt>
  112. gtestComparisonInternal(MacroType Macro, GtestCmp Cmp, StatementMatcher Left,
  113. StatementMatcher Right) {
  114. return callExpr(isExpandedFromMacro(getMacroName(Macro, Cmp)),
  115. callee(getComparisonDecl(Cmp)), hasArgument(2, Left),
  116. hasArgument(3, Right));
  117. }
  118. static internal::BindableMatcher<Stmt>
  119. gtestThatInternal(MacroType Macro, StatementMatcher Actual,
  120. StatementMatcher Matcher) {
  121. return cxxOperatorCallExpr(
  122. isExpandedFromMacro(getMacroName(Macro, "THAT")),
  123. hasOverloadedOperatorName("()"), hasArgument(2, Actual),
  124. hasArgument(
  125. 0, expr(hasType(classTemplateSpecializationDecl(hasName(
  126. "::testing::internal::PredicateFormatterFromMatcher"))),
  127. ignoringImplicit(
  128. callExpr(callee(functionDecl(hasName(
  129. "::testing::internal::"
  130. "MakePredicateFormatterFromMatcher"))),
  131. hasArgument(0, ignoringImplicit(Matcher)))))));
  132. }
  133. static internal::BindableMatcher<Stmt>
  134. gtestCallInternal(MacroType Macro, StatementMatcher MockCall, MockArgs Args) {
  135. // A ON_CALL or EXPECT_CALL macro expands to different AST structures
  136. // depending on whether the mock method has arguments or not.
  137. switch (Args) {
  138. // For example,
  139. // `ON_CALL(mock, TwoParamMethod)` is expanded to
  140. // `mock.gmock_TwoArgsMethod(WithoutMatchers(),
  141. // nullptr).InternalDefaultActionSetAt(...)`.
  142. // EXPECT_CALL is the same except
  143. // that it calls `InternalExpectedAt` instead of `InternalDefaultActionSetAt`
  144. // in the end.
  145. case MockArgs::None:
  146. return cxxMemberCallExpr(
  147. isExpandedFromMacro(getMacroName(Macro, "CALL")),
  148. callee(functionDecl(hasName(getSpecSetterName(Macro)))),
  149. onImplicitObjectArgument(ignoringImplicit(MockCall)));
  150. // For example,
  151. // `ON_CALL(mock, TwoParamMethod(m1, m2))` is expanded to
  152. // `mock.gmock_TwoParamMethod(m1,m2)(WithoutMatchers(),
  153. // nullptr).InternalDefaultActionSetAt(...)`.
  154. // EXPECT_CALL is the same except that it calls `InternalExpectedAt` instead
  155. // of `InternalDefaultActionSetAt` in the end.
  156. case MockArgs::Some:
  157. return cxxMemberCallExpr(
  158. isExpandedFromMacro(getMacroName(Macro, "CALL")),
  159. callee(functionDecl(hasName(getSpecSetterName(Macro)))),
  160. onImplicitObjectArgument(ignoringImplicit(cxxOperatorCallExpr(
  161. hasOverloadedOperatorName("()"), argumentCountIs(3),
  162. hasArgument(0, ignoringImplicit(MockCall))))));
  163. }
  164. llvm_unreachable("Unhandled MockArgs enum");
  165. }
  166. static internal::BindableMatcher<Stmt>
  167. gtestCallInternal(MacroType Macro, StatementMatcher MockObject,
  168. llvm::StringRef MockMethodName, MockArgs Args) {
  169. return gtestCallInternal(
  170. Macro,
  171. cxxMemberCallExpr(
  172. onImplicitObjectArgument(MockObject),
  173. callee(functionDecl(hasName(("gmock_" + MockMethodName).str())))),
  174. Args);
  175. }
  176. internal::BindableMatcher<Stmt> gtestAssert(GtestCmp Cmp, StatementMatcher Left,
  177. StatementMatcher Right) {
  178. return gtestComparisonInternal(MacroType::Assert, Cmp, Left, Right);
  179. }
  180. internal::BindableMatcher<Stmt> gtestExpect(GtestCmp Cmp, StatementMatcher Left,
  181. StatementMatcher Right) {
  182. return gtestComparisonInternal(MacroType::Expect, Cmp, Left, Right);
  183. }
  184. internal::BindableMatcher<Stmt> gtestAssertThat(StatementMatcher Actual,
  185. StatementMatcher Matcher) {
  186. return gtestThatInternal(MacroType::Assert, Actual, Matcher);
  187. }
  188. internal::BindableMatcher<Stmt> gtestExpectThat(StatementMatcher Actual,
  189. StatementMatcher Matcher) {
  190. return gtestThatInternal(MacroType::Expect, Actual, Matcher);
  191. }
  192. internal::BindableMatcher<Stmt> gtestOnCall(StatementMatcher MockObject,
  193. llvm::StringRef MockMethodName,
  194. MockArgs Args) {
  195. return gtestCallInternal(MacroType::On, MockObject, MockMethodName, Args);
  196. }
  197. internal::BindableMatcher<Stmt> gtestOnCall(StatementMatcher MockCall,
  198. MockArgs Args) {
  199. return gtestCallInternal(MacroType::On, MockCall, Args);
  200. }
  201. internal::BindableMatcher<Stmt> gtestExpectCall(StatementMatcher MockObject,
  202. llvm::StringRef MockMethodName,
  203. MockArgs Args) {
  204. return gtestCallInternal(MacroType::Expect, MockObject, MockMethodName, Args);
  205. }
  206. internal::BindableMatcher<Stmt> gtestExpectCall(StatementMatcher MockCall,
  207. MockArgs Args) {
  208. return gtestCallInternal(MacroType::Expect, MockCall, Args);
  209. }
  210. } // end namespace ast_matchers
  211. } // end namespace clang