[clang] d0e1593 - Add matchers for gtest's ASSERT_THAT, EXPECT_THAT, ON_CALL and EXPECT_CALL

Yitzhak Mandelbaum via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 2 10:28:52 PDT 2021


Author: Zhaomo Yang
Date: 2021-06-02T17:28:14Z
New Revision: d0e159334f9d1285ec35cf71465358c47141618c

URL: https://github.com/llvm/llvm-project/commit/d0e159334f9d1285ec35cf71465358c47141618c
DIFF: https://github.com/llvm/llvm-project/commit/d0e159334f9d1285ec35cf71465358c47141618c.diff

LOG: Add matchers for gtest's ASSERT_THAT, EXPECT_THAT, ON_CALL and EXPECT_CALL

This patch adds support for matching gtest's ASSERT_THAT, EXPECT_THAT, ON_CALL and EXPECT_CALL macros.

Reviewed By: ymandel, hokein

Differential Revision: https://reviews.llvm.org/D103195

Added: 
    

Modified: 
    clang/include/clang/ASTMatchers/GtestMatchers.h
    clang/lib/ASTMatchers/GtestMatchers.cpp
    clang/unittests/ASTMatchers/GtestMatchersTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/ASTMatchers/GtestMatchers.h b/clang/include/clang/ASTMatchers/GtestMatchers.h
index 4f8addcf744ae..e19d91a674f2e 100644
--- a/clang/include/clang/ASTMatchers/GtestMatchers.h
+++ b/clang/include/clang/ASTMatchers/GtestMatchers.h
@@ -16,6 +16,7 @@
 
 #include "clang/AST/Stmt.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
+#include "llvm/ADT/StringRef.h"
 
 namespace clang {
 namespace ast_matchers {
@@ -30,14 +31,55 @@ enum class GtestCmp {
   Lt,
 };
 
-/// Matcher for gtest's ASSERT_... macros.
+/// This enum indicates whether the mock method in the matched ON_CALL or
+/// EXPECT_CALL macro has arguments. For example, `None` can be used to match
+/// `ON_CALL(mock, TwoParamMethod)` whereas `Some` can be used to match
+/// `ON_CALL(mock, TwoParamMethod(m1, m2))`.
+enum class MockArgs {
+  None,
+  Some,
+};
+
+/// Matcher for gtest's ASSERT comparison macros including ASSERT_EQ, ASSERT_NE,
+/// ASSERT_GE, ASSERT_GT, ASSERT_LE and ASSERT_LT.
 internal::BindableMatcher<Stmt> gtestAssert(GtestCmp Cmp, StatementMatcher Left,
                                             StatementMatcher Right);
 
-/// Matcher for gtest's EXPECT_... macros.
+/// Matcher for gtest's ASSERT_THAT macro.
+internal::BindableMatcher<Stmt> gtestAssertThat(StatementMatcher Actual,
+                                                StatementMatcher Matcher);
+
+/// Matcher for gtest's EXPECT comparison macros including EXPECT_EQ, EXPECT_NE,
+/// EXPECT_GE, EXPECT_GT, EXPECT_LE and EXPECT_LT.
 internal::BindableMatcher<Stmt> gtestExpect(GtestCmp Cmp, StatementMatcher Left,
                                             StatementMatcher Right);
 
+/// Matcher for gtest's EXPECT_THAT macro.
+internal::BindableMatcher<Stmt> gtestExpectThat(StatementMatcher Actual,
+                                                StatementMatcher Matcher);
+
+/// Matcher for gtest's EXPECT_CALL macro. `MockObject` matches the mock
+/// object and `MockMethodName` is the name of the method invoked on the mock
+/// object.
+internal::BindableMatcher<Stmt> gtestExpectCall(StatementMatcher MockObject,
+                                                llvm::StringRef MockMethodName,
+                                                MockArgs Args);
+
+/// Matcher for gtest's EXPECT_CALL macro. `MockCall` matches the whole mock
+/// member method call. This API is more flexible but requires more knowledge of
+/// the AST structure of EXPECT_CALL macros.
+internal::BindableMatcher<Stmt> gtestExpectCall(StatementMatcher MockCall,
+                                                MockArgs Args);
+
+/// Like the first `gtestExpectCall` overload but for `ON_CALL`.
+internal::BindableMatcher<Stmt> gtestOnCall(StatementMatcher MockObject,
+                                            llvm::StringRef MockMethodName,
+                                            MockArgs Args);
+
+/// Like the second `gtestExpectCall` overload but for `ON_CALL`.
+internal::BindableMatcher<Stmt> gtestOnCall(StatementMatcher MockCall,
+                                            MockArgs Args);
+
 } // namespace ast_matchers
 } // namespace clang
 

diff  --git a/clang/lib/ASTMatchers/GtestMatchers.cpp b/clang/lib/ASTMatchers/GtestMatchers.cpp
index 0e587c0c3b9f6..79f69c63c10f0 100644
--- a/clang/lib/ASTMatchers/GtestMatchers.cpp
+++ b/clang/lib/ASTMatchers/GtestMatchers.cpp
@@ -5,76 +5,105 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+//
+// This file implements several matchers for popular gtest macros. In general,
+// AST matchers cannot match calls to macros. However, we can simulate such
+// matches if the macro definition has identifiable elements that themselves can
+// be matched. In that case, we can match on those elements and then check that
+// the match occurs within an expansion of the desired macro. The more uncommon
+// the identified elements, the more efficient this process will be.
+//
+//===----------------------------------------------------------------------===//
 
 #include "clang/ASTMatchers/GtestMatchers.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
-#include "llvm/Support/Timer.h"
-#include <deque>
-#include <memory>
-#include <set>
+#include "llvm/ADT/StringRef.h"
 
 namespace clang {
 namespace ast_matchers {
+namespace {
+
+enum class MacroType {
+  Expect,
+  Assert,
+  On,
+};
+
+} // namespace
 
 static DeclarationMatcher getComparisonDecl(GtestCmp Cmp) {
   switch (Cmp) {
-    case GtestCmp::Eq:
-      return cxxMethodDecl(hasName("Compare"),
-                           ofClass(cxxRecordDecl(isSameOrDerivedFrom(
-                               hasName("::testing::internal::EqHelper")))));
-    case GtestCmp::Ne:
-      return functionDecl(hasName("::testing::internal::CmpHelperNE"));
-    case GtestCmp::Ge:
-      return functionDecl(hasName("::testing::internal::CmpHelperGE"));
-    case GtestCmp::Gt:
-      return functionDecl(hasName("::testing::internal::CmpHelperGT"));
-    case GtestCmp::Le:
-      return functionDecl(hasName("::testing::internal::CmpHelperLE"));
-    case GtestCmp::Lt:
-      return functionDecl(hasName("::testing::internal::CmpHelperLT"));
+  case GtestCmp::Eq:
+    return cxxMethodDecl(hasName("Compare"),
+                         ofClass(cxxRecordDecl(isSameOrDerivedFrom(
+                             hasName("::testing::internal::EqHelper")))));
+  case GtestCmp::Ne:
+    return functionDecl(hasName("::testing::internal::CmpHelperNE"));
+  case GtestCmp::Ge:
+    return functionDecl(hasName("::testing::internal::CmpHelperGE"));
+  case GtestCmp::Gt:
+    return functionDecl(hasName("::testing::internal::CmpHelperGT"));
+  case GtestCmp::Le:
+    return functionDecl(hasName("::testing::internal::CmpHelperLE"));
+  case GtestCmp::Lt:
+    return functionDecl(hasName("::testing::internal::CmpHelperLT"));
   }
-  llvm_unreachable("Unhandled GtestCmp enum");
 }
 
-static llvm::StringRef getAssertMacro(GtestCmp Cmp) {
-  switch (Cmp) {
-    case GtestCmp::Eq:
-      return "ASSERT_EQ";
-    case GtestCmp::Ne:
-      return "ASSERT_NE";
-    case GtestCmp::Ge:
-      return "ASSERT_GE";
-    case GtestCmp::Gt:
-      return "ASSERT_GT";
-    case GtestCmp::Le:
-      return "ASSERT_LE";
-    case GtestCmp::Lt:
-      return "ASSERT_LT";
+static llvm::StringRef getMacroTypeName(MacroType Macro) {
+  switch (Macro) {
+  case MacroType::Expect:
+    return "EXPECT";
+  case MacroType::Assert:
+    return "ASSERT";
+  case MacroType::On:
+    return "ON";
   }
-  llvm_unreachable("Unhandled GtestCmp enum");
 }
 
-static llvm::StringRef getExpectMacro(GtestCmp Cmp) {
+static llvm::StringRef getComparisonTypeName(GtestCmp Cmp) {
   switch (Cmp) {
-    case GtestCmp::Eq:
-      return "EXPECT_EQ";
-    case GtestCmp::Ne:
-      return "EXPECT_NE";
-    case GtestCmp::Ge:
-      return "EXPECT_GE";
-    case GtestCmp::Gt:
-      return "EXPECT_GT";
-    case GtestCmp::Le:
-      return "EXPECT_LE";
-    case GtestCmp::Lt:
-      return "EXPECT_LT";
+  case GtestCmp::Eq:
+    return "EQ";
+  case GtestCmp::Ne:
+    return "NE";
+  case GtestCmp::Ge:
+    return "GE";
+  case GtestCmp::Gt:
+    return "GT";
+  case GtestCmp::Le:
+    return "LE";
+  case GtestCmp::Lt:
+    return "LT";
+  }
+}
+
+static std::string getMacroName(MacroType Macro, GtestCmp Cmp) {
+  return (getMacroTypeName(Macro) + "_" + getComparisonTypeName(Cmp)).str();
+}
+
+static std::string getMacroName(MacroType Macro, llvm::StringRef Operation) {
+  return (getMacroTypeName(Macro) + "_" + Operation).str();
+}
+
+// Under the hood, ON_CALL is expanded to a call to `InternalDefaultActionSetAt`
+// to set a default action spec to the underlying function mocker, while
+// EXPECT_CALL is expanded to a call to `InternalExpectedAt` to set a new
+// expectation spec.
+static llvm::StringRef getSpecSetterName(MacroType Macro) {
+  switch (Macro) {
+  case MacroType::On:
+    return "InternalDefaultActionSetAt";
+  case MacroType::Expect:
+    return "InternalExpectedAt";
+  default:
+    llvm_unreachable("Unhandled MacroType enum");
   }
-  llvm_unreachable("Unhandled GtestCmp enum");
 }
 
 // In general, AST matchers cannot match calls to macros. However, we can
@@ -86,18 +115,114 @@ static llvm::StringRef getExpectMacro(GtestCmp Cmp) {
 //
 // We use this approach to implement the derived matchers gtestAssert and
 // gtestExpect.
+static internal::BindableMatcher<Stmt>
+gtestComparisonInternal(MacroType Macro, GtestCmp Cmp, StatementMatcher Left,
+                        StatementMatcher Right) {
+  return callExpr(isExpandedFromMacro(getMacroName(Macro, Cmp)),
+                  callee(getComparisonDecl(Cmp)), hasArgument(2, Left),
+                  hasArgument(3, Right));
+}
+
+static internal::BindableMatcher<Stmt>
+gtestThatInternal(MacroType Macro, StatementMatcher Actual,
+                  StatementMatcher Matcher) {
+  return cxxOperatorCallExpr(
+      isExpandedFromMacro(getMacroName(Macro, "THAT")),
+      hasOverloadedOperatorName("()"), hasArgument(2, Actual),
+      hasArgument(
+          0, expr(hasType(classTemplateSpecializationDecl(hasName(
+                      "::testing::internal::PredicateFormatterFromMatcher"))),
+                  ignoringImplicit(
+                      callExpr(callee(functionDecl(hasName(
+                                   "::testing::internal::"
+                                   "MakePredicateFormatterFromMatcher"))),
+                               hasArgument(0, ignoringImplicit(Matcher)))))));
+}
+
+static internal::BindableMatcher<Stmt>
+gtestCallInternal(MacroType Macro, StatementMatcher MockCall, MockArgs Args) {
+  // A ON_CALL or EXPECT_CALL macro expands to 
diff erent AST structures
+  // depending on whether the mock method has arguments or not.
+  switch (Args) {
+  // For example,
+  // `ON_CALL(mock, TwoParamMethod)` is expanded to
+  // `mock.gmock_TwoArgsMethod(WithoutMatchers(),
+  // nullptr).InternalDefaultActionSetAt(...)`.
+  // EXPECT_CALL is the same except
+  // that it calls `InternalExpectedAt` instead of `InternalDefaultActionSetAt`
+  // in the end.
+  case MockArgs::None:
+    return cxxMemberCallExpr(
+        isExpandedFromMacro(getMacroName(Macro, "CALL")),
+        callee(functionDecl(hasName(getSpecSetterName(Macro)))),
+        onImplicitObjectArgument(ignoringImplicit(MockCall)));
+  // For example,
+  // `ON_CALL(mock, TwoParamMethod(m1, m2))` is expanded to
+  // `mock.gmock_TwoParamMethod(m1,m2)(WithoutMatchers(),
+  // nullptr).InternalDefaultActionSetAt(...)`.
+  // EXPECT_CALL is the same except that it calls `InternalExpectedAt` instead
+  // of `InternalDefaultActionSetAt` in the end.
+  case MockArgs::Some:
+    return cxxMemberCallExpr(
+        isExpandedFromMacro(getMacroName(Macro, "CALL")),
+        callee(functionDecl(hasName(getSpecSetterName(Macro)))),
+        onImplicitObjectArgument(ignoringImplicit(cxxOperatorCallExpr(
+            hasOverloadedOperatorName("()"), argumentCountIs(3),
+            hasArgument(0, ignoringImplicit(MockCall))))));
+  }
+}
+
+static internal::BindableMatcher<Stmt>
+gtestCallInternal(MacroType Macro, StatementMatcher MockObject,
+                  llvm::StringRef MockMethodName, MockArgs Args) {
+  return gtestCallInternal(
+      Macro,
+      cxxMemberCallExpr(
+          onImplicitObjectArgument(MockObject),
+          callee(functionDecl(hasName(("gmock_" + MockMethodName).str())))),
+      Args);
+}
+
 internal::BindableMatcher<Stmt> gtestAssert(GtestCmp Cmp, StatementMatcher Left,
                                             StatementMatcher Right) {
-  return callExpr(callee(getComparisonDecl(Cmp)),
-                  isExpandedFromMacro(getAssertMacro(Cmp).str()),
-                  hasArgument(2, Left), hasArgument(3, Right));
+  return gtestComparisonInternal(MacroType::Assert, Cmp, Left, Right);
 }
 
 internal::BindableMatcher<Stmt> gtestExpect(GtestCmp Cmp, StatementMatcher Left,
                                             StatementMatcher Right) {
-  return callExpr(callee(getComparisonDecl(Cmp)),
-                  isExpandedFromMacro(getExpectMacro(Cmp).str()),
-                  hasArgument(2, Left), hasArgument(3, Right));
+  return gtestComparisonInternal(MacroType::Expect, Cmp, Left, Right);
+}
+
+internal::BindableMatcher<Stmt> gtestAssertThat(StatementMatcher Actual,
+                                                StatementMatcher Matcher) {
+  return gtestThatInternal(MacroType::Assert, Actual, Matcher);
+}
+
+internal::BindableMatcher<Stmt> gtestExpectThat(StatementMatcher Actual,
+                                                StatementMatcher Matcher) {
+  return gtestThatInternal(MacroType::Expect, Actual, Matcher);
+}
+
+internal::BindableMatcher<Stmt> gtestOnCall(StatementMatcher MockObject,
+                                            llvm::StringRef MockMethodName,
+                                            MockArgs Args) {
+  return gtestCallInternal(MacroType::On, MockObject, MockMethodName, Args);
+}
+
+internal::BindableMatcher<Stmt> gtestOnCall(StatementMatcher MockCall,
+                                            MockArgs Args) {
+  return gtestCallInternal(MacroType::On, MockCall, Args);
+}
+
+internal::BindableMatcher<Stmt> gtestExpectCall(StatementMatcher MockObject,
+                                                llvm::StringRef MockMethodName,
+                                                MockArgs Args) {
+  return gtestCallInternal(MacroType::Expect, MockObject, MockMethodName, Args);
+}
+
+internal::BindableMatcher<Stmt> gtestExpectCall(StatementMatcher MockCall,
+                                                MockArgs Args) {
+  return gtestCallInternal(MacroType::Expect, MockCall, Args);
 }
 
 } // end namespace ast_matchers

diff  --git a/clang/unittests/ASTMatchers/GtestMatchersTest.cpp b/clang/unittests/ASTMatchers/GtestMatchersTest.cpp
index e5abb24cb4aba..5ee67a9e54844 100644
--- a/clang/unittests/ASTMatchers/GtestMatchersTest.cpp
+++ b/clang/unittests/ASTMatchers/GtestMatchersTest.cpp
@@ -42,6 +42,14 @@ constexpr llvm::StringLiteral GtestMockDecls = R"cc(
 #define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
     GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
 
+#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure) \
+  GTEST_ASSERT_(pred_format(#v1, v1), on_failure)
+
+#define EXPECT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
+
 #define EXPECT_EQ(val1, val2) \
     EXPECT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2)
 #define EXPECT_NE(val1, val2) \
@@ -55,11 +63,29 @@ constexpr llvm::StringLiteral GtestMockDecls = R"cc(
 #define EXPECT_LT(val1, val2) \
     EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
 
+#define ASSERT_THAT(value, matcher) \
+  ASSERT_PRED_FORMAT1(              \
+      ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
+#define EXPECT_THAT(value, matcher) \
+  EXPECT_PRED_FORMAT1(              \
+      ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
+
 #define ASSERT_EQ(val1, val2) \
     ASSERT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2)
 #define ASSERT_NE(val1, val2) \
     ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
 
+#define GMOCK_ON_CALL_IMPL_(mock_expr, Setter, call)                    \
+  ((mock_expr).gmock_##call)(::testing::internal::GetWithoutMatchers(), \
+                             nullptr)                                   \
+      .Setter(nullptr, 0, #mock_expr, #call)
+
+#define ON_CALL(obj, call) \
+  GMOCK_ON_CALL_IMPL_(obj, InternalDefaultActionSetAt, call)
+
+#define EXPECT_CALL(obj, call) \
+  GMOCK_ON_CALL_IMPL_(obj, InternalExpectedAt, call)
+
   namespace testing {
   namespace internal {
   class EqHelper {
@@ -96,8 +122,77 @@ constexpr llvm::StringLiteral GtestMockDecls = R"cc(
                   const T2& val2) {
     return 0;
   }
+
+  // For implementing ASSERT_THAT() and EXPECT_THAT().  The template
+  // argument M must be a type that can be converted to a matcher.
+  template <typename M>
+  class PredicateFormatterFromMatcher {
+   public:
+    explicit PredicateFormatterFromMatcher(M m) : matcher_(m) {}
+
+    // This template () operator allows a PredicateFormatterFromMatcher
+    // object to act as a predicate-formatter suitable for using with
+    // Google Test's EXPECT_PRED_FORMAT1() macro.
+    template <typename T>
+    int operator()(const char* value_text, const T& x) const {
+      return 0;
+    }
+
+   private:
+    const M matcher_;
+  };
+
+  template <typename M>
+  inline PredicateFormatterFromMatcher<M> MakePredicateFormatterFromMatcher(
+      M matcher) {
+    return PredicateFormatterFromMatcher<M>(matcher);
+  }
+
+  bool GetWithoutMatchers() { return false; }
+
+  template <typename F>
+  class MockSpec {
+   public:
+    MockSpec<F>() {}
+
+    bool InternalDefaultActionSetAt(
+        const char* file, int line, const char* obj, const char* call) {
+      return false;
+    }
+
+    bool InternalExpectedAt(
+        const char* file, int line, const char* obj, const char* call) {
+      return false;
+    }
+
+    MockSpec<F> operator()(bool, void*) {
+      return *this;
+    }
+  };  // class MockSpec
+
   }  // namespace internal
+
+  template <typename T>
+  int StrEq(T val) {
+    return 0;
+  }
+  template <typename T>
+  int Eq(T val) {
+    return 0;
+  }
+
   }  // namespace testing
+
+  class Mock {
+    public:
+    Mock() {}
+    testing::internal::MockSpec<int> gmock_TwoArgsMethod(int, int) {
+      return testing::internal::MockSpec<int>();
+    }
+    testing::internal::MockSpec<int> gmock_TwoArgsMethod(bool, void*) {
+      return testing::internal::MockSpec<int>();
+    }
+  };  // class Mock
 )cc";
 
 static std::string wrapGtest(llvm::StringRef Input) {
@@ -187,5 +282,137 @@ TEST(GtestExpectTest, GtShouldMatchExpectGt) {
       matches(wrapGtest(Input), gtestExpect(GtestCmp::Gt, expr(), expr())));
 }
 
+TEST(GtestExpectTest, ThatShouldMatchAssertThat) {
+  std::string Input = R"cc(
+    using ::testing::Eq;
+    void Test() { ASSERT_THAT(2, Eq(2)); }
+  )cc";
+  EXPECT_TRUE(matches(
+      wrapGtest(Input),
+      gtestAssertThat(
+          expr(), callExpr(callee(functionDecl(hasName("::testing::Eq")))))));
+}
+
+TEST(GtestExpectTest, ThatShouldMatchExpectThat) {
+  std::string Input = R"cc(
+    using ::testing::Eq;
+    void Test() { EXPECT_THAT(2, Eq(2)); }
+  )cc";
+  EXPECT_TRUE(matches(
+      wrapGtest(Input),
+      gtestExpectThat(
+          expr(), callExpr(callee(functionDecl(hasName("::testing::Eq")))))));
+}
+
+TEST(GtestOnCallTest, CallShouldMatchOnCallWithoutParams1) {
+  std::string Input = R"cc(
+    void Test() {
+      Mock mock;
+      ON_CALL(mock, TwoArgsMethod);
+    }
+  )cc";
+  EXPECT_TRUE(matches(wrapGtest(Input),
+                      gtestOnCall(expr(hasType(cxxRecordDecl(hasName("Mock")))),
+                                  "TwoArgsMethod", MockArgs::None)));
+}
+
+TEST(GtestOnCallTest, CallShouldMatchOnCallWithoutParams2) {
+  std::string Input = R"cc(
+    void Test() {
+      Mock mock;
+      ON_CALL(mock, TwoArgsMethod);
+    }
+  )cc";
+  EXPECT_TRUE(matches(
+      wrapGtest(Input),
+      gtestOnCall(cxxMemberCallExpr(
+                      callee(functionDecl(hasName("gmock_TwoArgsMethod"))))
+                      .bind("mock_call"),
+                  MockArgs::None)));
+}
+
+TEST(GtestOnCallTest, CallShouldMatchOnCallWithParams1) {
+  std::string Input = R"cc(
+    void Test() {
+      Mock mock;
+      ON_CALL(mock, TwoArgsMethod(1, 2));
+    }
+  )cc";
+  EXPECT_TRUE(matches(wrapGtest(Input),
+                      gtestOnCall(expr(hasType(cxxRecordDecl(hasName("Mock")))),
+                                  "TwoArgsMethod", MockArgs::Some)));
+}
+
+TEST(GtestOnCallTest, CallShouldMatchOnCallWithParams2) {
+  std::string Input = R"cc(
+    void Test() {
+      Mock mock;
+      ON_CALL(mock, TwoArgsMethod(1, 2));
+    }
+  )cc";
+  EXPECT_TRUE(matches(
+      wrapGtest(Input),
+      gtestOnCall(cxxMemberCallExpr(
+                      callee(functionDecl(hasName("gmock_TwoArgsMethod"))))
+                      .bind("mock_call"),
+                  MockArgs::Some)));
+}
+
+TEST(GtestExpectCallTest, CallShouldMatchExpectCallWithoutParams1) {
+  std::string Input = R"cc(
+    void Test() {
+      Mock mock;
+      EXPECT_CALL(mock, TwoArgsMethod);
+    }
+  )cc";
+  EXPECT_TRUE(
+      matches(wrapGtest(Input),
+              gtestExpectCall(expr(hasType(cxxRecordDecl(hasName("Mock")))),
+                              "TwoArgsMethod", MockArgs::None)));
+}
+
+TEST(GtestExpectCallTest, CallShouldMatchExpectCallWithoutParams2) {
+  std::string Input = R"cc(
+    void Test() {
+      Mock mock;
+      EXPECT_CALL(mock, TwoArgsMethod);
+    }
+  )cc";
+  EXPECT_TRUE(matches(
+      wrapGtest(Input),
+      gtestExpectCall(cxxMemberCallExpr(
+                          callee(functionDecl(hasName("gmock_TwoArgsMethod"))))
+                          .bind("mock_call"),
+                      MockArgs::None)));
+}
+
+TEST(GtestExpectCallTest, CallShouldMatchExpectCallWithParams1) {
+  std::string Input = R"cc(
+    void Test() {
+      Mock mock;
+      EXPECT_CALL(mock, TwoArgsMethod(1, 2));
+    }
+  )cc";
+  EXPECT_TRUE(
+      matches(wrapGtest(Input),
+              gtestExpectCall(expr(hasType(cxxRecordDecl(hasName("Mock")))),
+                              "TwoArgsMethod", MockArgs::Some)));
+}
+
+TEST(GtestExpectCallTest, CallShouldMatchExpectCallWithParams2) {
+  std::string Input = R"cc(
+    void Test() {
+      Mock mock;
+      EXPECT_CALL(mock, TwoArgsMethod(1, 2));
+    }
+  )cc";
+  EXPECT_TRUE(matches(
+      wrapGtest(Input),
+      gtestExpectCall(cxxMemberCallExpr(
+                          callee(functionDecl(hasName("gmock_TwoArgsMethod"))))
+                          .bind("mock_call"),
+                      MockArgs::Some)));
+}
+
 } // end namespace ast_matchers
 } // end namespace clang


        


More information about the cfe-commits mailing list