mirror of
https://github.com/google/googletest.git
synced 2026-09-25 04:09:59 +03:00
Merge branch 'master' of https://github.com/google/googletest into cmake-QNX-fix
# Conflicts: # CMakeLists.txt
This commit is contained in:
+1
-5
@@ -10,11 +10,7 @@ endif (POLICY CMP0048)
|
||||
project(googletest-distribution)
|
||||
set(GOOGLETEST_VERSION 1.10.0)
|
||||
|
||||
if (CMAKE_VERSION VERSION_LESS "3.1")
|
||||
add_definitions(-std=c++11)
|
||||
else()
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.1")
|
||||
if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
endif()
|
||||
|
||||
@@ -166,7 +166,6 @@ $env:Path = \"$project_bin;$env:Path\"
|
||||
cxx_test(gmock_ex_test gmock_main)
|
||||
cxx_test(gmock-function-mocker_test gmock_main)
|
||||
cxx_test(gmock-generated-actions_test gmock_main)
|
||||
cxx_test(gmock-generated-function-mockers_test gmock_main)
|
||||
cxx_test(gmock-generated-matchers_test gmock_main)
|
||||
cxx_test(gmock-internal-utils_test gmock_main)
|
||||
cxx_test(gmock-matchers_test gmock_main)
|
||||
|
||||
@@ -489,7 +489,7 @@ which must be a permanent callback.
|
||||
| Matcher | Description |
|
||||
| :----------------------------------- | :------------------------------------ |
|
||||
| `MATCHER(IsEven, "") { return (arg % 2) == 0; }` | Defines a matcher `IsEven()` to match an even number. |
|
||||
| `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a macher `IsDivisibleBy(n)` to match a number divisible by `n`. |
|
||||
| `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a matcher `IsDivisibleBy(n)` to match a number divisible by `n`. |
|
||||
| `MATCHER_P2(IsBetween, a, b, std::string(negation ? "isn't" : "is") + " between " + PrintToString(a) + " and " + PrintToString(b)) { return a <= arg && arg <= b; }` | Defines a matcher `IsBetween(a, b)` to match a value in the range [`a`, `b`]. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
|
||||
@@ -1426,7 +1426,7 @@ auto InvokeArgumentAdl(AdlTag, F f, Args... args) -> decltype(f(args...)) {
|
||||
typedef typename ::testing::internal::Function<F>::Result return_type; \
|
||||
typedef \
|
||||
typename ::testing::internal::Function<F>::ArgumentTuple args_type; \
|
||||
gmock_Impl(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \
|
||||
explicit gmock_Impl(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \
|
||||
: GMOCK_ACTION_INIT_PARAMS_(params) {} \
|
||||
return_type Perform(const args_type& args) override { \
|
||||
return ::testing::internal::ActionHelper<return_type, \
|
||||
|
||||
@@ -36,14 +36,36 @@
|
||||
#ifndef THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT
|
||||
#define THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT
|
||||
|
||||
#include "gmock/gmock-generated-function-mockers.h" // NOLINT
|
||||
#include <type_traits> // IWYU pragma: keep
|
||||
#include <utility> // IWYU pragma: keep
|
||||
|
||||
#include "gmock/gmock-spec-builders.h"
|
||||
#include "gmock/internal/gmock-internal-utils.h"
|
||||
#include "gmock/internal/gmock-pp.h"
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
template <typename T>
|
||||
using identity_t = T;
|
||||
|
||||
template <typename MockType>
|
||||
const MockType* AdjustConstness_const(const MockType* mock) {
|
||||
return mock;
|
||||
}
|
||||
|
||||
template <typename MockType>
|
||||
MockType* AdjustConstness_(const MockType* mock) {
|
||||
return const_cast<MockType*>(mock);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// The style guide prohibits "using" statements in a namespace scope
|
||||
// inside a header file. However, the FunctionMocker class template
|
||||
// is meant to be defined in the ::testing namespace. The following
|
||||
// line is just a trick for working around a bug in MSVC 8.0, which
|
||||
// cannot handle it if we define FunctionMocker in ::testing.
|
||||
using internal::FunctionMocker;
|
||||
} // namespace testing
|
||||
|
||||
#define MOCK_METHOD(...) \
|
||||
@@ -241,36 +263,196 @@ using identity_t = T;
|
||||
GMOCK_PP_IDENTITY) \
|
||||
(_elem)
|
||||
|
||||
#define GMOCK_INTERNAL_PARAMETER(_i, _Signature, _) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \
|
||||
GMOCK_PP_REMOVE_PARENS(_Signature)) \
|
||||
#define GMOCK_INTERNAL_PARAMETER(_i, _Signature, _) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
GMOCK_INTERNAL_ARG_O(_i, GMOCK_PP_REMOVE_PARENS(_Signature)) \
|
||||
gmock_a##_i
|
||||
|
||||
#define GMOCK_INTERNAL_FORWARD_ARG(_i, _Signature, _) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
::std::forward<GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \
|
||||
GMOCK_PP_REMOVE_PARENS(_Signature))>( \
|
||||
gmock_a##_i)
|
||||
#define GMOCK_INTERNAL_FORWARD_ARG(_i, _Signature, _) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
::std::forward<GMOCK_INTERNAL_ARG_O( \
|
||||
_i, GMOCK_PP_REMOVE_PARENS(_Signature))>(gmock_a##_i)
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_PARAMETER(_i, _Signature, _) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
GMOCK_INTERNAL_MATCHER_O(typename, GMOCK_PP_INC(_i), \
|
||||
GMOCK_PP_REMOVE_PARENS(_Signature)) \
|
||||
#define GMOCK_INTERNAL_MATCHER_PARAMETER(_i, _Signature, _) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
GMOCK_INTERNAL_MATCHER_O(_i, GMOCK_PP_REMOVE_PARENS(_Signature)) \
|
||||
gmock_a##_i
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_ARGUMENT(_i, _1, _2) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
gmock_a##_i
|
||||
|
||||
#define GMOCK_INTERNAL_A_MATCHER_ARGUMENT(_i, _Signature, _) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
::testing::A<GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \
|
||||
GMOCK_PP_REMOVE_PARENS(_Signature))>()
|
||||
#define GMOCK_INTERNAL_A_MATCHER_ARGUMENT(_i, _Signature, _) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
::testing::A<GMOCK_INTERNAL_ARG_O(_i, GMOCK_PP_REMOVE_PARENS(_Signature))>()
|
||||
|
||||
#define GMOCK_INTERNAL_ARG_O(_tn, _i, ...) GMOCK_ARG_(_tn, _i, __VA_ARGS__)
|
||||
#define GMOCK_INTERNAL_ARG_O(_i, ...) \
|
||||
typename ::testing::internal::Function<__VA_ARGS__>::template Arg<_i>::type
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_O(_tn, _i, ...) \
|
||||
GMOCK_MATCHER_(_tn, _i, __VA_ARGS__)
|
||||
#define GMOCK_INTERNAL_MATCHER_O(_i, ...) \
|
||||
const ::testing::Matcher<typename ::testing::internal::Function< \
|
||||
__VA_ARGS__>::template Arg<_i>::type>&
|
||||
|
||||
#define MOCK_METHOD0(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 0, __VA_ARGS__)
|
||||
#define MOCK_METHOD1(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 1, __VA_ARGS__)
|
||||
#define MOCK_METHOD2(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 2, __VA_ARGS__)
|
||||
#define MOCK_METHOD3(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 3, __VA_ARGS__)
|
||||
#define MOCK_METHOD4(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 4, __VA_ARGS__)
|
||||
#define MOCK_METHOD5(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 5, __VA_ARGS__)
|
||||
#define MOCK_METHOD6(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 6, __VA_ARGS__)
|
||||
#define MOCK_METHOD7(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 7, __VA_ARGS__)
|
||||
#define MOCK_METHOD8(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 8, __VA_ARGS__)
|
||||
#define MOCK_METHOD9(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 9, __VA_ARGS__)
|
||||
#define MOCK_METHOD10(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, , m, 10, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 0, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 1, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 2, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 3, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 4, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 5, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 6, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 7, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 8, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 9, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 10, __VA_ARGS__)
|
||||
|
||||
#define MOCK_METHOD0_T(m, ...) MOCK_METHOD0(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD1_T(m, ...) MOCK_METHOD1(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD2_T(m, ...) MOCK_METHOD2(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD3_T(m, ...) MOCK_METHOD3(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD4_T(m, ...) MOCK_METHOD4(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD5_T(m, ...) MOCK_METHOD5(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD6_T(m, ...) MOCK_METHOD6(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD7_T(m, ...) MOCK_METHOD7(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD8_T(m, ...) MOCK_METHOD8(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD9_T(m, ...) MOCK_METHOD9(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD10_T(m, ...) MOCK_METHOD10(m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0_T(m, ...) MOCK_CONST_METHOD0(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1_T(m, ...) MOCK_CONST_METHOD1(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2_T(m, ...) MOCK_CONST_METHOD2(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3_T(m, ...) MOCK_CONST_METHOD3(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4_T(m, ...) MOCK_CONST_METHOD4(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5_T(m, ...) MOCK_CONST_METHOD5(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6_T(m, ...) MOCK_CONST_METHOD6(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7_T(m, ...) MOCK_CONST_METHOD7(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8_T(m, ...) MOCK_CONST_METHOD8(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9_T(m, ...) MOCK_CONST_METHOD9(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10_T(m, ...) MOCK_CONST_METHOD10(m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 0, __VA_ARGS__)
|
||||
#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 1, __VA_ARGS__)
|
||||
#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 2, __VA_ARGS__)
|
||||
#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 3, __VA_ARGS__)
|
||||
#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 4, __VA_ARGS__)
|
||||
#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 5, __VA_ARGS__)
|
||||
#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 6, __VA_ARGS__)
|
||||
#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 7, __VA_ARGS__)
|
||||
#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 8, __VA_ARGS__)
|
||||
#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 9, __VA_ARGS__)
|
||||
#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 10, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 0, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 1, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 2, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 3, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 4, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 5, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 6, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 7, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 8, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 9, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 10, __VA_ARGS__)
|
||||
|
||||
#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD0_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD1_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD2_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD3_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD4_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD5_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD6_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD7_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD8_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD9_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD10_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
|
||||
#define GMOCK_INTERNAL_MOCK_METHODN(constness, ct, Method, args_num, ...) \
|
||||
GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \
|
||||
args_num, ::testing::internal::identity_t<__VA_ARGS__>); \
|
||||
GMOCK_INTERNAL_MOCK_METHOD_IMPL( \
|
||||
args_num, Method, GMOCK_PP_NARG0(constness), 0, 0, , ct, \
|
||||
(::testing::internal::identity_t<__VA_ARGS__>))
|
||||
|
||||
#define GMOCK_MOCKER_(arity, constness, Method) \
|
||||
GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
|
||||
|
||||
#endif // THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_
|
||||
|
||||
@@ -1,752 +0,0 @@
|
||||
// This file was GENERATED by command:
|
||||
// pump.py gmock-generated-function-mockers.h.pump
|
||||
// DO NOT EDIT BY HAND!!!
|
||||
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements function mockers of various arities.
|
||||
|
||||
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||
|
||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "gmock/gmock-spec-builders.h"
|
||||
#include "gmock/internal/gmock-internal-utils.h"
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
// Removes the given pointer; this is a helper for the expectation setter method
|
||||
// for parameterless matchers.
|
||||
//
|
||||
// We want to make sure that the user cannot set a parameterless expectation on
|
||||
// overloaded methods, including methods which are overloaded on const. Example:
|
||||
//
|
||||
// class MockClass {
|
||||
// MOCK_METHOD0(GetName, string&());
|
||||
// MOCK_CONST_METHOD0(GetName, const string&());
|
||||
// };
|
||||
//
|
||||
// TEST() {
|
||||
// // This should be an error, as it's not clear which overload is expected.
|
||||
// EXPECT_CALL(mock, GetName).WillOnce(ReturnRef(value));
|
||||
// }
|
||||
//
|
||||
// Here are the generated expectation-setter methods:
|
||||
//
|
||||
// class MockClass {
|
||||
// // Overload 1
|
||||
// MockSpec<string&()> gmock_GetName() { ... }
|
||||
// // Overload 2. Declared const so that the compiler will generate an
|
||||
// // error when trying to resolve between this and overload 4 in
|
||||
// // 'gmock_GetName(WithoutMatchers(), nullptr)'.
|
||||
// MockSpec<string&()> gmock_GetName(
|
||||
// const WithoutMatchers&, const Function<string&()>*) const {
|
||||
// // Removes const from this, calls overload 1
|
||||
// return AdjustConstness_(this)->gmock_GetName();
|
||||
// }
|
||||
//
|
||||
// // Overload 3
|
||||
// const string& gmock_GetName() const { ... }
|
||||
// // Overload 4
|
||||
// MockSpec<const string&()> gmock_GetName(
|
||||
// const WithoutMatchers&, const Function<const string&()>*) const {
|
||||
// // Does not remove const, calls overload 3
|
||||
// return AdjustConstness_const(this)->gmock_GetName();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
template <typename MockType>
|
||||
const MockType* AdjustConstness_const(const MockType* mock) {
|
||||
return mock;
|
||||
}
|
||||
|
||||
// Removes const from and returns the given pointer; this is a helper for the
|
||||
// expectation setter method for parameterless matchers.
|
||||
template <typename MockType>
|
||||
MockType* AdjustConstness_(const MockType* mock) {
|
||||
return const_cast<MockType*>(mock);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// The style guide prohibits "using" statements in a namespace scope
|
||||
// inside a header file. However, the FunctionMocker class template
|
||||
// is meant to be defined in the ::testing namespace. The following
|
||||
// line is just a trick for working around a bug in MSVC 8.0, which
|
||||
// cannot handle it if we define FunctionMocker in ::testing.
|
||||
using internal::FunctionMocker;
|
||||
|
||||
// GMOCK_RESULT_(tn, F) expands to the result type of function type F.
|
||||
// We define this as a variadic macro in case F contains unprotected
|
||||
// commas (the same reason that we use variadic macros in other places
|
||||
// in this file).
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_RESULT_(tn, ...) \
|
||||
tn ::testing::internal::Function<__VA_ARGS__>::Result
|
||||
|
||||
// The type of argument N of the given function type.
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_ARG_(tn, N, ...) \
|
||||
tn ::testing::internal::Function<__VA_ARGS__>::template Arg<N-1>::type
|
||||
|
||||
// The matcher type for argument N of the given function type.
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_MATCHER_(tn, N, ...) \
|
||||
const ::testing::Matcher<GMOCK_ARG_(tn, N, __VA_ARGS__)>&
|
||||
|
||||
// The variable for mocking the given method.
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_MOCKER_(arity, constness, Method) \
|
||||
GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD0_(tn, constness, ct, Method, ...) \
|
||||
static_assert(0 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
) constness { \
|
||||
GMOCK_MOCKER_(0, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(0, constness, Method).Invoke(); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method() constness { \
|
||||
GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(0, constness, Method).With(); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
|
||||
const ::testing::internal::WithoutMatchers&, \
|
||||
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
|
||||
return ::testing::internal::AdjustConstness_##constness(this)-> \
|
||||
gmock_##Method(); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(0, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD1_(tn, constness, ct, Method, ...) \
|
||||
static_assert(1 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1) constness { \
|
||||
GMOCK_MOCKER_(1, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(1, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1) constness { \
|
||||
GMOCK_MOCKER_(1, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(1, constness, Method).With(gmock_a1); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
|
||||
const ::testing::internal::WithoutMatchers&, \
|
||||
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
|
||||
return ::testing::internal::AdjustConstness_##constness(this)-> \
|
||||
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(1, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD2_(tn, constness, ct, Method, ...) \
|
||||
static_assert(2 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2) constness { \
|
||||
GMOCK_MOCKER_(2, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(2, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2) constness { \
|
||||
GMOCK_MOCKER_(2, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(2, constness, Method).With(gmock_a1, gmock_a2); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
|
||||
const ::testing::internal::WithoutMatchers&, \
|
||||
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
|
||||
return ::testing::internal::AdjustConstness_##constness(this)-> \
|
||||
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(2, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD3_(tn, constness, ct, Method, ...) \
|
||||
static_assert(3 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, \
|
||||
__VA_ARGS__) gmock_a3) constness { \
|
||||
GMOCK_MOCKER_(3, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(3, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3) constness { \
|
||||
GMOCK_MOCKER_(3, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(3, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
|
||||
const ::testing::internal::WithoutMatchers&, \
|
||||
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
|
||||
return ::testing::internal::AdjustConstness_##constness(this)-> \
|
||||
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(3, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD4_(tn, constness, ct, Method, ...) \
|
||||
static_assert(4 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4) constness { \
|
||||
GMOCK_MOCKER_(4, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(4, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
|
||||
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4) constness { \
|
||||
GMOCK_MOCKER_(4, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(4, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3, gmock_a4); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
|
||||
const ::testing::internal::WithoutMatchers&, \
|
||||
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
|
||||
return ::testing::internal::AdjustConstness_##constness(this)-> \
|
||||
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(4, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD5_(tn, constness, ct, Method, ...) \
|
||||
static_assert(5 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
|
||||
__VA_ARGS__) gmock_a5) constness { \
|
||||
GMOCK_MOCKER_(5, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(5, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
|
||||
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
|
||||
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5) constness { \
|
||||
GMOCK_MOCKER_(5, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(5, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3, gmock_a4, gmock_a5); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
|
||||
const ::testing::internal::WithoutMatchers&, \
|
||||
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
|
||||
return ::testing::internal::AdjustConstness_##constness(this)-> \
|
||||
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(5, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD6_(tn, constness, ct, Method, ...) \
|
||||
static_assert(6 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
|
||||
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, \
|
||||
__VA_ARGS__) gmock_a6) constness { \
|
||||
GMOCK_MOCKER_(6, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(6, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
|
||||
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
|
||||
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
|
||||
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6) constness { \
|
||||
GMOCK_MOCKER_(6, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(6, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3, gmock_a4, gmock_a5, gmock_a6); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
|
||||
const ::testing::internal::WithoutMatchers&, \
|
||||
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
|
||||
return ::testing::internal::AdjustConstness_##constness(this)-> \
|
||||
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(6, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD7_(tn, constness, ct, Method, ...) \
|
||||
static_assert(7 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
|
||||
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7) constness { \
|
||||
GMOCK_MOCKER_(7, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(7, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
|
||||
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
|
||||
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
|
||||
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \
|
||||
::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7) constness { \
|
||||
GMOCK_MOCKER_(7, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(7, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
|
||||
const ::testing::internal::WithoutMatchers&, \
|
||||
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
|
||||
return ::testing::internal::AdjustConstness_##constness(this)-> \
|
||||
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(7, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD8_(tn, constness, ct, Method, ...) \
|
||||
static_assert(8 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
|
||||
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \
|
||||
__VA_ARGS__) gmock_a8) constness { \
|
||||
GMOCK_MOCKER_(8, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(8, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
|
||||
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
|
||||
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
|
||||
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \
|
||||
::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7), \
|
||||
::std::forward<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(gmock_a8)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
|
||||
GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8) constness { \
|
||||
GMOCK_MOCKER_(8, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(8, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
|
||||
const ::testing::internal::WithoutMatchers&, \
|
||||
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
|
||||
return ::testing::internal::AdjustConstness_##constness(this)-> \
|
||||
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 8, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(8, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD9_(tn, constness, ct, Method, ...) \
|
||||
static_assert(9 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
|
||||
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \
|
||||
__VA_ARGS__) gmock_a8, GMOCK_ARG_(tn, 9, \
|
||||
__VA_ARGS__) gmock_a9) constness { \
|
||||
GMOCK_MOCKER_(9, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(9, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
|
||||
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
|
||||
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
|
||||
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \
|
||||
::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7), \
|
||||
::std::forward<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(gmock_a8), \
|
||||
::std::forward<GMOCK_ARG_(tn, 9, __VA_ARGS__)>(gmock_a9)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
|
||||
GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \
|
||||
GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9) constness { \
|
||||
GMOCK_MOCKER_(9, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(9, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
|
||||
gmock_a9); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
|
||||
const ::testing::internal::WithoutMatchers&, \
|
||||
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
|
||||
return ::testing::internal::AdjustConstness_##constness(this)-> \
|
||||
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 9, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(9, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD10_(tn, constness, ct, Method, ...) \
|
||||
static_assert(10 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
|
||||
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \
|
||||
__VA_ARGS__) gmock_a8, GMOCK_ARG_(tn, 9, __VA_ARGS__) gmock_a9, \
|
||||
GMOCK_ARG_(tn, 10, __VA_ARGS__) gmock_a10) constness { \
|
||||
GMOCK_MOCKER_(10, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(10, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
|
||||
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
|
||||
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
|
||||
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \
|
||||
::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7), \
|
||||
::std::forward<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(gmock_a8), \
|
||||
::std::forward<GMOCK_ARG_(tn, 9, __VA_ARGS__)>(gmock_a9), \
|
||||
::std::forward<GMOCK_ARG_(tn, 10, __VA_ARGS__)>(gmock_a10)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
|
||||
GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \
|
||||
GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9, \
|
||||
GMOCK_MATCHER_(tn, 10, \
|
||||
__VA_ARGS__) gmock_a10) constness { \
|
||||
GMOCK_MOCKER_(10, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(10, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
|
||||
gmock_a10); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
|
||||
const ::testing::internal::WithoutMatchers&, \
|
||||
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
|
||||
return ::testing::internal::AdjustConstness_##constness(this)-> \
|
||||
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 9, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 10, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(10, constness, \
|
||||
Method)
|
||||
|
||||
#define MOCK_METHOD0(m, ...) GMOCK_METHOD0_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD1(m, ...) GMOCK_METHOD1_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD2(m, ...) GMOCK_METHOD2_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD3(m, ...) GMOCK_METHOD3_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD4(m, ...) GMOCK_METHOD4_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD5(m, ...) GMOCK_METHOD5_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD6(m, ...) GMOCK_METHOD6_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD7(m, ...) GMOCK_METHOD7_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD8(m, ...) GMOCK_METHOD8_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD9(m, ...) GMOCK_METHOD9_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD10(m, ...) GMOCK_METHOD10_(, , , m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0(m, ...) GMOCK_METHOD0_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1(m, ...) GMOCK_METHOD1_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2(m, ...) GMOCK_METHOD2_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3(m, ...) GMOCK_METHOD3_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4(m, ...) GMOCK_METHOD4_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5(m, ...) GMOCK_METHOD5_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6(m, ...) GMOCK_METHOD6_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7(m, ...) GMOCK_METHOD7_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8(m, ...) GMOCK_METHOD8_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9(m, ...) GMOCK_METHOD9_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10(m, ...) GMOCK_METHOD10_(, const, , m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_METHOD0_T(m, ...) GMOCK_METHOD0_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD1_T(m, ...) GMOCK_METHOD1_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD2_T(m, ...) GMOCK_METHOD2_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD3_T(m, ...) GMOCK_METHOD3_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD4_T(m, ...) GMOCK_METHOD4_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD5_T(m, ...) GMOCK_METHOD5_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD6_T(m, ...) GMOCK_METHOD6_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD7_T(m, ...) GMOCK_METHOD7_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD8_T(m, ...) GMOCK_METHOD8_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD9_T(m, ...) GMOCK_METHOD9_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD10_T(m, ...) GMOCK_METHOD10_(typename, , , m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0_T(m, ...) \
|
||||
GMOCK_METHOD0_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1_T(m, ...) \
|
||||
GMOCK_METHOD1_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2_T(m, ...) \
|
||||
GMOCK_METHOD2_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3_T(m, ...) \
|
||||
GMOCK_METHOD3_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4_T(m, ...) \
|
||||
GMOCK_METHOD4_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5_T(m, ...) \
|
||||
GMOCK_METHOD5_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6_T(m, ...) \
|
||||
GMOCK_METHOD6_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7_T(m, ...) \
|
||||
GMOCK_METHOD7_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8_T(m, ...) \
|
||||
GMOCK_METHOD8_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9_T(m, ...) \
|
||||
GMOCK_METHOD9_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10_T(m, ...) \
|
||||
GMOCK_METHOD10_(typename, const, , m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD0_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD1_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD2_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD3_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD4_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD5_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD6_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD7_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD8_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD9_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD10_(, , ct, m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD0_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD1_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD2_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD3_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD4_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD5_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD6_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD7_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD8_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD9_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD10_(, const, ct, m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD0_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD1_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD2_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD3_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD4_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD5_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD6_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD7_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD8_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD9_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD10_(typename, , ct, m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD0_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD1_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD2_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD3_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD4_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD5_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD6_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD7_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD8_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD9_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD10_(typename, const, ct, m, __VA_ARGS__)
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||
@@ -1,227 +0,0 @@
|
||||
$$ -*- mode: c++; -*-
|
||||
$$ This is a Pump source file. Please use Pump to convert
|
||||
$$ it to gmock-generated-function-mockers.h.
|
||||
$$
|
||||
$var n = 10 $$ The maximum arity we support.
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements function mockers of various arities.
|
||||
|
||||
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||
|
||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "gmock/gmock-spec-builders.h"
|
||||
#include "gmock/internal/gmock-internal-utils.h"
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
$range i 0..n
|
||||
// Removes the given pointer; this is a helper for the expectation setter method
|
||||
// for parameterless matchers.
|
||||
//
|
||||
// We want to make sure that the user cannot set a parameterless expectation on
|
||||
// overloaded methods, including methods which are overloaded on const. Example:
|
||||
//
|
||||
// class MockClass {
|
||||
// MOCK_METHOD0(GetName, string&());
|
||||
// MOCK_CONST_METHOD0(GetName, const string&());
|
||||
// };
|
||||
//
|
||||
// TEST() {
|
||||
// // This should be an error, as it's not clear which overload is expected.
|
||||
// EXPECT_CALL(mock, GetName).WillOnce(ReturnRef(value));
|
||||
// }
|
||||
//
|
||||
// Here are the generated expectation-setter methods:
|
||||
//
|
||||
// class MockClass {
|
||||
// // Overload 1
|
||||
// MockSpec<string&()> gmock_GetName() { ... }
|
||||
// // Overload 2. Declared const so that the compiler will generate an
|
||||
// // error when trying to resolve between this and overload 4 in
|
||||
// // 'gmock_GetName(WithoutMatchers(), nullptr)'.
|
||||
// MockSpec<string&()> gmock_GetName(
|
||||
// const WithoutMatchers&, const Function<string&()>*) const {
|
||||
// // Removes const from this, calls overload 1
|
||||
// return AdjustConstness_(this)->gmock_GetName();
|
||||
// }
|
||||
//
|
||||
// // Overload 3
|
||||
// const string& gmock_GetName() const { ... }
|
||||
// // Overload 4
|
||||
// MockSpec<const string&()> gmock_GetName(
|
||||
// const WithoutMatchers&, const Function<const string&()>*) const {
|
||||
// // Does not remove const, calls overload 3
|
||||
// return AdjustConstness_const(this)->gmock_GetName();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
template <typename MockType>
|
||||
const MockType* AdjustConstness_const(const MockType* mock) {
|
||||
return mock;
|
||||
}
|
||||
|
||||
// Removes const from and returns the given pointer; this is a helper for the
|
||||
// expectation setter method for parameterless matchers.
|
||||
template <typename MockType>
|
||||
MockType* AdjustConstness_(const MockType* mock) {
|
||||
return const_cast<MockType*>(mock);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// The style guide prohibits "using" statements in a namespace scope
|
||||
// inside a header file. However, the FunctionMocker class template
|
||||
// is meant to be defined in the ::testing namespace. The following
|
||||
// line is just a trick for working around a bug in MSVC 8.0, which
|
||||
// cannot handle it if we define FunctionMocker in ::testing.
|
||||
using internal::FunctionMocker;
|
||||
|
||||
// GMOCK_RESULT_(tn, F) expands to the result type of function type F.
|
||||
// We define this as a variadic macro in case F contains unprotected
|
||||
// commas (the same reason that we use variadic macros in other places
|
||||
// in this file).
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_RESULT_(tn, ...) \
|
||||
tn ::testing::internal::Function<__VA_ARGS__>::Result
|
||||
|
||||
// The type of argument N of the given function type.
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_ARG_(tn, N, ...) \
|
||||
tn ::testing::internal::Function<__VA_ARGS__>::template Arg<N-1>::type
|
||||
|
||||
// The matcher type for argument N of the given function type.
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_MATCHER_(tn, N, ...) \
|
||||
const ::testing::Matcher<GMOCK_ARG_(tn, N, __VA_ARGS__)>&
|
||||
|
||||
// The variable for mocking the given method.
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_MOCKER_(arity, constness, Method) \
|
||||
GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
|
||||
|
||||
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
$var arg_as = [[$for j, [[GMOCK_ARG_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
|
||||
$var as = [[$for j, \
|
||||
[[::std::forward<GMOCK_ARG_(tn, $j, __VA_ARGS__)>(gmock_a$j)]]]]
|
||||
$var matcher_arg_as = [[$for j, \
|
||||
[[GMOCK_MATCHER_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
|
||||
$var matcher_as = [[$for j, [[gmock_a$j]]]]
|
||||
$var anything_matchers = [[$for j, \
|
||||
[[::testing::A<GMOCK_ARG_(tn, $j, __VA_ARGS__)>()]]]]
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD$i[[]]_(tn, constness, ct, Method, ...) \
|
||||
static_assert($i == ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, "MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
$arg_as) constness { \
|
||||
GMOCK_MOCKER_($i, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_($i, constness, Method).Invoke($as); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method($matcher_arg_as) constness { \
|
||||
GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_($i, constness, Method).With($matcher_as); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
|
||||
const ::testing::internal::WithoutMatchers&, \
|
||||
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
|
||||
return ::testing::internal::AdjustConstness_##constness(this)-> \
|
||||
gmock_##Method($anything_matchers); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_($i, constness, Method)
|
||||
|
||||
|
||||
]]
|
||||
$for i [[
|
||||
#define MOCK_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, , , m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
$for i [[
|
||||
#define MOCK_CONST_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, const, , m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
$for i [[
|
||||
#define MOCK_METHOD$i[[]]_T(m, ...) GMOCK_METHOD$i[[]]_(typename, , , m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
$for i [[
|
||||
#define MOCK_CONST_METHOD$i[[]]_T(m, ...) \
|
||||
GMOCK_METHOD$i[[]]_(typename, const, , m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
$for i [[
|
||||
#define MOCK_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD$i[[]]_(, , ct, m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
$for i [[
|
||||
#define MOCK_CONST_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD$i[[]]_(, const, ct, m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
$for i [[
|
||||
#define MOCK_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD$i[[]]_(typename, , ct, m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
$for i [[
|
||||
#define MOCK_CONST_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD$i[[]]_(typename, const, ct, m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||
@@ -1,1097 +0,0 @@
|
||||
// This file was GENERATED by command:
|
||||
// pump.py gmock-generated-matchers.h.pump
|
||||
// DO NOT EDIT BY HAND!!!
|
||||
|
||||
// Copyright 2008, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements some commonly used variadic matchers.
|
||||
|
||||
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||
|
||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "gmock/gmock-matchers.h"
|
||||
|
||||
// The MATCHER* family of macros can be used in a namespace scope to
|
||||
// define custom matchers easily.
|
||||
//
|
||||
// Basic Usage
|
||||
// ===========
|
||||
//
|
||||
// The syntax
|
||||
//
|
||||
// MATCHER(name, description_string) { statements; }
|
||||
//
|
||||
// defines a matcher with the given name that executes the statements,
|
||||
// which must return a bool to indicate if the match succeeds. Inside
|
||||
// the statements, you can refer to the value being matched by 'arg',
|
||||
// and refer to its type by 'arg_type'.
|
||||
//
|
||||
// The description string documents what the matcher does, and is used
|
||||
// to generate the failure message when the match fails. Since a
|
||||
// MATCHER() is usually defined in a header file shared by multiple
|
||||
// C++ source files, we require the description to be a C-string
|
||||
// literal to avoid possible side effects. It can be empty, in which
|
||||
// case we'll use the sequence of words in the matcher name as the
|
||||
// description.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// MATCHER(IsEven, "") { return (arg % 2) == 0; }
|
||||
//
|
||||
// allows you to write
|
||||
//
|
||||
// // Expects mock_foo.Bar(n) to be called where n is even.
|
||||
// EXPECT_CALL(mock_foo, Bar(IsEven()));
|
||||
//
|
||||
// or,
|
||||
//
|
||||
// // Verifies that the value of some_expression is even.
|
||||
// EXPECT_THAT(some_expression, IsEven());
|
||||
//
|
||||
// If the above assertion fails, it will print something like:
|
||||
//
|
||||
// Value of: some_expression
|
||||
// Expected: is even
|
||||
// Actual: 7
|
||||
//
|
||||
// where the description "is even" is automatically calculated from the
|
||||
// matcher name IsEven.
|
||||
//
|
||||
// Argument Type
|
||||
// =============
|
||||
//
|
||||
// Note that the type of the value being matched (arg_type) is
|
||||
// determined by the context in which you use the matcher and is
|
||||
// supplied to you by the compiler, so you don't need to worry about
|
||||
// declaring it (nor can you). This allows the matcher to be
|
||||
// polymorphic. For example, IsEven() can be used to match any type
|
||||
// where the value of "(arg % 2) == 0" can be implicitly converted to
|
||||
// a bool. In the "Bar(IsEven())" example above, if method Bar()
|
||||
// takes an int, 'arg_type' will be int; if it takes an unsigned long,
|
||||
// 'arg_type' will be unsigned long; and so on.
|
||||
//
|
||||
// Parameterizing Matchers
|
||||
// =======================
|
||||
//
|
||||
// Sometimes you'll want to parameterize the matcher. For that you
|
||||
// can use another macro:
|
||||
//
|
||||
// MATCHER_P(name, param_name, description_string) { statements; }
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
|
||||
//
|
||||
// will allow you to write:
|
||||
//
|
||||
// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
|
||||
//
|
||||
// which may lead to this message (assuming n is 10):
|
||||
//
|
||||
// Value of: Blah("a")
|
||||
// Expected: has absolute value 10
|
||||
// Actual: -9
|
||||
//
|
||||
// Note that both the matcher description and its parameter are
|
||||
// printed, making the message human-friendly.
|
||||
//
|
||||
// In the matcher definition body, you can write 'foo_type' to
|
||||
// reference the type of a parameter named 'foo'. For example, in the
|
||||
// body of MATCHER_P(HasAbsoluteValue, value) above, you can write
|
||||
// 'value_type' to refer to the type of 'value'.
|
||||
//
|
||||
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P10 to
|
||||
// support multi-parameter matchers.
|
||||
//
|
||||
// Describing Parameterized Matchers
|
||||
// =================================
|
||||
//
|
||||
// The last argument to MATCHER*() is a string-typed expression. The
|
||||
// expression can reference all of the matcher's parameters and a
|
||||
// special bool-typed variable named 'negation'. When 'negation' is
|
||||
// false, the expression should evaluate to the matcher's description;
|
||||
// otherwise it should evaluate to the description of the negation of
|
||||
// the matcher. For example,
|
||||
//
|
||||
// using testing::PrintToString;
|
||||
//
|
||||
// MATCHER_P2(InClosedRange, low, hi,
|
||||
// std::string(negation ? "is not" : "is") + " in range [" +
|
||||
// PrintToString(low) + ", " + PrintToString(hi) + "]") {
|
||||
// return low <= arg && arg <= hi;
|
||||
// }
|
||||
// ...
|
||||
// EXPECT_THAT(3, InClosedRange(4, 6));
|
||||
// EXPECT_THAT(3, Not(InClosedRange(2, 4)));
|
||||
//
|
||||
// would generate two failures that contain the text:
|
||||
//
|
||||
// Expected: is in range [4, 6]
|
||||
// ...
|
||||
// Expected: is not in range [2, 4]
|
||||
//
|
||||
// If you specify "" as the description, the failure message will
|
||||
// contain the sequence of words in the matcher name followed by the
|
||||
// parameter values printed as a tuple. For example,
|
||||
//
|
||||
// MATCHER_P2(InClosedRange, low, hi, "") { ... }
|
||||
// ...
|
||||
// EXPECT_THAT(3, InClosedRange(4, 6));
|
||||
// EXPECT_THAT(3, Not(InClosedRange(2, 4)));
|
||||
//
|
||||
// would generate two failures that contain the text:
|
||||
//
|
||||
// Expected: in closed range (4, 6)
|
||||
// ...
|
||||
// Expected: not (in closed range (2, 4))
|
||||
//
|
||||
// Types of Matcher Parameters
|
||||
// ===========================
|
||||
//
|
||||
// For the purpose of typing, you can view
|
||||
//
|
||||
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
|
||||
//
|
||||
// as shorthand for
|
||||
//
|
||||
// template <typename p1_type, ..., typename pk_type>
|
||||
// FooMatcherPk<p1_type, ..., pk_type>
|
||||
// Foo(p1_type p1, ..., pk_type pk) { ... }
|
||||
//
|
||||
// When you write Foo(v1, ..., vk), the compiler infers the types of
|
||||
// the parameters v1, ..., and vk for you. If you are not happy with
|
||||
// the result of the type inference, you can specify the types by
|
||||
// explicitly instantiating the template, as in Foo<long, bool>(5,
|
||||
// false). As said earlier, you don't get to (or need to) specify
|
||||
// 'arg_type' as that's determined by the context in which the matcher
|
||||
// is used. You can assign the result of expression Foo(p1, ..., pk)
|
||||
// to a variable of type FooMatcherPk<p1_type, ..., pk_type>. This
|
||||
// can be useful when composing matchers.
|
||||
//
|
||||
// While you can instantiate a matcher template with reference types,
|
||||
// passing the parameters by pointer usually makes your code more
|
||||
// readable. If, however, you still want to pass a parameter by
|
||||
// reference, be aware that in the failure message generated by the
|
||||
// matcher you will see the value of the referenced object but not its
|
||||
// address.
|
||||
//
|
||||
// Explaining Match Results
|
||||
// ========================
|
||||
//
|
||||
// Sometimes the matcher description alone isn't enough to explain why
|
||||
// the match has failed or succeeded. For example, when expecting a
|
||||
// long string, it can be very helpful to also print the diff between
|
||||
// the expected string and the actual one. To achieve that, you can
|
||||
// optionally stream additional information to a special variable
|
||||
// named result_listener, whose type is a pointer to class
|
||||
// MatchResultListener:
|
||||
//
|
||||
// MATCHER_P(EqualsLongString, str, "") {
|
||||
// if (arg == str) return true;
|
||||
//
|
||||
// *result_listener << "the difference: "
|
||||
/// << DiffStrings(str, arg);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// Overloading Matchers
|
||||
// ====================
|
||||
//
|
||||
// You can overload matchers with different numbers of parameters:
|
||||
//
|
||||
// MATCHER_P(Blah, a, description_string1) { ... }
|
||||
// MATCHER_P2(Blah, a, b, description_string2) { ... }
|
||||
//
|
||||
// Caveats
|
||||
// =======
|
||||
//
|
||||
// When defining a new matcher, you should also consider implementing
|
||||
// MatcherInterface or using MakePolymorphicMatcher(). These
|
||||
// approaches require more work than the MATCHER* macros, but also
|
||||
// give you more control on the types of the value being matched and
|
||||
// the matcher parameters, which may leads to better compiler error
|
||||
// messages when the matcher is used wrong. They also allow
|
||||
// overloading matchers based on parameter types (as opposed to just
|
||||
// based on the number of parameters).
|
||||
//
|
||||
// MATCHER*() can only be used in a namespace scope as templates cannot be
|
||||
// declared inside of a local class.
|
||||
//
|
||||
// More Information
|
||||
// ================
|
||||
//
|
||||
// To learn more about using these macros, please search for 'MATCHER'
|
||||
// on
|
||||
// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md
|
||||
|
||||
#define MATCHER(name, description)\
|
||||
class name##Matcher {\
|
||||
public:\
|
||||
template <typename arg_type>\
|
||||
class gmock_Impl : public ::testing::MatcherInterface<\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
|
||||
public:\
|
||||
gmock_Impl()\
|
||||
{}\
|
||||
bool MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener) const override;\
|
||||
void DescribeTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(false);\
|
||||
}\
|
||||
void DescribeNegationTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(true);\
|
||||
}\
|
||||
private:\
|
||||
::std::string FormatDescription(bool negation) const {\
|
||||
::std::string gmock_description = (description);\
|
||||
if (!gmock_description.empty()) {\
|
||||
return gmock_description;\
|
||||
}\
|
||||
return ::testing::internal::FormatMatcherDescription(\
|
||||
negation, #name, \
|
||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||
::std::tuple<>()));\
|
||||
}\
|
||||
};\
|
||||
template <typename arg_type>\
|
||||
operator ::testing::Matcher<arg_type>() const {\
|
||||
return ::testing::Matcher<arg_type>(\
|
||||
new gmock_Impl<arg_type>());\
|
||||
}\
|
||||
name##Matcher() {\
|
||||
}\
|
||||
private:\
|
||||
};\
|
||||
inline name##Matcher name() {\
|
||||
return name##Matcher();\
|
||||
}\
|
||||
template <typename arg_type>\
|
||||
bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||
const
|
||||
|
||||
#define MATCHER_P(name, p0, description)\
|
||||
template <typename p0##_type>\
|
||||
class name##MatcherP {\
|
||||
public:\
|
||||
template <typename arg_type>\
|
||||
class gmock_Impl : public ::testing::MatcherInterface<\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
|
||||
public:\
|
||||
explicit gmock_Impl(p0##_type gmock_p0)\
|
||||
: p0(::std::move(gmock_p0)) {}\
|
||||
bool MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener) const override;\
|
||||
void DescribeTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(false);\
|
||||
}\
|
||||
void DescribeNegationTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(true);\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
private:\
|
||||
::std::string FormatDescription(bool negation) const {\
|
||||
::std::string gmock_description = (description);\
|
||||
if (!gmock_description.empty()) {\
|
||||
return gmock_description;\
|
||||
}\
|
||||
return ::testing::internal::FormatMatcherDescription(\
|
||||
negation, #name, \
|
||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||
::std::tuple<p0##_type>(p0)));\
|
||||
}\
|
||||
};\
|
||||
template <typename arg_type>\
|
||||
operator ::testing::Matcher<arg_type>() const {\
|
||||
return ::testing::Matcher<arg_type>(\
|
||||
new gmock_Impl<arg_type>(p0));\
|
||||
}\
|
||||
explicit name##MatcherP(p0##_type gmock_p0) : p0(::std::move(gmock_p0)) {\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
private:\
|
||||
};\
|
||||
template <typename p0##_type>\
|
||||
inline name##MatcherP<p0##_type> name(p0##_type p0) {\
|
||||
return name##MatcherP<p0##_type>(p0);\
|
||||
}\
|
||||
template <typename p0##_type>\
|
||||
template <typename arg_type>\
|
||||
bool name##MatcherP<p0##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||
const
|
||||
|
||||
#define MATCHER_P2(name, p0, p1, description)\
|
||||
template <typename p0##_type, typename p1##_type>\
|
||||
class name##MatcherP2 {\
|
||||
public:\
|
||||
template <typename arg_type>\
|
||||
class gmock_Impl : public ::testing::MatcherInterface<\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
|
||||
public:\
|
||||
gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1)\
|
||||
: p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)) {}\
|
||||
bool MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener) const override;\
|
||||
void DescribeTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(false);\
|
||||
}\
|
||||
void DescribeNegationTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(true);\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
private:\
|
||||
::std::string FormatDescription(bool negation) const {\
|
||||
::std::string gmock_description = (description);\
|
||||
if (!gmock_description.empty()) {\
|
||||
return gmock_description;\
|
||||
}\
|
||||
return ::testing::internal::FormatMatcherDescription(\
|
||||
negation, #name, \
|
||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||
::std::tuple<p0##_type, p1##_type>(p0, p1)));\
|
||||
}\
|
||||
};\
|
||||
template <typename arg_type>\
|
||||
operator ::testing::Matcher<arg_type>() const {\
|
||||
return ::testing::Matcher<arg_type>(\
|
||||
new gmock_Impl<arg_type>(p0, p1));\
|
||||
}\
|
||||
name##MatcherP2(p0##_type gmock_p0, \
|
||||
p1##_type gmock_p1) : p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)) {\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
private:\
|
||||
};\
|
||||
template <typename p0##_type, typename p1##_type>\
|
||||
inline name##MatcherP2<p0##_type, p1##_type> name(p0##_type p0, \
|
||||
p1##_type p1) {\
|
||||
return name##MatcherP2<p0##_type, p1##_type>(p0, p1);\
|
||||
}\
|
||||
template <typename p0##_type, typename p1##_type>\
|
||||
template <typename arg_type>\
|
||||
bool name##MatcherP2<p0##_type, \
|
||||
p1##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||
const
|
||||
|
||||
#define MATCHER_P3(name, p0, p1, p2, description)\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type>\
|
||||
class name##MatcherP3 {\
|
||||
public:\
|
||||
template <typename arg_type>\
|
||||
class gmock_Impl : public ::testing::MatcherInterface<\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
|
||||
public:\
|
||||
gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2)\
|
||||
: p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)) {}\
|
||||
bool MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener) const override;\
|
||||
void DescribeTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(false);\
|
||||
}\
|
||||
void DescribeNegationTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(true);\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
private:\
|
||||
::std::string FormatDescription(bool negation) const {\
|
||||
::std::string gmock_description = (description);\
|
||||
if (!gmock_description.empty()) {\
|
||||
return gmock_description;\
|
||||
}\
|
||||
return ::testing::internal::FormatMatcherDescription(\
|
||||
negation, #name, \
|
||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||
::std::tuple<p0##_type, p1##_type, p2##_type>(p0, p1, p2)));\
|
||||
}\
|
||||
};\
|
||||
template <typename arg_type>\
|
||||
operator ::testing::Matcher<arg_type>() const {\
|
||||
return ::testing::Matcher<arg_type>(\
|
||||
new gmock_Impl<arg_type>(p0, p1, p2));\
|
||||
}\
|
||||
name##MatcherP3(p0##_type gmock_p0, p1##_type gmock_p1, \
|
||||
p2##_type gmock_p2) : p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)) {\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
private:\
|
||||
};\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type>\
|
||||
inline name##MatcherP3<p0##_type, p1##_type, p2##_type> name(p0##_type p0, \
|
||||
p1##_type p1, p2##_type p2) {\
|
||||
return name##MatcherP3<p0##_type, p1##_type, p2##_type>(p0, p1, p2);\
|
||||
}\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type>\
|
||||
template <typename arg_type>\
|
||||
bool name##MatcherP3<p0##_type, p1##_type, \
|
||||
p2##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||
const
|
||||
|
||||
#define MATCHER_P4(name, p0, p1, p2, p3, description)\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type>\
|
||||
class name##MatcherP4 {\
|
||||
public:\
|
||||
template <typename arg_type>\
|
||||
class gmock_Impl : public ::testing::MatcherInterface<\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
|
||||
public:\
|
||||
gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
|
||||
p3##_type gmock_p3)\
|
||||
: p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)) {}\
|
||||
bool MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener) const override;\
|
||||
void DescribeTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(false);\
|
||||
}\
|
||||
void DescribeNegationTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(true);\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
p3##_type const p3;\
|
||||
private:\
|
||||
::std::string FormatDescription(bool negation) const {\
|
||||
::std::string gmock_description = (description);\
|
||||
if (!gmock_description.empty()) {\
|
||||
return gmock_description;\
|
||||
}\
|
||||
return ::testing::internal::FormatMatcherDescription(\
|
||||
negation, #name, \
|
||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||
::std::tuple<p0##_type, p1##_type, p2##_type, p3##_type>(p0, \
|
||||
p1, p2, p3)));\
|
||||
}\
|
||||
};\
|
||||
template <typename arg_type>\
|
||||
operator ::testing::Matcher<arg_type>() const {\
|
||||
return ::testing::Matcher<arg_type>(\
|
||||
new gmock_Impl<arg_type>(p0, p1, p2, p3));\
|
||||
}\
|
||||
name##MatcherP4(p0##_type gmock_p0, p1##_type gmock_p1, \
|
||||
p2##_type gmock_p2, p3##_type gmock_p3) : p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \
|
||||
p3(::std::move(gmock_p3)) {\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
p3##_type const p3;\
|
||||
private:\
|
||||
};\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type>\
|
||||
inline name##MatcherP4<p0##_type, p1##_type, p2##_type, \
|
||||
p3##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \
|
||||
p3##_type p3) {\
|
||||
return name##MatcherP4<p0##_type, p1##_type, p2##_type, p3##_type>(p0, \
|
||||
p1, p2, p3);\
|
||||
}\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type>\
|
||||
template <typename arg_type>\
|
||||
bool name##MatcherP4<p0##_type, p1##_type, p2##_type, \
|
||||
p3##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||
const
|
||||
|
||||
#define MATCHER_P5(name, p0, p1, p2, p3, p4, description)\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type>\
|
||||
class name##MatcherP5 {\
|
||||
public:\
|
||||
template <typename arg_type>\
|
||||
class gmock_Impl : public ::testing::MatcherInterface<\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
|
||||
public:\
|
||||
gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
|
||||
p3##_type gmock_p3, p4##_type gmock_p4)\
|
||||
: p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \
|
||||
p4(::std::move(gmock_p4)) {}\
|
||||
bool MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener) const override;\
|
||||
void DescribeTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(false);\
|
||||
}\
|
||||
void DescribeNegationTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(true);\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
p3##_type const p3;\
|
||||
p4##_type const p4;\
|
||||
private:\
|
||||
::std::string FormatDescription(bool negation) const {\
|
||||
::std::string gmock_description = (description);\
|
||||
if (!gmock_description.empty()) {\
|
||||
return gmock_description;\
|
||||
}\
|
||||
return ::testing::internal::FormatMatcherDescription(\
|
||||
negation, #name, \
|
||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||
::std::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type>(p0, p1, p2, p3, p4)));\
|
||||
}\
|
||||
};\
|
||||
template <typename arg_type>\
|
||||
operator ::testing::Matcher<arg_type>() const {\
|
||||
return ::testing::Matcher<arg_type>(\
|
||||
new gmock_Impl<arg_type>(p0, p1, p2, p3, p4));\
|
||||
}\
|
||||
name##MatcherP5(p0##_type gmock_p0, p1##_type gmock_p1, \
|
||||
p2##_type gmock_p2, p3##_type gmock_p3, \
|
||||
p4##_type gmock_p4) : p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \
|
||||
p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)) {\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
p3##_type const p3;\
|
||||
p4##_type const p4;\
|
||||
private:\
|
||||
};\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type>\
|
||||
inline name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
|
||||
p4##_type p4) {\
|
||||
return name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type>(p0, p1, p2, p3, p4);\
|
||||
}\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type>\
|
||||
template <typename arg_type>\
|
||||
bool name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||
const
|
||||
|
||||
#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description)\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type>\
|
||||
class name##MatcherP6 {\
|
||||
public:\
|
||||
template <typename arg_type>\
|
||||
class gmock_Impl : public ::testing::MatcherInterface<\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
|
||||
public:\
|
||||
gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
|
||||
p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5)\
|
||||
: p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \
|
||||
p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)) {}\
|
||||
bool MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener) const override;\
|
||||
void DescribeTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(false);\
|
||||
}\
|
||||
void DescribeNegationTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(true);\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
p3##_type const p3;\
|
||||
p4##_type const p4;\
|
||||
p5##_type const p5;\
|
||||
private:\
|
||||
::std::string FormatDescription(bool negation) const {\
|
||||
::std::string gmock_description = (description);\
|
||||
if (!gmock_description.empty()) {\
|
||||
return gmock_description;\
|
||||
}\
|
||||
return ::testing::internal::FormatMatcherDescription(\
|
||||
negation, #name, \
|
||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||
::std::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5)));\
|
||||
}\
|
||||
};\
|
||||
template <typename arg_type>\
|
||||
operator ::testing::Matcher<arg_type>() const {\
|
||||
return ::testing::Matcher<arg_type>(\
|
||||
new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5));\
|
||||
}\
|
||||
name##MatcherP6(p0##_type gmock_p0, p1##_type gmock_p1, \
|
||||
p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
|
||||
p5##_type gmock_p5) : p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \
|
||||
p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \
|
||||
p5(::std::move(gmock_p5)) {\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
p3##_type const p3;\
|
||||
p4##_type const p4;\
|
||||
p5##_type const p5;\
|
||||
private:\
|
||||
};\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type>\
|
||||
inline name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \
|
||||
p3##_type p3, p4##_type p4, p5##_type p5) {\
|
||||
return name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5);\
|
||||
}\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type>\
|
||||
template <typename arg_type>\
|
||||
bool name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
|
||||
p5##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||
const
|
||||
|
||||
#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description)\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type>\
|
||||
class name##MatcherP7 {\
|
||||
public:\
|
||||
template <typename arg_type>\
|
||||
class gmock_Impl : public ::testing::MatcherInterface<\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
|
||||
public:\
|
||||
gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
|
||||
p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
|
||||
p6##_type gmock_p6)\
|
||||
: p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \
|
||||
p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)), \
|
||||
p6(::std::move(gmock_p6)) {}\
|
||||
bool MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener) const override;\
|
||||
void DescribeTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(false);\
|
||||
}\
|
||||
void DescribeNegationTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(true);\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
p3##_type const p3;\
|
||||
p4##_type const p4;\
|
||||
p5##_type const p5;\
|
||||
p6##_type const p6;\
|
||||
private:\
|
||||
::std::string FormatDescription(bool negation) const {\
|
||||
::std::string gmock_description = (description);\
|
||||
if (!gmock_description.empty()) {\
|
||||
return gmock_description;\
|
||||
}\
|
||||
return ::testing::internal::FormatMatcherDescription(\
|
||||
negation, #name, \
|
||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||
::std::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, \
|
||||
p6)));\
|
||||
}\
|
||||
};\
|
||||
template <typename arg_type>\
|
||||
operator ::testing::Matcher<arg_type>() const {\
|
||||
return ::testing::Matcher<arg_type>(\
|
||||
new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6));\
|
||||
}\
|
||||
name##MatcherP7(p0##_type gmock_p0, p1##_type gmock_p1, \
|
||||
p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
|
||||
p5##_type gmock_p5, p6##_type gmock_p6) : p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \
|
||||
p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \
|
||||
p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)) {\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
p3##_type const p3;\
|
||||
p4##_type const p4;\
|
||||
p5##_type const p5;\
|
||||
p6##_type const p6;\
|
||||
private:\
|
||||
};\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type>\
|
||||
inline name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type, p6##_type> name(p0##_type p0, p1##_type p1, \
|
||||
p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \
|
||||
p6##_type p6) {\
|
||||
return name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, p6);\
|
||||
}\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type>\
|
||||
template <typename arg_type>\
|
||||
bool name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
|
||||
p5##_type, p6##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||
const
|
||||
|
||||
#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description)\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type, typename p7##_type>\
|
||||
class name##MatcherP8 {\
|
||||
public:\
|
||||
template <typename arg_type>\
|
||||
class gmock_Impl : public ::testing::MatcherInterface<\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
|
||||
public:\
|
||||
gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
|
||||
p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
|
||||
p6##_type gmock_p6, p7##_type gmock_p7)\
|
||||
: p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \
|
||||
p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)), \
|
||||
p6(::std::move(gmock_p6)), p7(::std::move(gmock_p7)) {}\
|
||||
bool MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener) const override;\
|
||||
void DescribeTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(false);\
|
||||
}\
|
||||
void DescribeNegationTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(true);\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
p3##_type const p3;\
|
||||
p4##_type const p4;\
|
||||
p5##_type const p5;\
|
||||
p6##_type const p6;\
|
||||
p7##_type const p7;\
|
||||
private:\
|
||||
::std::string FormatDescription(bool negation) const {\
|
||||
::std::string gmock_description = (description);\
|
||||
if (!gmock_description.empty()) {\
|
||||
return gmock_description;\
|
||||
}\
|
||||
return ::testing::internal::FormatMatcherDescription(\
|
||||
negation, #name, \
|
||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||
::std::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, \
|
||||
p3, p4, p5, p6, p7)));\
|
||||
}\
|
||||
};\
|
||||
template <typename arg_type>\
|
||||
operator ::testing::Matcher<arg_type>() const {\
|
||||
return ::testing::Matcher<arg_type>(\
|
||||
new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7));\
|
||||
}\
|
||||
name##MatcherP8(p0##_type gmock_p0, p1##_type gmock_p1, \
|
||||
p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
|
||||
p5##_type gmock_p5, p6##_type gmock_p6, \
|
||||
p7##_type gmock_p7) : p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \
|
||||
p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \
|
||||
p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)), \
|
||||
p7(::std::move(gmock_p7)) {\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
p3##_type const p3;\
|
||||
p4##_type const p4;\
|
||||
p5##_type const p5;\
|
||||
p6##_type const p6;\
|
||||
p7##_type const p7;\
|
||||
private:\
|
||||
};\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type, typename p7##_type>\
|
||||
inline name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type, p6##_type, p7##_type> name(p0##_type p0, \
|
||||
p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \
|
||||
p6##_type p6, p7##_type p7) {\
|
||||
return name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, p3, p4, p5, \
|
||||
p6, p7);\
|
||||
}\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type, typename p7##_type>\
|
||||
template <typename arg_type>\
|
||||
bool name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
|
||||
p5##_type, p6##_type, \
|
||||
p7##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||
const
|
||||
|
||||
#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description)\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type, typename p7##_type, typename p8##_type>\
|
||||
class name##MatcherP9 {\
|
||||
public:\
|
||||
template <typename arg_type>\
|
||||
class gmock_Impl : public ::testing::MatcherInterface<\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
|
||||
public:\
|
||||
gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
|
||||
p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
|
||||
p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8)\
|
||||
: p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \
|
||||
p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)), \
|
||||
p6(::std::move(gmock_p6)), p7(::std::move(gmock_p7)), \
|
||||
p8(::std::move(gmock_p8)) {}\
|
||||
bool MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener) const override;\
|
||||
void DescribeTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(false);\
|
||||
}\
|
||||
void DescribeNegationTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(true);\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
p3##_type const p3;\
|
||||
p4##_type const p4;\
|
||||
p5##_type const p5;\
|
||||
p6##_type const p6;\
|
||||
p7##_type const p7;\
|
||||
p8##_type const p8;\
|
||||
private:\
|
||||
::std::string FormatDescription(bool negation) const {\
|
||||
::std::string gmock_description = (description);\
|
||||
if (!gmock_description.empty()) {\
|
||||
return gmock_description;\
|
||||
}\
|
||||
return ::testing::internal::FormatMatcherDescription(\
|
||||
negation, #name, \
|
||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||
::std::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type, p6##_type, p7##_type, \
|
||||
p8##_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8)));\
|
||||
}\
|
||||
};\
|
||||
template <typename arg_type>\
|
||||
operator ::testing::Matcher<arg_type>() const {\
|
||||
return ::testing::Matcher<arg_type>(\
|
||||
new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8));\
|
||||
}\
|
||||
name##MatcherP9(p0##_type gmock_p0, p1##_type gmock_p1, \
|
||||
p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
|
||||
p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \
|
||||
p8##_type gmock_p8) : p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \
|
||||
p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \
|
||||
p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)), \
|
||||
p7(::std::move(gmock_p7)), p8(::std::move(gmock_p8)) {\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
p3##_type const p3;\
|
||||
p4##_type const p4;\
|
||||
p5##_type const p5;\
|
||||
p6##_type const p6;\
|
||||
p7##_type const p7;\
|
||||
p8##_type const p8;\
|
||||
private:\
|
||||
};\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type, typename p7##_type, typename p8##_type>\
|
||||
inline name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type, p6##_type, p7##_type, \
|
||||
p8##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
|
||||
p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \
|
||||
p8##_type p8) {\
|
||||
return name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type, p6##_type, p7##_type, p8##_type>(p0, p1, p2, \
|
||||
p3, p4, p5, p6, p7, p8);\
|
||||
}\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type, typename p7##_type, typename p8##_type>\
|
||||
template <typename arg_type>\
|
||||
bool name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
|
||||
p5##_type, p6##_type, p7##_type, \
|
||||
p8##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||
const
|
||||
|
||||
#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description)\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type, typename p7##_type, typename p8##_type, \
|
||||
typename p9##_type>\
|
||||
class name##MatcherP10 {\
|
||||
public:\
|
||||
template <typename arg_type>\
|
||||
class gmock_Impl : public ::testing::MatcherInterface<\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
|
||||
public:\
|
||||
gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
|
||||
p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
|
||||
p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \
|
||||
p9##_type gmock_p9)\
|
||||
: p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \
|
||||
p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)), \
|
||||
p6(::std::move(gmock_p6)), p7(::std::move(gmock_p7)), \
|
||||
p8(::std::move(gmock_p8)), p9(::std::move(gmock_p9)) {}\
|
||||
bool MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener) const override;\
|
||||
void DescribeTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(false);\
|
||||
}\
|
||||
void DescribeNegationTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(true);\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
p3##_type const p3;\
|
||||
p4##_type const p4;\
|
||||
p5##_type const p5;\
|
||||
p6##_type const p6;\
|
||||
p7##_type const p7;\
|
||||
p8##_type const p8;\
|
||||
p9##_type const p9;\
|
||||
private:\
|
||||
::std::string FormatDescription(bool negation) const {\
|
||||
::std::string gmock_description = (description);\
|
||||
if (!gmock_description.empty()) {\
|
||||
return gmock_description;\
|
||||
}\
|
||||
return ::testing::internal::FormatMatcherDescription(\
|
||||
negation, #name, \
|
||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||
::std::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
|
||||
p9##_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)));\
|
||||
}\
|
||||
};\
|
||||
template <typename arg_type>\
|
||||
operator ::testing::Matcher<arg_type>() const {\
|
||||
return ::testing::Matcher<arg_type>(\
|
||||
new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9));\
|
||||
}\
|
||||
name##MatcherP10(p0##_type gmock_p0, p1##_type gmock_p1, \
|
||||
p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
|
||||
p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \
|
||||
p8##_type gmock_p8, p9##_type gmock_p9) : p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \
|
||||
p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \
|
||||
p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)), \
|
||||
p7(::std::move(gmock_p7)), p8(::std::move(gmock_p8)), \
|
||||
p9(::std::move(gmock_p9)) {\
|
||||
}\
|
||||
p0##_type const p0;\
|
||||
p1##_type const p1;\
|
||||
p2##_type const p2;\
|
||||
p3##_type const p3;\
|
||||
p4##_type const p4;\
|
||||
p5##_type const p5;\
|
||||
p6##_type const p6;\
|
||||
p7##_type const p7;\
|
||||
p8##_type const p8;\
|
||||
p9##_type const p9;\
|
||||
private:\
|
||||
};\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type, typename p7##_type, typename p8##_type, \
|
||||
typename p9##_type>\
|
||||
inline name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
|
||||
p9##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
|
||||
p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \
|
||||
p9##_type p9) {\
|
||||
return name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>(p0, \
|
||||
p1, p2, p3, p4, p5, p6, p7, p8, p9);\
|
||||
}\
|
||||
template <typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type, typename p7##_type, typename p8##_type, \
|
||||
typename p9##_type>\
|
||||
template <typename arg_type>\
|
||||
bool name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \
|
||||
p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
|
||||
p9##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||
const
|
||||
|
||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||
@@ -1,346 +0,0 @@
|
||||
$$ -*- mode: c++; -*-
|
||||
$$ This is a Pump source file. Please use Pump to convert
|
||||
$$ it to gmock-generated-matchers.h.
|
||||
$$
|
||||
$var n = 10 $$ The maximum arity we support.
|
||||
$$ }} This line fixes auto-indentation of the following code in Emacs.
|
||||
// Copyright 2008, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements some commonly used variadic matchers.
|
||||
|
||||
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||
|
||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "gmock/gmock-matchers.h"
|
||||
|
||||
// The MATCHER* family of macros can be used in a namespace scope to
|
||||
// define custom matchers easily.
|
||||
//
|
||||
// Basic Usage
|
||||
// ===========
|
||||
//
|
||||
// The syntax
|
||||
//
|
||||
// MATCHER(name, description_string) { statements; }
|
||||
//
|
||||
// defines a matcher with the given name that executes the statements,
|
||||
// which must return a bool to indicate if the match succeeds. Inside
|
||||
// the statements, you can refer to the value being matched by 'arg',
|
||||
// and refer to its type by 'arg_type'.
|
||||
//
|
||||
// The description string documents what the matcher does, and is used
|
||||
// to generate the failure message when the match fails. Since a
|
||||
// MATCHER() is usually defined in a header file shared by multiple
|
||||
// C++ source files, we require the description to be a C-string
|
||||
// literal to avoid possible side effects. It can be empty, in which
|
||||
// case we'll use the sequence of words in the matcher name as the
|
||||
// description.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// MATCHER(IsEven, "") { return (arg % 2) == 0; }
|
||||
//
|
||||
// allows you to write
|
||||
//
|
||||
// // Expects mock_foo.Bar(n) to be called where n is even.
|
||||
// EXPECT_CALL(mock_foo, Bar(IsEven()));
|
||||
//
|
||||
// or,
|
||||
//
|
||||
// // Verifies that the value of some_expression is even.
|
||||
// EXPECT_THAT(some_expression, IsEven());
|
||||
//
|
||||
// If the above assertion fails, it will print something like:
|
||||
//
|
||||
// Value of: some_expression
|
||||
// Expected: is even
|
||||
// Actual: 7
|
||||
//
|
||||
// where the description "is even" is automatically calculated from the
|
||||
// matcher name IsEven.
|
||||
//
|
||||
// Argument Type
|
||||
// =============
|
||||
//
|
||||
// Note that the type of the value being matched (arg_type) is
|
||||
// determined by the context in which you use the matcher and is
|
||||
// supplied to you by the compiler, so you don't need to worry about
|
||||
// declaring it (nor can you). This allows the matcher to be
|
||||
// polymorphic. For example, IsEven() can be used to match any type
|
||||
// where the value of "(arg % 2) == 0" can be implicitly converted to
|
||||
// a bool. In the "Bar(IsEven())" example above, if method Bar()
|
||||
// takes an int, 'arg_type' will be int; if it takes an unsigned long,
|
||||
// 'arg_type' will be unsigned long; and so on.
|
||||
//
|
||||
// Parameterizing Matchers
|
||||
// =======================
|
||||
//
|
||||
// Sometimes you'll want to parameterize the matcher. For that you
|
||||
// can use another macro:
|
||||
//
|
||||
// MATCHER_P(name, param_name, description_string) { statements; }
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
|
||||
//
|
||||
// will allow you to write:
|
||||
//
|
||||
// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
|
||||
//
|
||||
// which may lead to this message (assuming n is 10):
|
||||
//
|
||||
// Value of: Blah("a")
|
||||
// Expected: has absolute value 10
|
||||
// Actual: -9
|
||||
//
|
||||
// Note that both the matcher description and its parameter are
|
||||
// printed, making the message human-friendly.
|
||||
//
|
||||
// In the matcher definition body, you can write 'foo_type' to
|
||||
// reference the type of a parameter named 'foo'. For example, in the
|
||||
// body of MATCHER_P(HasAbsoluteValue, value) above, you can write
|
||||
// 'value_type' to refer to the type of 'value'.
|
||||
//
|
||||
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to
|
||||
// support multi-parameter matchers.
|
||||
//
|
||||
// Describing Parameterized Matchers
|
||||
// =================================
|
||||
//
|
||||
// The last argument to MATCHER*() is a string-typed expression. The
|
||||
// expression can reference all of the matcher's parameters and a
|
||||
// special bool-typed variable named 'negation'. When 'negation' is
|
||||
// false, the expression should evaluate to the matcher's description;
|
||||
// otherwise it should evaluate to the description of the negation of
|
||||
// the matcher. For example,
|
||||
//
|
||||
// using testing::PrintToString;
|
||||
//
|
||||
// MATCHER_P2(InClosedRange, low, hi,
|
||||
// std::string(negation ? "is not" : "is") + " in range [" +
|
||||
// PrintToString(low) + ", " + PrintToString(hi) + "]") {
|
||||
// return low <= arg && arg <= hi;
|
||||
// }
|
||||
// ...
|
||||
// EXPECT_THAT(3, InClosedRange(4, 6));
|
||||
// EXPECT_THAT(3, Not(InClosedRange(2, 4)));
|
||||
//
|
||||
// would generate two failures that contain the text:
|
||||
//
|
||||
// Expected: is in range [4, 6]
|
||||
// ...
|
||||
// Expected: is not in range [2, 4]
|
||||
//
|
||||
// If you specify "" as the description, the failure message will
|
||||
// contain the sequence of words in the matcher name followed by the
|
||||
// parameter values printed as a tuple. For example,
|
||||
//
|
||||
// MATCHER_P2(InClosedRange, low, hi, "") { ... }
|
||||
// ...
|
||||
// EXPECT_THAT(3, InClosedRange(4, 6));
|
||||
// EXPECT_THAT(3, Not(InClosedRange(2, 4)));
|
||||
//
|
||||
// would generate two failures that contain the text:
|
||||
//
|
||||
// Expected: in closed range (4, 6)
|
||||
// ...
|
||||
// Expected: not (in closed range (2, 4))
|
||||
//
|
||||
// Types of Matcher Parameters
|
||||
// ===========================
|
||||
//
|
||||
// For the purpose of typing, you can view
|
||||
//
|
||||
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
|
||||
//
|
||||
// as shorthand for
|
||||
//
|
||||
// template <typename p1_type, ..., typename pk_type>
|
||||
// FooMatcherPk<p1_type, ..., pk_type>
|
||||
// Foo(p1_type p1, ..., pk_type pk) { ... }
|
||||
//
|
||||
// When you write Foo(v1, ..., vk), the compiler infers the types of
|
||||
// the parameters v1, ..., and vk for you. If you are not happy with
|
||||
// the result of the type inference, you can specify the types by
|
||||
// explicitly instantiating the template, as in Foo<long, bool>(5,
|
||||
// false). As said earlier, you don't get to (or need to) specify
|
||||
// 'arg_type' as that's determined by the context in which the matcher
|
||||
// is used. You can assign the result of expression Foo(p1, ..., pk)
|
||||
// to a variable of type FooMatcherPk<p1_type, ..., pk_type>. This
|
||||
// can be useful when composing matchers.
|
||||
//
|
||||
// While you can instantiate a matcher template with reference types,
|
||||
// passing the parameters by pointer usually makes your code more
|
||||
// readable. If, however, you still want to pass a parameter by
|
||||
// reference, be aware that in the failure message generated by the
|
||||
// matcher you will see the value of the referenced object but not its
|
||||
// address.
|
||||
//
|
||||
// Explaining Match Results
|
||||
// ========================
|
||||
//
|
||||
// Sometimes the matcher description alone isn't enough to explain why
|
||||
// the match has failed or succeeded. For example, when expecting a
|
||||
// long string, it can be very helpful to also print the diff between
|
||||
// the expected string and the actual one. To achieve that, you can
|
||||
// optionally stream additional information to a special variable
|
||||
// named result_listener, whose type is a pointer to class
|
||||
// MatchResultListener:
|
||||
//
|
||||
// MATCHER_P(EqualsLongString, str, "") {
|
||||
// if (arg == str) return true;
|
||||
//
|
||||
// *result_listener << "the difference: "
|
||||
/// << DiffStrings(str, arg);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// Overloading Matchers
|
||||
// ====================
|
||||
//
|
||||
// You can overload matchers with different numbers of parameters:
|
||||
//
|
||||
// MATCHER_P(Blah, a, description_string1) { ... }
|
||||
// MATCHER_P2(Blah, a, b, description_string2) { ... }
|
||||
//
|
||||
// Caveats
|
||||
// =======
|
||||
//
|
||||
// When defining a new matcher, you should also consider implementing
|
||||
// MatcherInterface or using MakePolymorphicMatcher(). These
|
||||
// approaches require more work than the MATCHER* macros, but also
|
||||
// give you more control on the types of the value being matched and
|
||||
// the matcher parameters, which may leads to better compiler error
|
||||
// messages when the matcher is used wrong. They also allow
|
||||
// overloading matchers based on parameter types (as opposed to just
|
||||
// based on the number of parameters).
|
||||
//
|
||||
// MATCHER*() can only be used in a namespace scope as templates cannot be
|
||||
// declared inside of a local class.
|
||||
//
|
||||
// More Information
|
||||
// ================
|
||||
//
|
||||
// To learn more about using these macros, please search for 'MATCHER'
|
||||
// on
|
||||
// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md
|
||||
|
||||
$range i 0..n
|
||||
$for i
|
||||
|
||||
[[
|
||||
$var macro_name = [[$if i==0 [[MATCHER]] $elif i==1 [[MATCHER_P]]
|
||||
$else [[MATCHER_P$i]]]]
|
||||
$var class_name = [[name##Matcher[[$if i==0 [[]] $elif i==1 [[P]]
|
||||
$else [[P$i]]]]]]
|
||||
$range j 0..i-1
|
||||
$var template = [[$if i==0 [[]] $else [[
|
||||
|
||||
template <$for j, [[typename p$j##_type]]>\
|
||||
]]]]
|
||||
$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
|
||||
$var impl_ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
|
||||
$var impl_inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::move(gmock_p$j))]]]]]]
|
||||
$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::move(gmock_p$j))]]]]]]
|
||||
$var params = [[$for j, [[p$j]]]]
|
||||
$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
|
||||
$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
|
||||
$var param_field_decls = [[$for j
|
||||
[[
|
||||
|
||||
p$j##_type const p$j;\
|
||||
]]]]
|
||||
$var param_field_decls2 = [[$for j
|
||||
[[
|
||||
|
||||
p$j##_type const p$j;\
|
||||
]]]]
|
||||
|
||||
#define $macro_name(name$for j [[, p$j]], description)\$template
|
||||
class $class_name {\
|
||||
public:\
|
||||
template <typename arg_type>\
|
||||
class gmock_Impl : public ::testing::MatcherInterface<\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
|
||||
public:\
|
||||
[[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\
|
||||
$impl_inits {}\
|
||||
bool MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener) const override;\
|
||||
void DescribeTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(false);\
|
||||
}\
|
||||
void DescribeNegationTo(::std::ostream* gmock_os) const override {\
|
||||
*gmock_os << FormatDescription(true);\
|
||||
}\$param_field_decls
|
||||
private:\
|
||||
::std::string FormatDescription(bool negation) const {\
|
||||
::std::string gmock_description = (description);\
|
||||
if (!gmock_description.empty()) {\
|
||||
return gmock_description;\
|
||||
}\
|
||||
return ::testing::internal::FormatMatcherDescription(\
|
||||
negation, #name, \
|
||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||
::std::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]])));\
|
||||
}\
|
||||
};\
|
||||
template <typename arg_type>\
|
||||
operator ::testing::Matcher<arg_type>() const {\
|
||||
return ::testing::Matcher<arg_type>(\
|
||||
new gmock_Impl<arg_type>($params));\
|
||||
}\
|
||||
[[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {\
|
||||
}\$param_field_decls2
|
||||
private:\
|
||||
};\$template
|
||||
inline $class_name$param_types name($param_types_and_names) {\
|
||||
return $class_name$param_types($params);\
|
||||
}\$template
|
||||
template <typename arg_type>\
|
||||
bool $class_name$param_types::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||
const
|
||||
]]
|
||||
|
||||
|
||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||
@@ -30,7 +30,220 @@
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements some commonly used argument matchers. More
|
||||
// The MATCHER* family of macros can be used in a namespace scope to
|
||||
// define custom matchers easily.
|
||||
//
|
||||
// Basic Usage
|
||||
// ===========
|
||||
//
|
||||
// The syntax
|
||||
//
|
||||
// MATCHER(name, description_string) { statements; }
|
||||
//
|
||||
// defines a matcher with the given name that executes the statements,
|
||||
// which must return a bool to indicate if the match succeeds. Inside
|
||||
// the statements, you can refer to the value being matched by 'arg',
|
||||
// and refer to its type by 'arg_type'.
|
||||
//
|
||||
// The description string documents what the matcher does, and is used
|
||||
// to generate the failure message when the match fails. Since a
|
||||
// MATCHER() is usually defined in a header file shared by multiple
|
||||
// C++ source files, we require the description to be a C-string
|
||||
// literal to avoid possible side effects. It can be empty, in which
|
||||
// case we'll use the sequence of words in the matcher name as the
|
||||
// description.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// MATCHER(IsEven, "") { return (arg % 2) == 0; }
|
||||
//
|
||||
// allows you to write
|
||||
//
|
||||
// // Expects mock_foo.Bar(n) to be called where n is even.
|
||||
// EXPECT_CALL(mock_foo, Bar(IsEven()));
|
||||
//
|
||||
// or,
|
||||
//
|
||||
// // Verifies that the value of some_expression is even.
|
||||
// EXPECT_THAT(some_expression, IsEven());
|
||||
//
|
||||
// If the above assertion fails, it will print something like:
|
||||
//
|
||||
// Value of: some_expression
|
||||
// Expected: is even
|
||||
// Actual: 7
|
||||
//
|
||||
// where the description "is even" is automatically calculated from the
|
||||
// matcher name IsEven.
|
||||
//
|
||||
// Argument Type
|
||||
// =============
|
||||
//
|
||||
// Note that the type of the value being matched (arg_type) is
|
||||
// determined by the context in which you use the matcher and is
|
||||
// supplied to you by the compiler, so you don't need to worry about
|
||||
// declaring it (nor can you). This allows the matcher to be
|
||||
// polymorphic. For example, IsEven() can be used to match any type
|
||||
// where the value of "(arg % 2) == 0" can be implicitly converted to
|
||||
// a bool. In the "Bar(IsEven())" example above, if method Bar()
|
||||
// takes an int, 'arg_type' will be int; if it takes an unsigned long,
|
||||
// 'arg_type' will be unsigned long; and so on.
|
||||
//
|
||||
// Parameterizing Matchers
|
||||
// =======================
|
||||
//
|
||||
// Sometimes you'll want to parameterize the matcher. For that you
|
||||
// can use another macro:
|
||||
//
|
||||
// MATCHER_P(name, param_name, description_string) { statements; }
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
|
||||
//
|
||||
// will allow you to write:
|
||||
//
|
||||
// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
|
||||
//
|
||||
// which may lead to this message (assuming n is 10):
|
||||
//
|
||||
// Value of: Blah("a")
|
||||
// Expected: has absolute value 10
|
||||
// Actual: -9
|
||||
//
|
||||
// Note that both the matcher description and its parameter are
|
||||
// printed, making the message human-friendly.
|
||||
//
|
||||
// In the matcher definition body, you can write 'foo_type' to
|
||||
// reference the type of a parameter named 'foo'. For example, in the
|
||||
// body of MATCHER_P(HasAbsoluteValue, value) above, you can write
|
||||
// 'value_type' to refer to the type of 'value'.
|
||||
//
|
||||
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to
|
||||
// support multi-parameter matchers.
|
||||
//
|
||||
// Describing Parameterized Matchers
|
||||
// =================================
|
||||
//
|
||||
// The last argument to MATCHER*() is a string-typed expression. The
|
||||
// expression can reference all of the matcher's parameters and a
|
||||
// special bool-typed variable named 'negation'. When 'negation' is
|
||||
// false, the expression should evaluate to the matcher's description;
|
||||
// otherwise it should evaluate to the description of the negation of
|
||||
// the matcher. For example,
|
||||
//
|
||||
// using testing::PrintToString;
|
||||
//
|
||||
// MATCHER_P2(InClosedRange, low, hi,
|
||||
// std::string(negation ? "is not" : "is") + " in range [" +
|
||||
// PrintToString(low) + ", " + PrintToString(hi) + "]") {
|
||||
// return low <= arg && arg <= hi;
|
||||
// }
|
||||
// ...
|
||||
// EXPECT_THAT(3, InClosedRange(4, 6));
|
||||
// EXPECT_THAT(3, Not(InClosedRange(2, 4)));
|
||||
//
|
||||
// would generate two failures that contain the text:
|
||||
//
|
||||
// Expected: is in range [4, 6]
|
||||
// ...
|
||||
// Expected: is not in range [2, 4]
|
||||
//
|
||||
// If you specify "" as the description, the failure message will
|
||||
// contain the sequence of words in the matcher name followed by the
|
||||
// parameter values printed as a tuple. For example,
|
||||
//
|
||||
// MATCHER_P2(InClosedRange, low, hi, "") { ... }
|
||||
// ...
|
||||
// EXPECT_THAT(3, InClosedRange(4, 6));
|
||||
// EXPECT_THAT(3, Not(InClosedRange(2, 4)));
|
||||
//
|
||||
// would generate two failures that contain the text:
|
||||
//
|
||||
// Expected: in closed range (4, 6)
|
||||
// ...
|
||||
// Expected: not (in closed range (2, 4))
|
||||
//
|
||||
// Types of Matcher Parameters
|
||||
// ===========================
|
||||
//
|
||||
// For the purpose of typing, you can view
|
||||
//
|
||||
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
|
||||
//
|
||||
// as shorthand for
|
||||
//
|
||||
// template <typename p1_type, ..., typename pk_type>
|
||||
// FooMatcherPk<p1_type, ..., pk_type>
|
||||
// Foo(p1_type p1, ..., pk_type pk) { ... }
|
||||
//
|
||||
// When you write Foo(v1, ..., vk), the compiler infers the types of
|
||||
// the parameters v1, ..., and vk for you. If you are not happy with
|
||||
// the result of the type inference, you can specify the types by
|
||||
// explicitly instantiating the template, as in Foo<long, bool>(5,
|
||||
// false). As said earlier, you don't get to (or need to) specify
|
||||
// 'arg_type' as that's determined by the context in which the matcher
|
||||
// is used. You can assign the result of expression Foo(p1, ..., pk)
|
||||
// to a variable of type FooMatcherPk<p1_type, ..., pk_type>. This
|
||||
// can be useful when composing matchers.
|
||||
//
|
||||
// While you can instantiate a matcher template with reference types,
|
||||
// passing the parameters by pointer usually makes your code more
|
||||
// readable. If, however, you still want to pass a parameter by
|
||||
// reference, be aware that in the failure message generated by the
|
||||
// matcher you will see the value of the referenced object but not its
|
||||
// address.
|
||||
//
|
||||
// Explaining Match Results
|
||||
// ========================
|
||||
//
|
||||
// Sometimes the matcher description alone isn't enough to explain why
|
||||
// the match has failed or succeeded. For example, when expecting a
|
||||
// long string, it can be very helpful to also print the diff between
|
||||
// the expected string and the actual one. To achieve that, you can
|
||||
// optionally stream additional information to a special variable
|
||||
// named result_listener, whose type is a pointer to class
|
||||
// MatchResultListener:
|
||||
//
|
||||
// MATCHER_P(EqualsLongString, str, "") {
|
||||
// if (arg == str) return true;
|
||||
//
|
||||
// *result_listener << "the difference: "
|
||||
/// << DiffStrings(str, arg);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// Overloading Matchers
|
||||
// ====================
|
||||
//
|
||||
// You can overload matchers with different numbers of parameters:
|
||||
//
|
||||
// MATCHER_P(Blah, a, description_string1) { ... }
|
||||
// MATCHER_P2(Blah, a, b, description_string2) { ... }
|
||||
//
|
||||
// Caveats
|
||||
// =======
|
||||
//
|
||||
// When defining a new matcher, you should also consider implementing
|
||||
// MatcherInterface or using MakePolymorphicMatcher(). These
|
||||
// approaches require more work than the MATCHER* macros, but also
|
||||
// give you more control on the types of the value being matched and
|
||||
// the matcher parameters, which may leads to better compiler error
|
||||
// messages when the matcher is used wrong. They also allow
|
||||
// overloading matchers based on parameter types (as opposed to just
|
||||
// based on the number of parameters).
|
||||
//
|
||||
// MATCHER*() can only be used in a namespace scope as templates cannot be
|
||||
// declared inside of a local class.
|
||||
//
|
||||
// More Information
|
||||
// ================
|
||||
//
|
||||
// To learn more about using these macros, please search for 'MATCHER'
|
||||
// on
|
||||
// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md
|
||||
//
|
||||
// This file also implements some commonly used argument matchers. More
|
||||
// matchers can be defined by the user implementing the
|
||||
// MatcherInterface<T> interface if necessary.
|
||||
//
|
||||
@@ -57,6 +270,7 @@
|
||||
|
||||
#include "gmock/internal/gmock-internal-utils.h"
|
||||
#include "gmock/internal/gmock-port.h"
|
||||
#include "gmock/internal/gmock-pp.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
// MSVC warning C5046 is new as of VS2017 version 15.8.
|
||||
@@ -236,6 +450,50 @@ class MatcherCastImpl<T, Matcher<T> > {
|
||||
static Matcher<T> Cast(const Matcher<T>& matcher) { return matcher; }
|
||||
};
|
||||
|
||||
// Template specialization for parameterless Matcher.
|
||||
template <typename Derived>
|
||||
class MatcherBaseImpl {
|
||||
public:
|
||||
MatcherBaseImpl() = default;
|
||||
|
||||
template <typename T>
|
||||
operator ::testing::Matcher<T>() const { // NOLINT(runtime/explicit)
|
||||
return ::testing::Matcher<T>(new
|
||||
typename Derived::template gmock_Impl<T>());
|
||||
}
|
||||
};
|
||||
|
||||
// Template specialization for Matcher with parameters.
|
||||
template <template <typename...> class Derived, typename... Ts>
|
||||
class MatcherBaseImpl<Derived<Ts...>> {
|
||||
public:
|
||||
// Mark the constructor explicit for single argument T to avoid implicit
|
||||
// conversions.
|
||||
template <typename E = std::enable_if<sizeof...(Ts) == 1>,
|
||||
typename E::type* = nullptr>
|
||||
explicit MatcherBaseImpl(Ts... params)
|
||||
: params_(std::forward<Ts>(params)...) {}
|
||||
template <typename E = std::enable_if<sizeof...(Ts) != 1>,
|
||||
typename = typename E::type>
|
||||
MatcherBaseImpl(Ts... params) // NOLINT
|
||||
: params_(std::forward<Ts>(params)...) {}
|
||||
|
||||
template <typename F>
|
||||
operator ::testing::Matcher<F>() const { // NOLINT(runtime/explicit)
|
||||
return Apply<F>(MakeIndexSequence<sizeof...(Ts)>{});
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename F, std::size_t... tuple_ids>
|
||||
::testing::Matcher<F> Apply(IndexSequence<tuple_ids...>) const {
|
||||
return ::testing::Matcher<F>(
|
||||
new typename Derived<Ts...>::template gmock_Impl<F>(
|
||||
std::get<tuple_ids>(params_)...));
|
||||
}
|
||||
|
||||
const std::tuple<Ts...> params_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// In order to be safe and clear, casting between different matcher
|
||||
@@ -648,15 +906,15 @@ class StrEqualityMatcher {
|
||||
bool case_sensitive)
|
||||
: string_(str), expect_eq_(expect_eq), case_sensitive_(case_sensitive) {}
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
bool MatchAndExplain(const absl::string_view& s,
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
bool MatchAndExplain(const internal::StringView& s,
|
||||
MatchResultListener* listener) const {
|
||||
// This should fail to compile if absl::string_view is used with wide
|
||||
// This should fail to compile if StringView is used with wide
|
||||
// strings.
|
||||
const StringType& str = std::string(s);
|
||||
return MatchAndExplain(str, listener);
|
||||
}
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Accepts pointer types, particularly:
|
||||
// const char*
|
||||
@@ -674,7 +932,7 @@ class StrEqualityMatcher {
|
||||
// Matches anything that can convert to StringType.
|
||||
//
|
||||
// This is a template, not just a plain function with const StringType&,
|
||||
// because absl::string_view has some interfering non-explicit constructors.
|
||||
// because StringView has some interfering non-explicit constructors.
|
||||
template <typename MatcheeStringType>
|
||||
bool MatchAndExplain(const MatcheeStringType& s,
|
||||
MatchResultListener* /* listener */) const {
|
||||
@@ -718,15 +976,15 @@ class HasSubstrMatcher {
|
||||
explicit HasSubstrMatcher(const StringType& substring)
|
||||
: substring_(substring) {}
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
bool MatchAndExplain(const absl::string_view& s,
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
bool MatchAndExplain(const internal::StringView& s,
|
||||
MatchResultListener* listener) const {
|
||||
// This should fail to compile if absl::string_view is used with wide
|
||||
// This should fail to compile if StringView is used with wide
|
||||
// strings.
|
||||
const StringType& str = std::string(s);
|
||||
return MatchAndExplain(str, listener);
|
||||
}
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Accepts pointer types, particularly:
|
||||
// const char*
|
||||
@@ -741,7 +999,7 @@ class HasSubstrMatcher {
|
||||
// Matches anything that can convert to StringType.
|
||||
//
|
||||
// This is a template, not just a plain function with const StringType&,
|
||||
// because absl::string_view has some interfering non-explicit constructors.
|
||||
// because StringView has some interfering non-explicit constructors.
|
||||
template <typename MatcheeStringType>
|
||||
bool MatchAndExplain(const MatcheeStringType& s,
|
||||
MatchResultListener* /* listener */) const {
|
||||
@@ -774,15 +1032,15 @@ class StartsWithMatcher {
|
||||
explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) {
|
||||
}
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
bool MatchAndExplain(const absl::string_view& s,
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
bool MatchAndExplain(const internal::StringView& s,
|
||||
MatchResultListener* listener) const {
|
||||
// This should fail to compile if absl::string_view is used with wide
|
||||
// This should fail to compile if StringView is used with wide
|
||||
// strings.
|
||||
const StringType& str = std::string(s);
|
||||
return MatchAndExplain(str, listener);
|
||||
}
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Accepts pointer types, particularly:
|
||||
// const char*
|
||||
@@ -797,7 +1055,7 @@ class StartsWithMatcher {
|
||||
// Matches anything that can convert to StringType.
|
||||
//
|
||||
// This is a template, not just a plain function with const StringType&,
|
||||
// because absl::string_view has some interfering non-explicit constructors.
|
||||
// because StringView has some interfering non-explicit constructors.
|
||||
template <typename MatcheeStringType>
|
||||
bool MatchAndExplain(const MatcheeStringType& s,
|
||||
MatchResultListener* /* listener */) const {
|
||||
@@ -830,15 +1088,15 @@ class EndsWithMatcher {
|
||||
public:
|
||||
explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {}
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
bool MatchAndExplain(const absl::string_view& s,
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
bool MatchAndExplain(const internal::StringView& s,
|
||||
MatchResultListener* listener) const {
|
||||
// This should fail to compile if absl::string_view is used with wide
|
||||
// This should fail to compile if StringView is used with wide
|
||||
// strings.
|
||||
const StringType& str = std::string(s);
|
||||
return MatchAndExplain(str, listener);
|
||||
}
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Accepts pointer types, particularly:
|
||||
// const char*
|
||||
@@ -853,7 +1111,7 @@ class EndsWithMatcher {
|
||||
// Matches anything that can convert to StringType.
|
||||
//
|
||||
// This is a template, not just a plain function with const StringType&,
|
||||
// because absl::string_view has some interfering non-explicit constructors.
|
||||
// because StringView has some interfering non-explicit constructors.
|
||||
template <typename MatcheeStringType>
|
||||
bool MatchAndExplain(const MatcheeStringType& s,
|
||||
MatchResultListener* /* listener */) const {
|
||||
@@ -4555,6 +4813,156 @@ PolymorphicMatcher<internal::variant_matcher::VariantMatcher<T> > VariantWith(
|
||||
#define EXPECT_THAT(value, matcher) EXPECT_PRED_FORMAT1(\
|
||||
::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
|
||||
|
||||
// MATCHER* macroses itself are listed below.
|
||||
#define MATCHER(name, description) \
|
||||
class name##Matcher \
|
||||
: public ::testing::internal::MatcherBaseImpl<name##Matcher> { \
|
||||
public: \
|
||||
template <typename arg_type> \
|
||||
class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> { \
|
||||
public: \
|
||||
gmock_Impl() {} \
|
||||
bool MatchAndExplain( \
|
||||
const arg_type& arg, \
|
||||
::testing::MatchResultListener* result_listener) const override; \
|
||||
void DescribeTo(::std::ostream* gmock_os) const override { \
|
||||
*gmock_os << FormatDescription(false); \
|
||||
} \
|
||||
void DescribeNegationTo(::std::ostream* gmock_os) const override { \
|
||||
*gmock_os << FormatDescription(true); \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
::std::string FormatDescription(bool negation) const { \
|
||||
::std::string gmock_description = (description); \
|
||||
if (!gmock_description.empty()) { \
|
||||
return gmock_description; \
|
||||
} \
|
||||
return ::testing::internal::FormatMatcherDescription(negation, #name, \
|
||||
{}); \
|
||||
} \
|
||||
}; \
|
||||
}; \
|
||||
GTEST_ATTRIBUTE_UNUSED_ inline name##Matcher name() { return {}; } \
|
||||
template <typename arg_type> \
|
||||
bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain( \
|
||||
const arg_type& arg, \
|
||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_) \
|
||||
const
|
||||
|
||||
#define MATCHER_P(name, p0, description) \
|
||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (p0))
|
||||
#define MATCHER_P2(name, p0, p1, description) \
|
||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP2, description, (p0, p1))
|
||||
#define MATCHER_P3(name, p0, p1, p2, description) \
|
||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP3, description, (p0, p1, p2))
|
||||
#define MATCHER_P4(name, p0, p1, p2, p3, description) \
|
||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP4, description, (p0, p1, p2, p3))
|
||||
#define MATCHER_P5(name, p0, p1, p2, p3, p4, description) \
|
||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP5, description, \
|
||||
(p0, p1, p2, p3, p4))
|
||||
#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description) \
|
||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP6, description, \
|
||||
(p0, p1, p2, p3, p4, p5))
|
||||
#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description) \
|
||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP7, description, \
|
||||
(p0, p1, p2, p3, p4, p5, p6))
|
||||
#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description) \
|
||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP8, description, \
|
||||
(p0, p1, p2, p3, p4, p5, p6, p7))
|
||||
#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description) \
|
||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP9, description, \
|
||||
(p0, p1, p2, p3, p4, p5, p6, p7, p8))
|
||||
#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description) \
|
||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP10, description, \
|
||||
(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9))
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER(name, full_name, description, args) \
|
||||
template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \
|
||||
class full_name : public ::testing::internal::MatcherBaseImpl< \
|
||||
full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>> { \
|
||||
public: \
|
||||
using full_name::MatcherBaseImpl::MatcherBaseImpl; \
|
||||
template <typename arg_type> \
|
||||
class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> { \
|
||||
public: \
|
||||
explicit gmock_Impl(GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args)) \
|
||||
: GMOCK_INTERNAL_MATCHER_FORWARD_ARGS(args) {} \
|
||||
bool MatchAndExplain( \
|
||||
const arg_type& arg, \
|
||||
::testing::MatchResultListener* result_listener) const override; \
|
||||
void DescribeTo(::std::ostream* gmock_os) const override { \
|
||||
*gmock_os << FormatDescription(false); \
|
||||
} \
|
||||
void DescribeNegationTo(::std::ostream* gmock_os) const override { \
|
||||
*gmock_os << FormatDescription(true); \
|
||||
} \
|
||||
GMOCK_INTERNAL_MATCHER_MEMBERS(args) \
|
||||
\
|
||||
private: \
|
||||
::std::string FormatDescription(bool negation) const { \
|
||||
::std::string gmock_description = (description); \
|
||||
if (!gmock_description.empty()) { \
|
||||
return gmock_description; \
|
||||
} \
|
||||
return ::testing::internal::FormatMatcherDescription( \
|
||||
negation, #name, \
|
||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings( \
|
||||
::std::tuple<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>( \
|
||||
GMOCK_INTERNAL_MATCHER_MEMBERS_USAGE(args)))); \
|
||||
} \
|
||||
}; \
|
||||
}; \
|
||||
template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \
|
||||
inline full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)> name( \
|
||||
GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args)) { \
|
||||
return full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>( \
|
||||
GMOCK_INTERNAL_MATCHER_ARGS_USAGE(args)); \
|
||||
} \
|
||||
template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \
|
||||
template <typename arg_type> \
|
||||
bool full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>::gmock_Impl< \
|
||||
arg_type>::MatchAndExplain(const arg_type& arg, \
|
||||
::testing::MatchResultListener* \
|
||||
result_listener GTEST_ATTRIBUTE_UNUSED_) \
|
||||
const
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args) \
|
||||
GMOCK_PP_TAIL( \
|
||||
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAM, , args))
|
||||
#define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAM(i_unused, data_unused, arg) \
|
||||
, typename arg##_type
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args) \
|
||||
GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_TYPE_PARAM, , args))
|
||||
#define GMOCK_INTERNAL_MATCHER_TYPE_PARAM(i_unused, data_unused, arg) \
|
||||
, arg##_type
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args) \
|
||||
GMOCK_PP_TAIL(dummy_first GMOCK_PP_FOR_EACH( \
|
||||
GMOCK_INTERNAL_MATCHER_FUNCTION_ARG, , args))
|
||||
#define GMOCK_INTERNAL_MATCHER_FUNCTION_ARG(i, data_unused, arg) \
|
||||
, arg##_type gmock_p##i
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_FORWARD_ARGS(args) \
|
||||
GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_FORWARD_ARG, , args))
|
||||
#define GMOCK_INTERNAL_MATCHER_FORWARD_ARG(i, data_unused, arg) \
|
||||
, arg(::std::forward<arg##_type>(gmock_p##i))
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_MEMBERS(args) \
|
||||
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_MEMBER, , args)
|
||||
#define GMOCK_INTERNAL_MATCHER_MEMBER(i_unused, data_unused, arg) \
|
||||
const arg##_type arg;
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_MEMBERS_USAGE(args) \
|
||||
GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_MEMBER_USAGE, , args))
|
||||
#define GMOCK_INTERNAL_MATCHER_MEMBER_USAGE(i_unused, data_unused, arg) , arg
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_ARGS_USAGE(args) \
|
||||
GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_ARG_USAGE, , args))
|
||||
#define GMOCK_INTERNAL_MATCHER_ARG_USAGE(i, data_unused, arg_unused) \
|
||||
, gmock_p##i
|
||||
|
||||
} // namespace testing
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 5046
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements some matchers that depend on gmock-generated-matchers.h.
|
||||
// This file implements some matchers that depend on gmock-matchers.h.
|
||||
//
|
||||
// Note that tests are implemented in gmock-matchers_test.cc rather than
|
||||
// gmock-more-matchers-test.cc.
|
||||
@@ -40,7 +40,7 @@
|
||||
#ifndef GMOCK_INCLUDE_GMOCK_MORE_MATCHERS_H_
|
||||
#define GMOCK_INCLUDE_GMOCK_MORE_MATCHERS_H_
|
||||
|
||||
#include "gmock/gmock-generated-matchers.h"
|
||||
#include "gmock/gmock-matchers.h"
|
||||
|
||||
namespace testing {
|
||||
|
||||
|
||||
@@ -60,8 +60,6 @@
|
||||
#include "gmock/gmock-cardinalities.h"
|
||||
#include "gmock/gmock-function-mocker.h"
|
||||
#include "gmock/gmock-generated-actions.h"
|
||||
#include "gmock/gmock-generated-function-mockers.h"
|
||||
#include "gmock/gmock-generated-matchers.h"
|
||||
#include "gmock/gmock-matchers.h"
|
||||
#include "gmock/gmock-more-actions.h"
|
||||
#include "gmock/gmock-more-matchers.h"
|
||||
|
||||
@@ -86,6 +86,14 @@
|
||||
#define GMOCK_PP_IF(_Cond, _Then, _Else) \
|
||||
GMOCK_PP_CAT(GMOCK_PP_INTERNAL_IF_, _Cond)(_Then, _Else)
|
||||
|
||||
// Similar to GMOCK_PP_IF but takes _Then and _Else in parentheses.
|
||||
//
|
||||
// GMOCK_PP_GENERIC_IF(1, (a, b, c), (d, e, f)) => a, b, c
|
||||
// GMOCK_PP_GENERIC_IF(0, (a, b, c), (d, e, f)) => d, e, f
|
||||
//
|
||||
#define GMOCK_PP_GENERIC_IF(_Cond, _Then, _Else) \
|
||||
GMOCK_PP_REMOVE_PARENS(GMOCK_PP_IF(_Cond, _Then, _Else))
|
||||
|
||||
// Evaluates to the number of arguments after expansion. Identifies 'empty' as
|
||||
// 0.
|
||||
//
|
||||
|
||||
+1473
-1461
@@ -30,11 +30,11 @@
|
||||
|
||||
|
||||
try:
|
||||
# Python 3.x
|
||||
import builtins
|
||||
# Python 3.x
|
||||
import builtins
|
||||
except ImportError:
|
||||
# Python 2.x
|
||||
import __builtin__ as builtins
|
||||
# Python 2.x
|
||||
import __builtin__ as builtins
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
@@ -45,15 +45,15 @@ from cpp import utils
|
||||
|
||||
|
||||
if not hasattr(builtins, 'reversed'):
|
||||
# Support Python 2.3 and earlier.
|
||||
def reversed(seq):
|
||||
for i in range(len(seq)-1, -1, -1):
|
||||
yield seq[i]
|
||||
# Support Python 2.3 and earlier.
|
||||
def reversed(seq):
|
||||
for i in range(len(seq)-1, -1, -1):
|
||||
yield seq[i]
|
||||
|
||||
if not hasattr(builtins, 'next'):
|
||||
# Support Python 2.5 and earlier.
|
||||
def next(obj):
|
||||
return obj.next()
|
||||
# Support Python 2.5 and earlier.
|
||||
def next(obj):
|
||||
return obj.next()
|
||||
|
||||
|
||||
VISIBILITY_PUBLIC, VISIBILITY_PROTECTED, VISIBILITY_PRIVATE = range(3)
|
||||
@@ -98,1598 +98,1610 @@ _NAMESPACE_POP = 'ns-pop'
|
||||
# TODO(nnorwitz): use this as a singleton for templated_types, etc
|
||||
# where we don't want to create a new empty dict each time. It is also const.
|
||||
class _NullDict(object):
|
||||
__contains__ = lambda self: False
|
||||
keys = values = items = iterkeys = itervalues = iteritems = lambda self: ()
|
||||
__contains__ = lambda self: False
|
||||
keys = values = items = iterkeys = itervalues = iteritems = lambda self: ()
|
||||
|
||||
|
||||
# TODO(nnorwitz): move AST nodes into a separate module.
|
||||
class Node(object):
|
||||
"""Base AST node."""
|
||||
"""Base AST node."""
|
||||
|
||||
def __init__(self, start, end):
|
||||
self.start = start
|
||||
self.end = end
|
||||
def __init__(self, start, end):
|
||||
self.start = start
|
||||
self.end = end
|
||||
|
||||
def IsDeclaration(self):
|
||||
"""Returns bool if this node is a declaration."""
|
||||
return False
|
||||
def IsDeclaration(self):
|
||||
"""Returns bool if this node is a declaration."""
|
||||
return False
|
||||
|
||||
def IsDefinition(self):
|
||||
"""Returns bool if this node is a definition."""
|
||||
return False
|
||||
def IsDefinition(self):
|
||||
"""Returns bool if this node is a definition."""
|
||||
return False
|
||||
|
||||
def IsExportable(self):
|
||||
"""Returns bool if this node exportable from a header file."""
|
||||
return False
|
||||
def IsExportable(self):
|
||||
"""Returns bool if this node exportable from a header file."""
|
||||
return False
|
||||
|
||||
def Requires(self, node):
|
||||
"""Does this AST node require the definition of the node passed in?"""
|
||||
return False
|
||||
def Requires(self, node):
|
||||
"""Does this AST node require the definition of the node passed in?"""
|
||||
return False
|
||||
|
||||
def XXX__str__(self):
|
||||
return self._StringHelper(self.__class__.__name__, '')
|
||||
def XXX__str__(self):
|
||||
return self._StringHelper(self.__class__.__name__, '')
|
||||
|
||||
def _StringHelper(self, name, suffix):
|
||||
if not utils.DEBUG:
|
||||
return '%s(%s)' % (name, suffix)
|
||||
return '%s(%d, %d, %s)' % (name, self.start, self.end, suffix)
|
||||
def _StringHelper(self, name, suffix):
|
||||
if not utils.DEBUG:
|
||||
return '%s(%s)' % (name, suffix)
|
||||
return '%s(%d, %d, %s)' % (name, self.start, self.end, suffix)
|
||||
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
|
||||
|
||||
class Define(Node):
|
||||
def __init__(self, start, end, name, definition):
|
||||
Node.__init__(self, start, end)
|
||||
self.name = name
|
||||
self.definition = definition
|
||||
def __init__(self, start, end, name, definition):
|
||||
Node.__init__(self, start, end)
|
||||
self.name = name
|
||||
self.definition = definition
|
||||
|
||||
def __str__(self):
|
||||
value = '%s %s' % (self.name, self.definition)
|
||||
return self._StringHelper(self.__class__.__name__, value)
|
||||
def __str__(self):
|
||||
value = '%s %s' % (self.name, self.definition)
|
||||
return self._StringHelper(self.__class__.__name__, value)
|
||||
|
||||
|
||||
class Include(Node):
|
||||
def __init__(self, start, end, filename, system):
|
||||
Node.__init__(self, start, end)
|
||||
self.filename = filename
|
||||
self.system = system
|
||||
def __init__(self, start, end, filename, system):
|
||||
Node.__init__(self, start, end)
|
||||
self.filename = filename
|
||||
self.system = system
|
||||
|
||||
def __str__(self):
|
||||
fmt = '"%s"'
|
||||
if self.system:
|
||||
fmt = '<%s>'
|
||||
return self._StringHelper(self.__class__.__name__, fmt % self.filename)
|
||||
def __str__(self):
|
||||
fmt = '"%s"'
|
||||
if self.system:
|
||||
fmt = '<%s>'
|
||||
return self._StringHelper(self.__class__.__name__, fmt % self.filename)
|
||||
|
||||
|
||||
class Goto(Node):
|
||||
def __init__(self, start, end, label):
|
||||
Node.__init__(self, start, end)
|
||||
self.label = label
|
||||
def __init__(self, start, end, label):
|
||||
Node.__init__(self, start, end)
|
||||
self.label = label
|
||||
|
||||
def __str__(self):
|
||||
return self._StringHelper(self.__class__.__name__, str(self.label))
|
||||
def __str__(self):
|
||||
return self._StringHelper(self.__class__.__name__, str(self.label))
|
||||
|
||||
|
||||
class Expr(Node):
|
||||
def __init__(self, start, end, expr):
|
||||
Node.__init__(self, start, end)
|
||||
self.expr = expr
|
||||
def __init__(self, start, end, expr):
|
||||
Node.__init__(self, start, end)
|
||||
self.expr = expr
|
||||
|
||||
def Requires(self, node):
|
||||
# TODO(nnorwitz): impl.
|
||||
return False
|
||||
def Requires(self, node):
|
||||
# TODO(nnorwitz): impl.
|
||||
return False
|
||||
|
||||
def __str__(self):
|
||||
return self._StringHelper(self.__class__.__name__, str(self.expr))
|
||||
def __str__(self):
|
||||
return self._StringHelper(self.__class__.__name__, str(self.expr))
|
||||
|
||||
|
||||
class Return(Expr):
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
class Delete(Expr):
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
class Friend(Expr):
|
||||
def __init__(self, start, end, expr, namespace):
|
||||
Expr.__init__(self, start, end, expr)
|
||||
self.namespace = namespace[:]
|
||||
def __init__(self, start, end, expr, namespace):
|
||||
Expr.__init__(self, start, end, expr)
|
||||
self.namespace = namespace[:]
|
||||
|
||||
|
||||
class Using(Node):
|
||||
def __init__(self, start, end, names):
|
||||
Node.__init__(self, start, end)
|
||||
self.names = names
|
||||
def __init__(self, start, end, names):
|
||||
Node.__init__(self, start, end)
|
||||
self.names = names
|
||||
|
||||
def __str__(self):
|
||||
return self._StringHelper(self.__class__.__name__, str(self.names))
|
||||
def __str__(self):
|
||||
return self._StringHelper(self.__class__.__name__, str(self.names))
|
||||
|
||||
|
||||
class Parameter(Node):
|
||||
def __init__(self, start, end, name, parameter_type, default):
|
||||
Node.__init__(self, start, end)
|
||||
self.name = name
|
||||
self.type = parameter_type
|
||||
self.default = default
|
||||
def __init__(self, start, end, name, parameter_type, default):
|
||||
Node.__init__(self, start, end)
|
||||
self.name = name
|
||||
self.type = parameter_type
|
||||
self.default = default
|
||||
|
||||
def Requires(self, node):
|
||||
# TODO(nnorwitz): handle namespaces, etc.
|
||||
return self.type.name == node.name
|
||||
def Requires(self, node):
|
||||
# TODO(nnorwitz): handle namespaces, etc.
|
||||
return self.type.name == node.name
|
||||
|
||||
def __str__(self):
|
||||
name = str(self.type)
|
||||
suffix = '%s %s' % (name, self.name)
|
||||
if self.default:
|
||||
suffix += ' = ' + ''.join([d.name for d in self.default])
|
||||
return self._StringHelper(self.__class__.__name__, suffix)
|
||||
def __str__(self):
|
||||
name = str(self.type)
|
||||
suffix = '%s %s' % (name, self.name)
|
||||
if self.default:
|
||||
suffix += ' = ' + ''.join([d.name for d in self.default])
|
||||
return self._StringHelper(self.__class__.__name__, suffix)
|
||||
|
||||
|
||||
class _GenericDeclaration(Node):
|
||||
def __init__(self, start, end, name, namespace):
|
||||
Node.__init__(self, start, end)
|
||||
self.name = name
|
||||
self.namespace = namespace[:]
|
||||
def __init__(self, start, end, name, namespace):
|
||||
Node.__init__(self, start, end)
|
||||
self.name = name
|
||||
self.namespace = namespace[:]
|
||||
|
||||
def FullName(self):
|
||||
prefix = ''
|
||||
if self.namespace and self.namespace[-1]:
|
||||
prefix = '::'.join(self.namespace) + '::'
|
||||
return prefix + self.name
|
||||
def FullName(self):
|
||||
prefix = ''
|
||||
if self.namespace and self.namespace[-1]:
|
||||
prefix = '::'.join(self.namespace) + '::'
|
||||
return prefix + self.name
|
||||
|
||||
def _TypeStringHelper(self, suffix):
|
||||
if self.namespace:
|
||||
names = [n or '<anonymous>' for n in self.namespace]
|
||||
suffix += ' in ' + '::'.join(names)
|
||||
return self._StringHelper(self.__class__.__name__, suffix)
|
||||
def _TypeStringHelper(self, suffix):
|
||||
if self.namespace:
|
||||
names = [n or '<anonymous>' for n in self.namespace]
|
||||
suffix += ' in ' + '::'.join(names)
|
||||
return self._StringHelper(self.__class__.__name__, suffix)
|
||||
|
||||
|
||||
# TODO(nnorwitz): merge with Parameter in some way?
|
||||
class VariableDeclaration(_GenericDeclaration):
|
||||
def __init__(self, start, end, name, var_type, initial_value, namespace):
|
||||
_GenericDeclaration.__init__(self, start, end, name, namespace)
|
||||
self.type = var_type
|
||||
self.initial_value = initial_value
|
||||
def __init__(self, start, end, name, var_type, initial_value, namespace):
|
||||
_GenericDeclaration.__init__(self, start, end, name, namespace)
|
||||
self.type = var_type
|
||||
self.initial_value = initial_value
|
||||
|
||||
def Requires(self, node):
|
||||
# TODO(nnorwitz): handle namespaces, etc.
|
||||
return self.type.name == node.name
|
||||
def Requires(self, node):
|
||||
# TODO(nnorwitz): handle namespaces, etc.
|
||||
return self.type.name == node.name
|
||||
|
||||
def ToString(self):
|
||||
"""Return a string that tries to reconstitute the variable decl."""
|
||||
suffix = '%s %s' % (self.type, self.name)
|
||||
if self.initial_value:
|
||||
suffix += ' = ' + self.initial_value
|
||||
return suffix
|
||||
def ToString(self):
|
||||
"""Return a string that tries to reconstitute the variable decl."""
|
||||
suffix = '%s %s' % (self.type, self.name)
|
||||
if self.initial_value:
|
||||
suffix += ' = ' + self.initial_value
|
||||
return suffix
|
||||
|
||||
def __str__(self):
|
||||
return self._StringHelper(self.__class__.__name__, self.ToString())
|
||||
def __str__(self):
|
||||
return self._StringHelper(self.__class__.__name__, self.ToString())
|
||||
|
||||
|
||||
class Typedef(_GenericDeclaration):
|
||||
def __init__(self, start, end, name, alias, namespace):
|
||||
_GenericDeclaration.__init__(self, start, end, name, namespace)
|
||||
self.alias = alias
|
||||
def __init__(self, start, end, name, alias, namespace):
|
||||
_GenericDeclaration.__init__(self, start, end, name, namespace)
|
||||
self.alias = alias
|
||||
|
||||
def IsDefinition(self):
|
||||
def IsDefinition(self):
|
||||
return True
|
||||
|
||||
def IsExportable(self):
|
||||
return True
|
||||
|
||||
def Requires(self, node):
|
||||
# TODO(nnorwitz): handle namespaces, etc.
|
||||
name = node.name
|
||||
for token in self.alias:
|
||||
if token is not None and name == token.name:
|
||||
return True
|
||||
return False
|
||||
|
||||
def IsExportable(self):
|
||||
return True
|
||||
|
||||
def Requires(self, node):
|
||||
# TODO(nnorwitz): handle namespaces, etc.
|
||||
name = node.name
|
||||
for token in self.alias:
|
||||
if token is not None and name == token.name:
|
||||
return True
|
||||
return False
|
||||
|
||||
def __str__(self):
|
||||
suffix = '%s, %s' % (self.name, self.alias)
|
||||
return self._TypeStringHelper(suffix)
|
||||
def __str__(self):
|
||||
suffix = '%s, %s' % (self.name, self.alias)
|
||||
return self._TypeStringHelper(suffix)
|
||||
|
||||
|
||||
class _NestedType(_GenericDeclaration):
|
||||
def __init__(self, start, end, name, fields, namespace):
|
||||
_GenericDeclaration.__init__(self, start, end, name, namespace)
|
||||
self.fields = fields
|
||||
def __init__(self, start, end, name, fields, namespace):
|
||||
_GenericDeclaration.__init__(self, start, end, name, namespace)
|
||||
self.fields = fields
|
||||
|
||||
def IsDefinition(self):
|
||||
return True
|
||||
def IsDefinition(self):
|
||||
return True
|
||||
|
||||
def IsExportable(self):
|
||||
return True
|
||||
def IsExportable(self):
|
||||
return True
|
||||
|
||||
def __str__(self):
|
||||
suffix = '%s, {%s}' % (self.name, self.fields)
|
||||
return self._TypeStringHelper(suffix)
|
||||
def __str__(self):
|
||||
suffix = '%s, {%s}' % (self.name, self.fields)
|
||||
return self._TypeStringHelper(suffix)
|
||||
|
||||
|
||||
class Union(_NestedType):
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
class Enum(_NestedType):
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
class Class(_GenericDeclaration):
|
||||
def __init__(self, start, end, name, bases, templated_types, body, namespace):
|
||||
_GenericDeclaration.__init__(self, start, end, name, namespace)
|
||||
self.bases = bases
|
||||
self.body = body
|
||||
self.templated_types = templated_types
|
||||
def __init__(self, start, end, name, bases, templated_types, body, namespace):
|
||||
_GenericDeclaration.__init__(self, start, end, name, namespace)
|
||||
self.bases = bases
|
||||
self.body = body
|
||||
self.templated_types = templated_types
|
||||
|
||||
def IsDeclaration(self):
|
||||
return self.bases is None and self.body is None
|
||||
def IsDeclaration(self):
|
||||
return self.bases is None and self.body is None
|
||||
|
||||
def IsDefinition(self):
|
||||
return not self.IsDeclaration()
|
||||
def IsDefinition(self):
|
||||
return not self.IsDeclaration()
|
||||
|
||||
def IsExportable(self):
|
||||
return not self.IsDeclaration()
|
||||
def IsExportable(self):
|
||||
return not self.IsDeclaration()
|
||||
|
||||
def Requires(self, node):
|
||||
# TODO(nnorwitz): handle namespaces, etc.
|
||||
if self.bases:
|
||||
for token_list in self.bases:
|
||||
# TODO(nnorwitz): bases are tokens, do name comparision.
|
||||
for token in token_list:
|
||||
if token.name == node.name:
|
||||
return True
|
||||
# TODO(nnorwitz): search in body too.
|
||||
return False
|
||||
def Requires(self, node):
|
||||
# TODO(nnorwitz): handle namespaces, etc.
|
||||
if self.bases:
|
||||
for token_list in self.bases:
|
||||
# TODO(nnorwitz): bases are tokens, do name comparision.
|
||||
for token in token_list:
|
||||
if token.name == node.name:
|
||||
return True
|
||||
# TODO(nnorwitz): search in body too.
|
||||
return False
|
||||
|
||||
def __str__(self):
|
||||
name = self.name
|
||||
if self.templated_types:
|
||||
name += '<%s>' % self.templated_types
|
||||
suffix = '%s, %s, %s' % (name, self.bases, self.body)
|
||||
return self._TypeStringHelper(suffix)
|
||||
def __str__(self):
|
||||
name = self.name
|
||||
if self.templated_types:
|
||||
name += '<%s>' % self.templated_types
|
||||
suffix = '%s, %s, %s' % (name, self.bases, self.body)
|
||||
return self._TypeStringHelper(suffix)
|
||||
|
||||
|
||||
class Struct(Class):
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
class Function(_GenericDeclaration):
|
||||
def __init__(self, start, end, name, return_type, parameters,
|
||||
modifiers, templated_types, body, namespace):
|
||||
_GenericDeclaration.__init__(self, start, end, name, namespace)
|
||||
converter = TypeConverter(namespace)
|
||||
self.return_type = converter.CreateReturnType(return_type)
|
||||
self.parameters = converter.ToParameters(parameters)
|
||||
self.modifiers = modifiers
|
||||
self.body = body
|
||||
self.templated_types = templated_types
|
||||
def __init__(self, start, end, name, return_type, parameters,
|
||||
modifiers, templated_types, body, namespace):
|
||||
_GenericDeclaration.__init__(self, start, end, name, namespace)
|
||||
converter = TypeConverter(namespace)
|
||||
self.return_type = converter.CreateReturnType(return_type)
|
||||
self.parameters = converter.ToParameters(parameters)
|
||||
self.modifiers = modifiers
|
||||
self.body = body
|
||||
self.templated_types = templated_types
|
||||
|
||||
def IsDeclaration(self):
|
||||
return self.body is None
|
||||
def IsDeclaration(self):
|
||||
return self.body is None
|
||||
|
||||
def IsDefinition(self):
|
||||
return self.body is not None
|
||||
def IsDefinition(self):
|
||||
return self.body is not None
|
||||
|
||||
def IsExportable(self):
|
||||
if self.return_type and 'static' in self.return_type.modifiers:
|
||||
return False
|
||||
return None not in self.namespace
|
||||
def IsExportable(self):
|
||||
if self.return_type and 'static' in self.return_type.modifiers:
|
||||
return False
|
||||
return None not in self.namespace
|
||||
|
||||
def Requires(self, node):
|
||||
if self.parameters:
|
||||
# TODO(nnorwitz): parameters are tokens, do name comparision.
|
||||
for p in self.parameters:
|
||||
if p.name == node.name:
|
||||
return True
|
||||
# TODO(nnorwitz): search in body too.
|
||||
return False
|
||||
def Requires(self, node):
|
||||
if self.parameters:
|
||||
# TODO(nnorwitz): parameters are tokens, do name comparision.
|
||||
for p in self.parameters:
|
||||
if p.name == node.name:
|
||||
return True
|
||||
# TODO(nnorwitz): search in body too.
|
||||
return False
|
||||
|
||||
def __str__(self):
|
||||
# TODO(nnorwitz): add templated_types.
|
||||
suffix = ('%s %s(%s), 0x%02x, %s' %
|
||||
(self.return_type, self.name, self.parameters,
|
||||
self.modifiers, self.body))
|
||||
return self._TypeStringHelper(suffix)
|
||||
def __str__(self):
|
||||
# TODO(nnorwitz): add templated_types.
|
||||
suffix = ('%s %s(%s), 0x%02x, %s' %
|
||||
(self.return_type, self.name, self.parameters,
|
||||
self.modifiers, self.body))
|
||||
return self._TypeStringHelper(suffix)
|
||||
|
||||
|
||||
class Method(Function):
|
||||
def __init__(self, start, end, name, in_class, return_type, parameters,
|
||||
modifiers, templated_types, body, namespace):
|
||||
Function.__init__(self, start, end, name, return_type, parameters,
|
||||
modifiers, templated_types, body, namespace)
|
||||
# TODO(nnorwitz): in_class could also be a namespace which can
|
||||
# mess up finding functions properly.
|
||||
self.in_class = in_class
|
||||
def __init__(self, start, end, name, in_class, return_type, parameters,
|
||||
modifiers, templated_types, body, namespace):
|
||||
Function.__init__(self, start, end, name, return_type, parameters,
|
||||
modifiers, templated_types, body, namespace)
|
||||
# TODO(nnorwitz): in_class could also be a namespace which can
|
||||
# mess up finding functions properly.
|
||||
self.in_class = in_class
|
||||
|
||||
|
||||
class Type(_GenericDeclaration):
|
||||
"""Type used for any variable (eg class, primitive, struct, etc)."""
|
||||
"""Type used for any variable (eg class, primitive, struct, etc)."""
|
||||
|
||||
def __init__(self, start, end, name, templated_types, modifiers,
|
||||
reference, pointer, array):
|
||||
"""
|
||||
def __init__(self, start, end, name, templated_types, modifiers,
|
||||
reference, pointer, array):
|
||||
"""
|
||||
Args:
|
||||
name: str name of main type
|
||||
templated_types: [Class (Type?)] template type info between <>
|
||||
modifiers: [str] type modifiers (keywords) eg, const, mutable, etc.
|
||||
reference, pointer, array: bools
|
||||
"""
|
||||
_GenericDeclaration.__init__(self, start, end, name, [])
|
||||
self.templated_types = templated_types
|
||||
if not name and modifiers:
|
||||
self.name = modifiers.pop()
|
||||
self.modifiers = modifiers
|
||||
self.reference = reference
|
||||
self.pointer = pointer
|
||||
self.array = array
|
||||
_GenericDeclaration.__init__(self, start, end, name, [])
|
||||
self.templated_types = templated_types
|
||||
if not name and modifiers:
|
||||
self.name = modifiers.pop()
|
||||
self.modifiers = modifiers
|
||||
self.reference = reference
|
||||
self.pointer = pointer
|
||||
self.array = array
|
||||
|
||||
def __str__(self):
|
||||
prefix = ''
|
||||
if self.modifiers:
|
||||
prefix = ' '.join(self.modifiers) + ' '
|
||||
name = str(self.name)
|
||||
if self.templated_types:
|
||||
name += '<%s>' % self.templated_types
|
||||
suffix = prefix + name
|
||||
if self.reference:
|
||||
suffix += '&'
|
||||
if self.pointer:
|
||||
suffix += '*'
|
||||
if self.array:
|
||||
suffix += '[]'
|
||||
return self._TypeStringHelper(suffix)
|
||||
def __str__(self):
|
||||
prefix = ''
|
||||
if self.modifiers:
|
||||
prefix = ' '.join(self.modifiers) + ' '
|
||||
name = str(self.name)
|
||||
if self.templated_types:
|
||||
name += '<%s>' % self.templated_types
|
||||
suffix = prefix + name
|
||||
if self.reference:
|
||||
suffix += '&'
|
||||
if self.pointer:
|
||||
suffix += '*'
|
||||
if self.array:
|
||||
suffix += '[]'
|
||||
return self._TypeStringHelper(suffix)
|
||||
|
||||
# By definition, Is* are always False. A Type can only exist in
|
||||
# some sort of variable declaration, parameter, or return value.
|
||||
def IsDeclaration(self):
|
||||
return False
|
||||
# By definition, Is* are always False. A Type can only exist in
|
||||
# some sort of variable declaration, parameter, or return value.
|
||||
def IsDeclaration(self):
|
||||
return False
|
||||
|
||||
def IsDefinition(self):
|
||||
return False
|
||||
def IsDefinition(self):
|
||||
return False
|
||||
|
||||
def IsExportable(self):
|
||||
return False
|
||||
def IsExportable(self):
|
||||
return False
|
||||
|
||||
|
||||
class TypeConverter(object):
|
||||
|
||||
def __init__(self, namespace_stack):
|
||||
self.namespace_stack = namespace_stack
|
||||
def __init__(self, namespace_stack):
|
||||
self.namespace_stack = namespace_stack
|
||||
|
||||
def _GetTemplateEnd(self, tokens, start):
|
||||
count = 1
|
||||
end = start
|
||||
while 1:
|
||||
token = tokens[end]
|
||||
end += 1
|
||||
if token.name == '<':
|
||||
count += 1
|
||||
elif token.name == '>':
|
||||
count -= 1
|
||||
if count == 0:
|
||||
break
|
||||
return tokens[start:end-1], end
|
||||
def _GetTemplateEnd(self, tokens, start):
|
||||
count = 1
|
||||
end = start
|
||||
while 1:
|
||||
token = tokens[end]
|
||||
end += 1
|
||||
if token.name == '<':
|
||||
count += 1
|
||||
elif token.name == '>':
|
||||
count -= 1
|
||||
if count == 0:
|
||||
break
|
||||
return tokens[start:end-1], end
|
||||
|
||||
def ToType(self, tokens):
|
||||
"""Convert [Token,...] to [Class(...), ] useful for base classes.
|
||||
def ToType(self, tokens):
|
||||
"""Convert [Token,...] to [Class(...), ] useful for base classes.
|
||||
For example, code like class Foo : public Bar<x, y> { ... };
|
||||
the "Bar<x, y>" portion gets converted to an AST.
|
||||
|
||||
Returns:
|
||||
[Class(...), ...]
|
||||
"""
|
||||
result = []
|
||||
name_tokens = []
|
||||
result = []
|
||||
name_tokens = []
|
||||
reference = pointer = array = False
|
||||
|
||||
def AddType(templated_types):
|
||||
# Partition tokens into name and modifier tokens.
|
||||
names = []
|
||||
modifiers = []
|
||||
for t in name_tokens:
|
||||
if keywords.IsKeyword(t.name):
|
||||
modifiers.append(t.name)
|
||||
else:
|
||||
names.append(t.name)
|
||||
name = ''.join(names)
|
||||
if name_tokens:
|
||||
result.append(Type(name_tokens[0].start, name_tokens[-1].end,
|
||||
name, templated_types, modifiers,
|
||||
reference, pointer, array))
|
||||
del name_tokens[:]
|
||||
|
||||
i = 0
|
||||
end = len(tokens)
|
||||
while i < end:
|
||||
token = tokens[i]
|
||||
if token.name == '<':
|
||||
new_tokens, new_end = self._GetTemplateEnd(tokens, i+1)
|
||||
AddType(self.ToType(new_tokens))
|
||||
# If there is a comma after the template, we need to consume
|
||||
# that here otherwise it becomes part of the name.
|
||||
i = new_end
|
||||
reference = pointer = array = False
|
||||
elif token.name == ',':
|
||||
AddType([])
|
||||
reference = pointer = array = False
|
||||
elif token.name == '*':
|
||||
pointer = True
|
||||
elif token.name == '&':
|
||||
reference = True
|
||||
elif token.name == '[':
|
||||
pointer = True
|
||||
elif token.name == ']':
|
||||
pass
|
||||
else:
|
||||
name_tokens.append(token)
|
||||
i += 1
|
||||
|
||||
def AddType(templated_types):
|
||||
# Partition tokens into name and modifier tokens.
|
||||
names = []
|
||||
modifiers = []
|
||||
for t in name_tokens:
|
||||
if keywords.IsKeyword(t.name):
|
||||
modifiers.append(t.name)
|
||||
else:
|
||||
names.append(t.name)
|
||||
name = ''.join(names)
|
||||
if name_tokens:
|
||||
result.append(Type(name_tokens[0].start, name_tokens[-1].end,
|
||||
name, templated_types, modifiers,
|
||||
reference, pointer, array))
|
||||
del name_tokens[:]
|
||||
if name_tokens:
|
||||
# No '<' in the tokens, just a simple name and no template.
|
||||
AddType([])
|
||||
return result
|
||||
|
||||
i = 0
|
||||
end = len(tokens)
|
||||
while i < end:
|
||||
token = tokens[i]
|
||||
if token.name == '<':
|
||||
new_tokens, new_end = self._GetTemplateEnd(tokens, i+1)
|
||||
AddType(self.ToType(new_tokens))
|
||||
# If there is a comma after the template, we need to consume
|
||||
# that here otherwise it becomes part of the name.
|
||||
i = new_end
|
||||
reference = pointer = array = False
|
||||
elif token.name == ',':
|
||||
AddType([])
|
||||
reference = pointer = array = False
|
||||
elif token.name == '*':
|
||||
pointer = True
|
||||
elif token.name == '&':
|
||||
reference = True
|
||||
elif token.name == '[':
|
||||
pointer = True
|
||||
elif token.name == ']':
|
||||
pass
|
||||
else:
|
||||
name_tokens.append(token)
|
||||
i += 1
|
||||
def DeclarationToParts(self, parts, needs_name_removed):
|
||||
name = None
|
||||
default = []
|
||||
if needs_name_removed:
|
||||
# Handle default (initial) values properly.
|
||||
for i, t in enumerate(parts):
|
||||
if t.name == '=':
|
||||
default = parts[i+1:]
|
||||
name = parts[i-1].name
|
||||
if name == ']' and parts[i-2].name == '[':
|
||||
name = parts[i-3].name
|
||||
i -= 1
|
||||
parts = parts[:i-1]
|
||||
break
|
||||
else:
|
||||
if parts[-1].token_type == tokenize.NAME:
|
||||
name = parts.pop().name
|
||||
else:
|
||||
# TODO(nnorwitz): this is a hack that happens for code like
|
||||
# Register(Foo<T>); where it thinks this is a function call
|
||||
# but it's actually a declaration.
|
||||
name = '???'
|
||||
modifiers = []
|
||||
type_name = []
|
||||
other_tokens = []
|
||||
templated_types = []
|
||||
i = 0
|
||||
end = len(parts)
|
||||
while i < end:
|
||||
p = parts[i]
|
||||
if keywords.IsKeyword(p.name):
|
||||
modifiers.append(p.name)
|
||||
elif p.name == '<':
|
||||
templated_tokens, new_end = self._GetTemplateEnd(parts, i+1)
|
||||
templated_types = self.ToType(templated_tokens)
|
||||
i = new_end - 1
|
||||
# Don't add a spurious :: to data members being initialized.
|
||||
next_index = i + 1
|
||||
if next_index < end and parts[next_index].name == '::':
|
||||
i += 1
|
||||
elif p.name in ('[', ']', '='):
|
||||
# These are handled elsewhere.
|
||||
other_tokens.append(p)
|
||||
elif p.name not in ('*', '&', '>'):
|
||||
# Ensure that names have a space between them.
|
||||
if (type_name and type_name[-1].token_type == tokenize.NAME and
|
||||
p.token_type == tokenize.NAME):
|
||||
type_name.append(tokenize.Token(tokenize.SYNTAX, ' ', 0, 0))
|
||||
type_name.append(p)
|
||||
else:
|
||||
other_tokens.append(p)
|
||||
i += 1
|
||||
type_name = ''.join([t.name for t in type_name])
|
||||
return name, type_name, templated_types, modifiers, default, other_tokens
|
||||
|
||||
if name_tokens:
|
||||
# No '<' in the tokens, just a simple name and no template.
|
||||
AddType([])
|
||||
return result
|
||||
def ToParameters(self, tokens):
|
||||
if not tokens:
|
||||
return []
|
||||
|
||||
def DeclarationToParts(self, parts, needs_name_removed):
|
||||
name = None
|
||||
default = []
|
||||
if needs_name_removed:
|
||||
# Handle default (initial) values properly.
|
||||
for i, t in enumerate(parts):
|
||||
if t.name == '=':
|
||||
default = parts[i+1:]
|
||||
name = parts[i-1].name
|
||||
if name == ']' and parts[i-2].name == '[':
|
||||
name = parts[i-3].name
|
||||
i -= 1
|
||||
parts = parts[:i-1]
|
||||
break
|
||||
else:
|
||||
if parts[-1].token_type == tokenize.NAME:
|
||||
name = parts.pop().name
|
||||
else:
|
||||
# TODO(nnorwitz): this is a hack that happens for code like
|
||||
# Register(Foo<T>); where it thinks this is a function call
|
||||
# but it's actually a declaration.
|
||||
name = '???'
|
||||
modifiers = []
|
||||
type_name = []
|
||||
other_tokens = []
|
||||
templated_types = []
|
||||
i = 0
|
||||
end = len(parts)
|
||||
while i < end:
|
||||
p = parts[i]
|
||||
if keywords.IsKeyword(p.name):
|
||||
modifiers.append(p.name)
|
||||
elif p.name == '<':
|
||||
templated_tokens, new_end = self._GetTemplateEnd(parts, i+1)
|
||||
templated_types = self.ToType(templated_tokens)
|
||||
i = new_end - 1
|
||||
# Don't add a spurious :: to data members being initialized.
|
||||
next_index = i + 1
|
||||
if next_index < end and parts[next_index].name == '::':
|
||||
i += 1
|
||||
elif p.name in ('[', ']', '='):
|
||||
# These are handled elsewhere.
|
||||
other_tokens.append(p)
|
||||
elif p.name not in ('*', '&', '>'):
|
||||
# Ensure that names have a space between them.
|
||||
if (type_name and type_name[-1].token_type == tokenize.NAME and
|
||||
p.token_type == tokenize.NAME):
|
||||
type_name.append(tokenize.Token(tokenize.SYNTAX, ' ', 0, 0))
|
||||
type_name.append(p)
|
||||
else:
|
||||
other_tokens.append(p)
|
||||
i += 1
|
||||
type_name = ''.join([t.name for t in type_name])
|
||||
return name, type_name, templated_types, modifiers, default, other_tokens
|
||||
result = []
|
||||
name = type_name = ''
|
||||
type_modifiers = []
|
||||
pointer = reference = array = False
|
||||
first_token = None
|
||||
default = []
|
||||
|
||||
def ToParameters(self, tokens):
|
||||
if not tokens:
|
||||
return []
|
||||
def AddParameter(end):
|
||||
if default:
|
||||
del default[0] # Remove flag.
|
||||
parts = self.DeclarationToParts(type_modifiers, True)
|
||||
(name, type_name, templated_types, modifiers,
|
||||
unused_default, unused_other_tokens) = parts
|
||||
parameter_type = Type(first_token.start, first_token.end,
|
||||
type_name, templated_types, modifiers,
|
||||
reference, pointer, array)
|
||||
p = Parameter(first_token.start, end, name,
|
||||
parameter_type, default)
|
||||
result.append(p)
|
||||
|
||||
result = []
|
||||
template_count = 0
|
||||
brace_count = 0
|
||||
for s in tokens:
|
||||
if not first_token:
|
||||
first_token = s
|
||||
|
||||
# Check for braces before templates, as we can have unmatched '<>'
|
||||
# inside default arguments.
|
||||
if s.name == '{':
|
||||
brace_count += 1
|
||||
elif s.name == '}':
|
||||
brace_count -= 1
|
||||
if brace_count > 0:
|
||||
type_modifiers.append(s)
|
||||
continue
|
||||
|
||||
if s.name == '<':
|
||||
template_count += 1
|
||||
elif s.name == '>':
|
||||
template_count -= 1
|
||||
if template_count > 0:
|
||||
type_modifiers.append(s)
|
||||
continue
|
||||
|
||||
if s.name == ',':
|
||||
AddParameter(s.start)
|
||||
name = type_name = ''
|
||||
type_modifiers = []
|
||||
pointer = reference = array = False
|
||||
first_token = None
|
||||
default = []
|
||||
elif s.name == '*':
|
||||
pointer = True
|
||||
elif s.name == '&':
|
||||
reference = True
|
||||
elif s.name == '[':
|
||||
array = True
|
||||
elif s.name == ']':
|
||||
pass # Just don't add to type_modifiers.
|
||||
elif s.name == '=':
|
||||
# Got a default value. Add any value (None) as a flag.
|
||||
default.append(None)
|
||||
elif default:
|
||||
default.append(s)
|
||||
else:
|
||||
type_modifiers.append(s)
|
||||
AddParameter(tokens[-1].end)
|
||||
return result
|
||||
|
||||
def AddParameter(end):
|
||||
if default:
|
||||
del default[0] # Remove flag.
|
||||
parts = self.DeclarationToParts(type_modifiers, True)
|
||||
(name, type_name, templated_types, modifiers,
|
||||
unused_default, unused_other_tokens) = parts
|
||||
parameter_type = Type(first_token.start, first_token.end,
|
||||
type_name, templated_types, modifiers,
|
||||
reference, pointer, array)
|
||||
p = Parameter(first_token.start, end, name,
|
||||
parameter_type, default)
|
||||
result.append(p)
|
||||
def CreateReturnType(self, return_type_seq):
|
||||
if not return_type_seq:
|
||||
return None
|
||||
start = return_type_seq[0].start
|
||||
end = return_type_seq[-1].end
|
||||
_, name, templated_types, modifiers, default, other_tokens = \
|
||||
self.DeclarationToParts(return_type_seq, False)
|
||||
names = [n.name for n in other_tokens]
|
||||
reference = '&' in names
|
||||
pointer = '*' in names
|
||||
array = '[' in names
|
||||
return Type(start, end, name, templated_types, modifiers,
|
||||
reference, pointer, array)
|
||||
|
||||
template_count = 0
|
||||
for s in tokens:
|
||||
if not first_token:
|
||||
first_token = s
|
||||
if s.name == '<':
|
||||
template_count += 1
|
||||
elif s.name == '>':
|
||||
template_count -= 1
|
||||
if template_count > 0:
|
||||
type_modifiers.append(s)
|
||||
continue
|
||||
|
||||
if s.name == ',':
|
||||
AddParameter(s.start)
|
||||
name = type_name = ''
|
||||
type_modifiers = []
|
||||
pointer = reference = array = False
|
||||
first_token = None
|
||||
default = []
|
||||
elif s.name == '*':
|
||||
pointer = True
|
||||
elif s.name == '&':
|
||||
reference = True
|
||||
elif s.name == '[':
|
||||
array = True
|
||||
elif s.name == ']':
|
||||
pass # Just don't add to type_modifiers.
|
||||
elif s.name == '=':
|
||||
# Got a default value. Add any value (None) as a flag.
|
||||
default.append(None)
|
||||
elif default:
|
||||
default.append(s)
|
||||
else:
|
||||
type_modifiers.append(s)
|
||||
AddParameter(tokens[-1].end)
|
||||
return result
|
||||
|
||||
def CreateReturnType(self, return_type_seq):
|
||||
if not return_type_seq:
|
||||
return None
|
||||
start = return_type_seq[0].start
|
||||
end = return_type_seq[-1].end
|
||||
_, name, templated_types, modifiers, default, other_tokens = \
|
||||
self.DeclarationToParts(return_type_seq, False)
|
||||
names = [n.name for n in other_tokens]
|
||||
reference = '&' in names
|
||||
pointer = '*' in names
|
||||
array = '[' in names
|
||||
return Type(start, end, name, templated_types, modifiers,
|
||||
reference, pointer, array)
|
||||
|
||||
def GetTemplateIndices(self, names):
|
||||
# names is a list of strings.
|
||||
start = names.index('<')
|
||||
end = len(names) - 1
|
||||
while end > 0:
|
||||
if names[end] == '>':
|
||||
break
|
||||
end -= 1
|
||||
return start, end+1
|
||||
def GetTemplateIndices(self, names):
|
||||
# names is a list of strings.
|
||||
start = names.index('<')
|
||||
end = len(names) - 1
|
||||
while end > 0:
|
||||
if names[end] == '>':
|
||||
break
|
||||
end -= 1
|
||||
return start, end+1
|
||||
|
||||
class AstBuilder(object):
|
||||
def __init__(self, token_stream, filename, in_class='', visibility=None,
|
||||
namespace_stack=[]):
|
||||
self.tokens = token_stream
|
||||
self.filename = filename
|
||||
# TODO(nnorwitz): use a better data structure (deque) for the queue.
|
||||
# Switching directions of the "queue" improved perf by about 25%.
|
||||
# Using a deque should be even better since we access from both sides.
|
||||
self.token_queue = []
|
||||
self.namespace_stack = namespace_stack[:]
|
||||
self.in_class = in_class
|
||||
if in_class is None:
|
||||
self.in_class_name_only = None
|
||||
def __init__(self, token_stream, filename, in_class='', visibility=None,
|
||||
namespace_stack=[]):
|
||||
self.tokens = token_stream
|
||||
self.filename = filename
|
||||
# TODO(nnorwitz): use a better data structure (deque) for the queue.
|
||||
# Switching directions of the "queue" improved perf by about 25%.
|
||||
# Using a deque should be even better since we access from both sides.
|
||||
self.token_queue = []
|
||||
self.namespace_stack = namespace_stack[:]
|
||||
self.in_class = in_class
|
||||
if in_class is None:
|
||||
self.in_class_name_only = None
|
||||
else:
|
||||
self.in_class_name_only = in_class.split('::')[-1]
|
||||
self.visibility = visibility
|
||||
self.in_function = False
|
||||
self.current_token = None
|
||||
# Keep the state whether we are currently handling a typedef or not.
|
||||
self._handling_typedef = False
|
||||
|
||||
self.converter = TypeConverter(self.namespace_stack)
|
||||
|
||||
def HandleError(self, msg, token):
|
||||
printable_queue = list(reversed(self.token_queue[-20:]))
|
||||
sys.stderr.write('Got %s in %s @ %s %s\n' %
|
||||
(msg, self.filename, token, printable_queue))
|
||||
|
||||
def Generate(self):
|
||||
while 1:
|
||||
token = self._GetNextToken()
|
||||
if not token:
|
||||
break
|
||||
|
||||
# Get the next token.
|
||||
self.current_token = token
|
||||
|
||||
# Dispatch on the next token type.
|
||||
if token.token_type == _INTERNAL_TOKEN:
|
||||
if token.name == _NAMESPACE_POP:
|
||||
self.namespace_stack.pop()
|
||||
continue
|
||||
|
||||
try:
|
||||
result = self._GenerateOne(token)
|
||||
if result is not None:
|
||||
yield result
|
||||
except:
|
||||
self.HandleError('exception', token)
|
||||
raise
|
||||
|
||||
def _CreateVariable(self, pos_token, name, type_name, type_modifiers,
|
||||
ref_pointer_name_seq, templated_types, value=None):
|
||||
reference = '&' in ref_pointer_name_seq
|
||||
pointer = '*' in ref_pointer_name_seq
|
||||
array = '[' in ref_pointer_name_seq
|
||||
var_type = Type(pos_token.start, pos_token.end, type_name,
|
||||
templated_types, type_modifiers,
|
||||
reference, pointer, array)
|
||||
return VariableDeclaration(pos_token.start, pos_token.end,
|
||||
name, var_type, value, self.namespace_stack)
|
||||
|
||||
def _GenerateOne(self, token):
|
||||
if token.token_type == tokenize.NAME:
|
||||
if (keywords.IsKeyword(token.name) and
|
||||
not keywords.IsBuiltinType(token.name)):
|
||||
if token.name == 'enum':
|
||||
# Pop the next token and only put it back if it's not
|
||||
# 'class'. This allows us to support the two-token
|
||||
# 'enum class' keyword as if it were simply 'enum'.
|
||||
next = self._GetNextToken()
|
||||
if next.name != 'class':
|
||||
self._AddBackToken(next)
|
||||
|
||||
method = getattr(self, 'handle_' + token.name)
|
||||
return method()
|
||||
elif token.name == self.in_class_name_only:
|
||||
# The token name is the same as the class, must be a ctor if
|
||||
# there is a paren. Otherwise, it's the return type.
|
||||
# Peek ahead to get the next token to figure out which.
|
||||
next = self._GetNextToken()
|
||||
self._AddBackToken(next)
|
||||
if next.token_type == tokenize.SYNTAX and next.name == '(':
|
||||
return self._GetMethod([token], FUNCTION_CTOR, None, True)
|
||||
# Fall through--handle like any other method.
|
||||
|
||||
# Handle data or function declaration/definition.
|
||||
syntax = tokenize.SYNTAX
|
||||
temp_tokens, last_token = \
|
||||
self._GetVarTokensUpToIgnoringTemplates(syntax,
|
||||
'(', ';', '{', '[')
|
||||
temp_tokens.insert(0, token)
|
||||
if last_token.name == '(':
|
||||
# If there is an assignment before the paren,
|
||||
# this is an expression, not a method.
|
||||
expr = bool([e for e in temp_tokens if e.name == '='])
|
||||
if expr:
|
||||
new_temp = self._GetTokensUpTo(tokenize.SYNTAX, ';')
|
||||
temp_tokens.append(last_token)
|
||||
temp_tokens.extend(new_temp)
|
||||
last_token = tokenize.Token(tokenize.SYNTAX, ';', 0, 0)
|
||||
|
||||
if last_token.name == '[':
|
||||
# Handle array, this isn't a method, unless it's an operator.
|
||||
# TODO(nnorwitz): keep the size somewhere.
|
||||
# unused_size = self._GetTokensUpTo(tokenize.SYNTAX, ']')
|
||||
temp_tokens.append(last_token)
|
||||
if temp_tokens[-2].name == 'operator':
|
||||
temp_tokens.append(self._GetNextToken())
|
||||
else:
|
||||
self.in_class_name_only = in_class.split('::')[-1]
|
||||
self.visibility = visibility
|
||||
self.in_function = False
|
||||
self.current_token = None
|
||||
# Keep the state whether we are currently handling a typedef or not.
|
||||
self._handling_typedef = False
|
||||
temp_tokens2, last_token = \
|
||||
self._GetVarTokensUpTo(tokenize.SYNTAX, ';')
|
||||
temp_tokens.extend(temp_tokens2)
|
||||
|
||||
self.converter = TypeConverter(self.namespace_stack)
|
||||
|
||||
def HandleError(self, msg, token):
|
||||
printable_queue = list(reversed(self.token_queue[-20:]))
|
||||
sys.stderr.write('Got %s in %s @ %s %s\n' %
|
||||
(msg, self.filename, token, printable_queue))
|
||||
|
||||
def Generate(self):
|
||||
while 1:
|
||||
token = self._GetNextToken()
|
||||
if not token:
|
||||
break
|
||||
|
||||
# Get the next token.
|
||||
self.current_token = token
|
||||
|
||||
# Dispatch on the next token type.
|
||||
if token.token_type == _INTERNAL_TOKEN:
|
||||
if token.name == _NAMESPACE_POP:
|
||||
self.namespace_stack.pop()
|
||||
continue
|
||||
|
||||
try:
|
||||
result = self._GenerateOne(token)
|
||||
if result is not None:
|
||||
yield result
|
||||
except:
|
||||
self.HandleError('exception', token)
|
||||
raise
|
||||
|
||||
def _CreateVariable(self, pos_token, name, type_name, type_modifiers,
|
||||
ref_pointer_name_seq, templated_types, value=None):
|
||||
reference = '&' in ref_pointer_name_seq
|
||||
pointer = '*' in ref_pointer_name_seq
|
||||
array = '[' in ref_pointer_name_seq
|
||||
var_type = Type(pos_token.start, pos_token.end, type_name,
|
||||
templated_types, type_modifiers,
|
||||
reference, pointer, array)
|
||||
return VariableDeclaration(pos_token.start, pos_token.end,
|
||||
name, var_type, value, self.namespace_stack)
|
||||
|
||||
def _GenerateOne(self, token):
|
||||
if token.token_type == tokenize.NAME:
|
||||
if (keywords.IsKeyword(token.name) and
|
||||
not keywords.IsBuiltinType(token.name)):
|
||||
if token.name == 'enum':
|
||||
# Pop the next token and only put it back if it's not
|
||||
# 'class'. This allows us to support the two-token
|
||||
# 'enum class' keyword as if it were simply 'enum'.
|
||||
next = self._GetNextToken()
|
||||
if next.name != 'class':
|
||||
self._AddBackToken(next)
|
||||
|
||||
method = getattr(self, 'handle_' + token.name)
|
||||
return method()
|
||||
elif token.name == self.in_class_name_only:
|
||||
# The token name is the same as the class, must be a ctor if
|
||||
# there is a paren. Otherwise, it's the return type.
|
||||
# Peek ahead to get the next token to figure out which.
|
||||
next = self._GetNextToken()
|
||||
self._AddBackToken(next)
|
||||
if next.token_type == tokenize.SYNTAX and next.name == '(':
|
||||
return self._GetMethod([token], FUNCTION_CTOR, None, True)
|
||||
# Fall through--handle like any other method.
|
||||
|
||||
# Handle data or function declaration/definition.
|
||||
syntax = tokenize.SYNTAX
|
||||
temp_tokens, last_token = \
|
||||
self._GetVarTokensUpToIgnoringTemplates(syntax,
|
||||
'(', ';', '{', '[')
|
||||
temp_tokens.insert(0, token)
|
||||
if last_token.name == '(':
|
||||
# If there is an assignment before the paren,
|
||||
# this is an expression, not a method.
|
||||
expr = bool([e for e in temp_tokens if e.name == '='])
|
||||
if expr:
|
||||
new_temp = self._GetTokensUpTo(tokenize.SYNTAX, ';')
|
||||
temp_tokens.append(last_token)
|
||||
temp_tokens.extend(new_temp)
|
||||
last_token = tokenize.Token(tokenize.SYNTAX, ';', 0, 0)
|
||||
|
||||
if last_token.name == '[':
|
||||
# Handle array, this isn't a method, unless it's an operator.
|
||||
# TODO(nnorwitz): keep the size somewhere.
|
||||
# unused_size = self._GetTokensUpTo(tokenize.SYNTAX, ']')
|
||||
temp_tokens.append(last_token)
|
||||
if temp_tokens[-2].name == 'operator':
|
||||
temp_tokens.append(self._GetNextToken())
|
||||
else:
|
||||
temp_tokens2, last_token = \
|
||||
self._GetVarTokensUpTo(tokenize.SYNTAX, ';')
|
||||
temp_tokens.extend(temp_tokens2)
|
||||
|
||||
if last_token.name == ';':
|
||||
# Handle data, this isn't a method.
|
||||
parts = self.converter.DeclarationToParts(temp_tokens, True)
|
||||
(name, type_name, templated_types, modifiers, default,
|
||||
unused_other_tokens) = parts
|
||||
|
||||
t0 = temp_tokens[0]
|
||||
names = [t.name for t in temp_tokens]
|
||||
if templated_types:
|
||||
start, end = self.converter.GetTemplateIndices(names)
|
||||
names = names[:start] + names[end:]
|
||||
default = ''.join([t.name for t in default])
|
||||
return self._CreateVariable(t0, name, type_name, modifiers,
|
||||
names, templated_types, default)
|
||||
if last_token.name == '{':
|
||||
self._AddBackTokens(temp_tokens[1:])
|
||||
self._AddBackToken(last_token)
|
||||
method_name = temp_tokens[0].name
|
||||
method = getattr(self, 'handle_' + method_name, None)
|
||||
if not method:
|
||||
# Must be declaring a variable.
|
||||
# TODO(nnorwitz): handle the declaration.
|
||||
return None
|
||||
return method()
|
||||
return self._GetMethod(temp_tokens, 0, None, False)
|
||||
elif token.token_type == tokenize.SYNTAX:
|
||||
if token.name == '~' and self.in_class:
|
||||
# Must be a dtor (probably not in method body).
|
||||
token = self._GetNextToken()
|
||||
# self.in_class can contain A::Name, but the dtor will only
|
||||
# be Name. Make sure to compare against the right value.
|
||||
if (token.token_type == tokenize.NAME and
|
||||
token.name == self.in_class_name_only):
|
||||
return self._GetMethod([token], FUNCTION_DTOR, None, True)
|
||||
# TODO(nnorwitz): handle a lot more syntax.
|
||||
elif token.token_type == tokenize.PREPROCESSOR:
|
||||
# TODO(nnorwitz): handle more preprocessor directives.
|
||||
# token starts with a #, so remove it and strip whitespace.
|
||||
name = token.name[1:].lstrip()
|
||||
if name.startswith('include'):
|
||||
# Remove "include".
|
||||
name = name[7:].strip()
|
||||
assert name
|
||||
# Handle #include \<newline> "header-on-second-line.h".
|
||||
if name.startswith('\\'):
|
||||
name = name[1:].strip()
|
||||
assert name[0] in '<"', token
|
||||
assert name[-1] in '>"', token
|
||||
system = name[0] == '<'
|
||||
filename = name[1:-1]
|
||||
return Include(token.start, token.end, filename, system)
|
||||
if name.startswith('define'):
|
||||
# Remove "define".
|
||||
name = name[6:].strip()
|
||||
assert name
|
||||
value = ''
|
||||
for i, c in enumerate(name):
|
||||
if c.isspace():
|
||||
value = name[i:].lstrip()
|
||||
name = name[:i]
|
||||
break
|
||||
return Define(token.start, token.end, name, value)
|
||||
if name.startswith('if') and name[2:3].isspace():
|
||||
condition = name[3:].strip()
|
||||
if condition.startswith('0') or condition.startswith('(0)'):
|
||||
self._SkipIf0Blocks()
|
||||
return None
|
||||
|
||||
def _GetTokensUpTo(self, expected_token_type, expected_token):
|
||||
return self._GetVarTokensUpTo(expected_token_type, expected_token)[0]
|
||||
|
||||
def _GetVarTokensUpTo(self, expected_token_type, *expected_tokens):
|
||||
last_token = self._GetNextToken()
|
||||
tokens = []
|
||||
while (last_token.token_type != expected_token_type or
|
||||
last_token.name not in expected_tokens):
|
||||
tokens.append(last_token)
|
||||
last_token = self._GetNextToken()
|
||||
return tokens, last_token
|
||||
|
||||
# Same as _GetVarTokensUpTo, but skips over '<...>' which could contain an
|
||||
# expected token.
|
||||
def _GetVarTokensUpToIgnoringTemplates(self, expected_token_type,
|
||||
*expected_tokens):
|
||||
last_token = self._GetNextToken()
|
||||
tokens = []
|
||||
nesting = 0
|
||||
while (nesting > 0 or
|
||||
last_token.token_type != expected_token_type or
|
||||
last_token.name not in expected_tokens):
|
||||
tokens.append(last_token)
|
||||
last_token = self._GetNextToken()
|
||||
if last_token.name == '<':
|
||||
nesting += 1
|
||||
elif last_token.name == '>':
|
||||
nesting -= 1
|
||||
return tokens, last_token
|
||||
|
||||
# TODO(nnorwitz): remove _IgnoreUpTo() it shouldn't be necesary.
|
||||
def _IgnoreUpTo(self, token_type, token):
|
||||
unused_tokens = self._GetTokensUpTo(token_type, token)
|
||||
|
||||
def _SkipIf0Blocks(self):
|
||||
count = 1
|
||||
while 1:
|
||||
token = self._GetNextToken()
|
||||
if token.token_type != tokenize.PREPROCESSOR:
|
||||
continue
|
||||
|
||||
name = token.name[1:].lstrip()
|
||||
if name.startswith('endif'):
|
||||
count -= 1
|
||||
if count == 0:
|
||||
break
|
||||
elif name.startswith('if'):
|
||||
count += 1
|
||||
|
||||
def _GetMatchingChar(self, open_paren, close_paren, GetNextToken=None):
|
||||
if GetNextToken is None:
|
||||
GetNextToken = self._GetNextToken
|
||||
# Assumes the current token is open_paren and we will consume
|
||||
# and return up to the close_paren.
|
||||
count = 1
|
||||
token = GetNextToken()
|
||||
while 1:
|
||||
if token.token_type == tokenize.SYNTAX:
|
||||
if token.name == open_paren:
|
||||
count += 1
|
||||
elif token.name == close_paren:
|
||||
count -= 1
|
||||
if count == 0:
|
||||
break
|
||||
yield token
|
||||
token = GetNextToken()
|
||||
yield token
|
||||
|
||||
def _GetParameters(self):
|
||||
return self._GetMatchingChar('(', ')')
|
||||
|
||||
def GetScope(self):
|
||||
return self._GetMatchingChar('{', '}')
|
||||
|
||||
def _GetNextToken(self):
|
||||
if self.token_queue:
|
||||
return self.token_queue.pop()
|
||||
try:
|
||||
return next(self.tokens)
|
||||
except StopIteration:
|
||||
return
|
||||
|
||||
def _AddBackToken(self, token):
|
||||
if token.whence == tokenize.WHENCE_STREAM:
|
||||
token.whence = tokenize.WHENCE_QUEUE
|
||||
self.token_queue.insert(0, token)
|
||||
else:
|
||||
assert token.whence == tokenize.WHENCE_QUEUE, token
|
||||
self.token_queue.append(token)
|
||||
|
||||
def _AddBackTokens(self, tokens):
|
||||
if tokens:
|
||||
if tokens[-1].whence == tokenize.WHENCE_STREAM:
|
||||
for token in tokens:
|
||||
token.whence = tokenize.WHENCE_QUEUE
|
||||
self.token_queue[:0] = reversed(tokens)
|
||||
else:
|
||||
assert tokens[-1].whence == tokenize.WHENCE_QUEUE, tokens
|
||||
self.token_queue.extend(reversed(tokens))
|
||||
|
||||
def GetName(self, seq=None):
|
||||
"""Returns ([tokens], next_token_info)."""
|
||||
GetNextToken = self._GetNextToken
|
||||
if seq is not None:
|
||||
it = iter(seq)
|
||||
GetNextToken = lambda: next(it)
|
||||
next_token = GetNextToken()
|
||||
tokens = []
|
||||
last_token_was_name = False
|
||||
while (next_token.token_type == tokenize.NAME or
|
||||
(next_token.token_type == tokenize.SYNTAX and
|
||||
next_token.name in ('::', '<'))):
|
||||
# Two NAMEs in a row means the identifier should terminate.
|
||||
# It's probably some sort of variable declaration.
|
||||
if last_token_was_name and next_token.token_type == tokenize.NAME:
|
||||
break
|
||||
last_token_was_name = next_token.token_type == tokenize.NAME
|
||||
tokens.append(next_token)
|
||||
# Handle templated names.
|
||||
if next_token.name == '<':
|
||||
tokens.extend(self._GetMatchingChar('<', '>', GetNextToken))
|
||||
last_token_was_name = True
|
||||
next_token = GetNextToken()
|
||||
return tokens, next_token
|
||||
|
||||
def GetMethod(self, modifiers, templated_types):
|
||||
return_type_and_name = self._GetTokensUpTo(tokenize.SYNTAX, '(')
|
||||
assert len(return_type_and_name) >= 1
|
||||
return self._GetMethod(return_type_and_name, modifiers, templated_types,
|
||||
False)
|
||||
|
||||
def _GetMethod(self, return_type_and_name, modifiers, templated_types,
|
||||
get_paren):
|
||||
template_portion = None
|
||||
if get_paren:
|
||||
token = self._GetNextToken()
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
if token.name == '<':
|
||||
# Handle templatized dtors.
|
||||
template_portion = [token]
|
||||
template_portion.extend(self._GetMatchingChar('<', '>'))
|
||||
token = self._GetNextToken()
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
assert token.name == '(', token
|
||||
|
||||
name = return_type_and_name.pop()
|
||||
# Handle templatized ctors.
|
||||
if name.name == '>':
|
||||
index = 1
|
||||
while return_type_and_name[index].name != '<':
|
||||
index += 1
|
||||
template_portion = return_type_and_name[index:] + [name]
|
||||
del return_type_and_name[index:]
|
||||
name = return_type_and_name.pop()
|
||||
elif name.name == ']':
|
||||
rt = return_type_and_name
|
||||
assert rt[-1].name == '[', return_type_and_name
|
||||
assert rt[-2].name == 'operator', return_type_and_name
|
||||
name_seq = return_type_and_name[-2:]
|
||||
del return_type_and_name[-2:]
|
||||
name = tokenize.Token(tokenize.NAME, 'operator[]',
|
||||
name_seq[0].start, name.end)
|
||||
# Get the open paren so _GetParameters() below works.
|
||||
unused_open_paren = self._GetNextToken()
|
||||
|
||||
# TODO(nnorwitz): store template_portion.
|
||||
return_type = return_type_and_name
|
||||
indices = name
|
||||
if return_type:
|
||||
indices = return_type[0]
|
||||
|
||||
# Force ctor for templatized ctors.
|
||||
if name.name == self.in_class and not modifiers:
|
||||
modifiers |= FUNCTION_CTOR
|
||||
parameters = list(self._GetParameters())
|
||||
del parameters[-1] # Remove trailing ')'.
|
||||
|
||||
# Handling operator() is especially weird.
|
||||
if name.name == 'operator' and not parameters:
|
||||
token = self._GetNextToken()
|
||||
assert token.name == '(', token
|
||||
parameters = list(self._GetParameters())
|
||||
del parameters[-1] # Remove trailing ')'.
|
||||
if last_token.name == ';':
|
||||
# Handle data, this isn't a method.
|
||||
parts = self.converter.DeclarationToParts(temp_tokens, True)
|
||||
(name, type_name, templated_types, modifiers, default,
|
||||
unused_other_tokens) = parts
|
||||
|
||||
t0 = temp_tokens[0]
|
||||
names = [t.name for t in temp_tokens]
|
||||
if templated_types:
|
||||
start, end = self.converter.GetTemplateIndices(names)
|
||||
names = names[:start] + names[end:]
|
||||
default = ''.join([t.name for t in default])
|
||||
return self._CreateVariable(t0, name, type_name, modifiers,
|
||||
names, templated_types, default)
|
||||
if last_token.name == '{':
|
||||
self._AddBackTokens(temp_tokens[1:])
|
||||
self._AddBackToken(last_token)
|
||||
method_name = temp_tokens[0].name
|
||||
method = getattr(self, 'handle_' + method_name, None)
|
||||
if not method:
|
||||
# Must be declaring a variable.
|
||||
# TODO(nnorwitz): handle the declaration.
|
||||
return None
|
||||
return method()
|
||||
return self._GetMethod(temp_tokens, 0, None, False)
|
||||
elif token.token_type == tokenize.SYNTAX:
|
||||
if token.name == '~' and self.in_class:
|
||||
# Must be a dtor (probably not in method body).
|
||||
token = self._GetNextToken()
|
||||
while token.token_type == tokenize.NAME:
|
||||
modifier_token = token
|
||||
token = self._GetNextToken()
|
||||
if modifier_token.name == 'const':
|
||||
modifiers |= FUNCTION_CONST
|
||||
elif modifier_token.name == '__attribute__':
|
||||
# TODO(nnorwitz): handle more __attribute__ details.
|
||||
modifiers |= FUNCTION_ATTRIBUTE
|
||||
assert token.name == '(', token
|
||||
# Consume everything between the (parens).
|
||||
unused_tokens = list(self._GetMatchingChar('(', ')'))
|
||||
token = self._GetNextToken()
|
||||
elif modifier_token.name == 'throw':
|
||||
modifiers |= FUNCTION_THROW
|
||||
assert token.name == '(', token
|
||||
# Consume everything between the (parens).
|
||||
unused_tokens = list(self._GetMatchingChar('(', ')'))
|
||||
token = self._GetNextToken()
|
||||
elif modifier_token.name == 'override':
|
||||
modifiers |= FUNCTION_OVERRIDE
|
||||
elif modifier_token.name == modifier_token.name.upper():
|
||||
# HACK(nnorwitz): assume that all upper-case names
|
||||
# are some macro we aren't expanding.
|
||||
modifiers |= FUNCTION_UNKNOWN_ANNOTATION
|
||||
else:
|
||||
self.HandleError('unexpected token', modifier_token)
|
||||
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
# Handle ctor initializers.
|
||||
if token.name == ':':
|
||||
# TODO(nnorwitz): anything else to handle for initializer list?
|
||||
while token.name != ';' and token.name != '{':
|
||||
token = self._GetNextToken()
|
||||
|
||||
# Handle pointer to functions that are really data but look
|
||||
# like method declarations.
|
||||
if token.name == '(':
|
||||
if parameters[0].name == '*':
|
||||
# name contains the return type.
|
||||
name = parameters.pop()
|
||||
# parameters contains the name of the data.
|
||||
modifiers = [p.name for p in parameters]
|
||||
# Already at the ( to open the parameter list.
|
||||
function_parameters = list(self._GetMatchingChar('(', ')'))
|
||||
del function_parameters[-1] # Remove trailing ')'.
|
||||
# TODO(nnorwitz): store the function_parameters.
|
||||
token = self._GetNextToken()
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
assert token.name == ';', token
|
||||
return self._CreateVariable(indices, name.name, indices.name,
|
||||
modifiers, '', None)
|
||||
# At this point, we got something like:
|
||||
# return_type (type::*name_)(params);
|
||||
# This is a data member called name_ that is a function pointer.
|
||||
# With this code: void (sq_type::*field_)(string&);
|
||||
# We get: name=void return_type=[] parameters=sq_type ... field_
|
||||
# TODO(nnorwitz): is return_type always empty?
|
||||
# TODO(nnorwitz): this isn't even close to being correct.
|
||||
# Just put in something so we don't crash and can move on.
|
||||
real_name = parameters[-1]
|
||||
modifiers = [p.name for p in self._GetParameters()]
|
||||
del modifiers[-1] # Remove trailing ')'.
|
||||
return self._CreateVariable(indices, real_name.name, indices.name,
|
||||
modifiers, '', None)
|
||||
|
||||
if token.name == '{':
|
||||
body = list(self.GetScope())
|
||||
del body[-1] # Remove trailing '}'.
|
||||
else:
|
||||
body = None
|
||||
if token.name == '=':
|
||||
token = self._GetNextToken()
|
||||
|
||||
if token.name == 'default' or token.name == 'delete':
|
||||
# Ignore explicitly defaulted and deleted special members
|
||||
# in C++11.
|
||||
token = self._GetNextToken()
|
||||
else:
|
||||
# Handle pure-virtual declarations.
|
||||
assert token.token_type == tokenize.CONSTANT, token
|
||||
assert token.name == '0', token
|
||||
modifiers |= FUNCTION_PURE_VIRTUAL
|
||||
token = self._GetNextToken()
|
||||
|
||||
if token.name == '[':
|
||||
# TODO(nnorwitz): store tokens and improve parsing.
|
||||
# template <typename T, size_t N> char (&ASH(T (&seq)[N]))[N];
|
||||
tokens = list(self._GetMatchingChar('[', ']'))
|
||||
token = self._GetNextToken()
|
||||
|
||||
assert token.name == ';', (token, return_type_and_name, parameters)
|
||||
|
||||
# Looks like we got a method, not a function.
|
||||
if len(return_type) > 2 and return_type[-1].name == '::':
|
||||
return_type, in_class = \
|
||||
self._GetReturnTypeAndClassName(return_type)
|
||||
return Method(indices.start, indices.end, name.name, in_class,
|
||||
return_type, parameters, modifiers, templated_types,
|
||||
body, self.namespace_stack)
|
||||
return Function(indices.start, indices.end, name.name, return_type,
|
||||
parameters, modifiers, templated_types, body,
|
||||
self.namespace_stack)
|
||||
|
||||
def _GetReturnTypeAndClassName(self, token_seq):
|
||||
# Splitting the return type from the class name in a method
|
||||
# can be tricky. For example, Return::Type::Is::Hard::To::Find().
|
||||
# Where is the return type and where is the class name?
|
||||
# The heuristic used is to pull the last name as the class name.
|
||||
# This includes all the templated type info.
|
||||
# TODO(nnorwitz): if there is only One name like in the
|
||||
# example above, punt and assume the last bit is the class name.
|
||||
|
||||
# Ignore a :: prefix, if exists so we can find the first real name.
|
||||
i = 0
|
||||
if token_seq[0].name == '::':
|
||||
i = 1
|
||||
# Ignore a :: suffix, if exists.
|
||||
end = len(token_seq) - 1
|
||||
if token_seq[end-1].name == '::':
|
||||
end -= 1
|
||||
|
||||
# Make a copy of the sequence so we can append a sentinel
|
||||
# value. This is required for GetName will has to have some
|
||||
# terminating condition beyond the last name.
|
||||
seq_copy = token_seq[i:end]
|
||||
seq_copy.append(tokenize.Token(tokenize.SYNTAX, '', 0, 0))
|
||||
names = []
|
||||
while i < end:
|
||||
# Iterate through the sequence parsing out each name.
|
||||
new_name, next = self.GetName(seq_copy[i:])
|
||||
assert new_name, 'Got empty new_name, next=%s' % next
|
||||
# We got a pointer or ref. Add it to the name.
|
||||
if next and next.token_type == tokenize.SYNTAX:
|
||||
new_name.append(next)
|
||||
names.append(new_name)
|
||||
i += len(new_name)
|
||||
|
||||
# Now that we have the names, it's time to undo what we did.
|
||||
|
||||
# Remove the sentinel value.
|
||||
names[-1].pop()
|
||||
# Flatten the token sequence for the return type.
|
||||
return_type = [e for seq in names[:-1] for e in seq]
|
||||
# The class name is the last name.
|
||||
class_name = names[-1]
|
||||
return return_type, class_name
|
||||
|
||||
def handle_bool(self):
|
||||
pass
|
||||
|
||||
def handle_char(self):
|
||||
pass
|
||||
|
||||
def handle_int(self):
|
||||
pass
|
||||
|
||||
def handle_long(self):
|
||||
pass
|
||||
|
||||
def handle_short(self):
|
||||
pass
|
||||
|
||||
def handle_double(self):
|
||||
pass
|
||||
|
||||
def handle_float(self):
|
||||
pass
|
||||
|
||||
def handle_void(self):
|
||||
pass
|
||||
|
||||
def handle_wchar_t(self):
|
||||
pass
|
||||
|
||||
def handle_unsigned(self):
|
||||
pass
|
||||
|
||||
def handle_signed(self):
|
||||
pass
|
||||
|
||||
def _GetNestedType(self, ctor):
|
||||
name = None
|
||||
name_tokens, token = self.GetName()
|
||||
if name_tokens:
|
||||
name = ''.join([t.name for t in name_tokens])
|
||||
|
||||
# Handle forward declarations.
|
||||
if token.token_type == tokenize.SYNTAX and token.name == ';':
|
||||
return ctor(token.start, token.end, name, None,
|
||||
self.namespace_stack)
|
||||
|
||||
if token.token_type == tokenize.NAME and self._handling_typedef:
|
||||
self._AddBackToken(token)
|
||||
return ctor(token.start, token.end, name, None,
|
||||
self.namespace_stack)
|
||||
|
||||
# Must be the type declaration.
|
||||
fields = list(self._GetMatchingChar('{', '}'))
|
||||
del fields[-1] # Remove trailing '}'.
|
||||
if token.token_type == tokenize.SYNTAX and token.name == '{':
|
||||
next = self._GetNextToken()
|
||||
new_type = ctor(token.start, token.end, name, fields,
|
||||
self.namespace_stack)
|
||||
# A name means this is an anonymous type and the name
|
||||
# is the variable declaration.
|
||||
if next.token_type != tokenize.NAME:
|
||||
return new_type
|
||||
name = new_type
|
||||
token = next
|
||||
|
||||
# Must be variable declaration using the type prefixed with keyword.
|
||||
assert token.token_type == tokenize.NAME, token
|
||||
return self._CreateVariable(token, token.name, name, [], '', None)
|
||||
|
||||
def handle_struct(self):
|
||||
# Special case the handling typedef/aliasing of structs here.
|
||||
# It would be a pain to handle in the class code.
|
||||
name_tokens, var_token = self.GetName()
|
||||
if name_tokens:
|
||||
next_token = self._GetNextToken()
|
||||
is_syntax = (var_token.token_type == tokenize.SYNTAX and
|
||||
var_token.name[0] in '*&')
|
||||
is_variable = (var_token.token_type == tokenize.NAME and
|
||||
next_token.name == ';')
|
||||
variable = var_token
|
||||
if is_syntax and not is_variable:
|
||||
variable = next_token
|
||||
temp = self._GetNextToken()
|
||||
if temp.token_type == tokenize.SYNTAX and temp.name == '(':
|
||||
# Handle methods declared to return a struct.
|
||||
t0 = name_tokens[0]
|
||||
struct = tokenize.Token(tokenize.NAME, 'struct',
|
||||
t0.start-7, t0.start-2)
|
||||
type_and_name = [struct]
|
||||
type_and_name.extend(name_tokens)
|
||||
type_and_name.extend((var_token, next_token))
|
||||
return self._GetMethod(type_and_name, 0, None, False)
|
||||
assert temp.name == ';', (temp, name_tokens, var_token)
|
||||
if is_syntax or (is_variable and not self._handling_typedef):
|
||||
modifiers = ['struct']
|
||||
type_name = ''.join([t.name for t in name_tokens])
|
||||
position = name_tokens[0]
|
||||
return self._CreateVariable(position, variable.name, type_name,
|
||||
modifiers, var_token.name, None)
|
||||
name_tokens.extend((var_token, next_token))
|
||||
self._AddBackTokens(name_tokens)
|
||||
else:
|
||||
self._AddBackToken(var_token)
|
||||
return self._GetClass(Struct, VISIBILITY_PUBLIC, None)
|
||||
|
||||
def handle_union(self):
|
||||
return self._GetNestedType(Union)
|
||||
|
||||
def handle_enum(self):
|
||||
return self._GetNestedType(Enum)
|
||||
|
||||
def handle_auto(self):
|
||||
# TODO(nnorwitz): warn about using auto? Probably not since it
|
||||
# will be reclaimed and useful for C++0x.
|
||||
pass
|
||||
|
||||
def handle_register(self):
|
||||
pass
|
||||
|
||||
def handle_const(self):
|
||||
pass
|
||||
|
||||
def handle_inline(self):
|
||||
pass
|
||||
|
||||
def handle_extern(self):
|
||||
pass
|
||||
|
||||
def handle_static(self):
|
||||
pass
|
||||
|
||||
def handle_virtual(self):
|
||||
# What follows must be a method.
|
||||
token = token2 = self._GetNextToken()
|
||||
if token.name == 'inline':
|
||||
# HACK(nnorwitz): handle inline dtors by ignoring 'inline'.
|
||||
token2 = self._GetNextToken()
|
||||
if token2.token_type == tokenize.SYNTAX and token2.name == '~':
|
||||
return self.GetMethod(FUNCTION_VIRTUAL + FUNCTION_DTOR, None)
|
||||
assert token.token_type == tokenize.NAME or token.name == '::', token
|
||||
return_type_and_name, _ = self._GetVarTokensUpToIgnoringTemplates(
|
||||
tokenize.SYNTAX, '(') # )
|
||||
return_type_and_name.insert(0, token)
|
||||
if token2 is not token:
|
||||
return_type_and_name.insert(1, token2)
|
||||
return self._GetMethod(return_type_and_name, FUNCTION_VIRTUAL,
|
||||
None, False)
|
||||
|
||||
def handle_volatile(self):
|
||||
pass
|
||||
|
||||
def handle_mutable(self):
|
||||
pass
|
||||
|
||||
def handle_public(self):
|
||||
assert self.in_class
|
||||
self.visibility = VISIBILITY_PUBLIC
|
||||
|
||||
def handle_protected(self):
|
||||
assert self.in_class
|
||||
self.visibility = VISIBILITY_PROTECTED
|
||||
|
||||
def handle_private(self):
|
||||
assert self.in_class
|
||||
self.visibility = VISIBILITY_PRIVATE
|
||||
|
||||
def handle_friend(self):
|
||||
tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
|
||||
assert tokens
|
||||
t0 = tokens[0]
|
||||
return Friend(t0.start, t0.end, tokens, self.namespace_stack)
|
||||
|
||||
def handle_static_cast(self):
|
||||
pass
|
||||
|
||||
def handle_const_cast(self):
|
||||
pass
|
||||
|
||||
def handle_dynamic_cast(self):
|
||||
pass
|
||||
|
||||
def handle_reinterpret_cast(self):
|
||||
pass
|
||||
|
||||
def handle_new(self):
|
||||
pass
|
||||
|
||||
def handle_delete(self):
|
||||
tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
|
||||
assert tokens
|
||||
return Delete(tokens[0].start, tokens[0].end, tokens)
|
||||
|
||||
def handle_typedef(self):
|
||||
token = self._GetNextToken()
|
||||
# self.in_class can contain A::Name, but the dtor will only
|
||||
# be Name. Make sure to compare against the right value.
|
||||
if (token.token_type == tokenize.NAME and
|
||||
keywords.IsKeyword(token.name)):
|
||||
# Token must be struct/enum/union/class.
|
||||
method = getattr(self, 'handle_' + token.name)
|
||||
self._handling_typedef = True
|
||||
tokens = [method()]
|
||||
self._handling_typedef = False
|
||||
else:
|
||||
tokens = [token]
|
||||
token.name == self.in_class_name_only):
|
||||
return self._GetMethod([token], FUNCTION_DTOR, None, True)
|
||||
# TODO(nnorwitz): handle a lot more syntax.
|
||||
elif token.token_type == tokenize.PREPROCESSOR:
|
||||
# TODO(nnorwitz): handle more preprocessor directives.
|
||||
# token starts with a #, so remove it and strip whitespace.
|
||||
name = token.name[1:].lstrip()
|
||||
if name.startswith('include'):
|
||||
# Remove "include".
|
||||
name = name[7:].strip()
|
||||
assert name
|
||||
# Handle #include \<newline> "header-on-second-line.h".
|
||||
if name.startswith('\\'):
|
||||
name = name[1:].strip()
|
||||
assert name[0] in '<"', token
|
||||
assert name[-1] in '>"', token
|
||||
system = name[0] == '<'
|
||||
filename = name[1:-1]
|
||||
return Include(token.start, token.end, filename, system)
|
||||
if name.startswith('define'):
|
||||
# Remove "define".
|
||||
name = name[6:].strip()
|
||||
assert name
|
||||
value = ''
|
||||
for i, c in enumerate(name):
|
||||
if c.isspace():
|
||||
value = name[i:].lstrip()
|
||||
name = name[:i]
|
||||
break
|
||||
return Define(token.start, token.end, name, value)
|
||||
if name.startswith('if') and name[2:3].isspace():
|
||||
condition = name[3:].strip()
|
||||
if condition.startswith('0') or condition.startswith('(0)'):
|
||||
self._SkipIf0Blocks()
|
||||
return None
|
||||
|
||||
# Get the remainder of the typedef up to the semi-colon.
|
||||
tokens.extend(self._GetTokensUpTo(tokenize.SYNTAX, ';'))
|
||||
def _GetTokensUpTo(self, expected_token_type, expected_token):
|
||||
return self._GetVarTokensUpTo(expected_token_type, expected_token)[0]
|
||||
|
||||
# TODO(nnorwitz): clean all this up.
|
||||
assert tokens
|
||||
name = tokens.pop()
|
||||
indices = name
|
||||
if tokens:
|
||||
indices = tokens[0]
|
||||
if not indices:
|
||||
indices = token
|
||||
if name.name == ')':
|
||||
# HACK(nnorwitz): Handle pointers to functions "properly".
|
||||
if (len(tokens) >= 4 and
|
||||
tokens[1].name == '(' and tokens[2].name == '*'):
|
||||
tokens.append(name)
|
||||
name = tokens[3]
|
||||
elif name.name == ']':
|
||||
# HACK(nnorwitz): Handle arrays properly.
|
||||
if len(tokens) >= 2:
|
||||
tokens.append(name)
|
||||
name = tokens[1]
|
||||
new_type = tokens
|
||||
if tokens and isinstance(tokens[0], tokenize.Token):
|
||||
new_type = self.converter.ToType(tokens)[0]
|
||||
return Typedef(indices.start, indices.end, name.name,
|
||||
new_type, self.namespace_stack)
|
||||
def _GetVarTokensUpTo(self, expected_token_type, *expected_tokens):
|
||||
last_token = self._GetNextToken()
|
||||
tokens = []
|
||||
while (last_token.token_type != expected_token_type or
|
||||
last_token.name not in expected_tokens):
|
||||
tokens.append(last_token)
|
||||
last_token = self._GetNextToken()
|
||||
return tokens, last_token
|
||||
|
||||
def handle_typeid(self):
|
||||
pass # Not needed yet.
|
||||
# Same as _GetVarTokensUpTo, but skips over '<...>' which could contain an
|
||||
# expected token.
|
||||
def _GetVarTokensUpToIgnoringTemplates(self, expected_token_type,
|
||||
*expected_tokens):
|
||||
last_token = self._GetNextToken()
|
||||
tokens = []
|
||||
nesting = 0
|
||||
while (nesting > 0 or
|
||||
last_token.token_type != expected_token_type or
|
||||
last_token.name not in expected_tokens):
|
||||
tokens.append(last_token)
|
||||
last_token = self._GetNextToken()
|
||||
if last_token.name == '<':
|
||||
nesting += 1
|
||||
elif last_token.name == '>':
|
||||
nesting -= 1
|
||||
return tokens, last_token
|
||||
|
||||
def handle_typename(self):
|
||||
pass # Not needed yet.
|
||||
# TODO(nnorwitz): remove _IgnoreUpTo() it shouldn't be necesary.
|
||||
def _IgnoreUpTo(self, token_type, token):
|
||||
unused_tokens = self._GetTokensUpTo(token_type, token)
|
||||
|
||||
def _GetTemplatedTypes(self):
|
||||
result = {}
|
||||
tokens = list(self._GetMatchingChar('<', '>'))
|
||||
len_tokens = len(tokens) - 1 # Ignore trailing '>'.
|
||||
i = 0
|
||||
while i < len_tokens:
|
||||
key = tokens[i].name
|
||||
i += 1
|
||||
if keywords.IsKeyword(key) or key == ',':
|
||||
continue
|
||||
type_name = default = None
|
||||
if i < len_tokens:
|
||||
i += 1
|
||||
if tokens[i-1].name == '=':
|
||||
assert i < len_tokens, '%s %s' % (i, tokens)
|
||||
default, unused_next_token = self.GetName(tokens[i:])
|
||||
i += len(default)
|
||||
else:
|
||||
if tokens[i-1].name != ',':
|
||||
# We got something like: Type variable.
|
||||
# Re-adjust the key (variable) and type_name (Type).
|
||||
key = tokens[i-1].name
|
||||
type_name = tokens[i-2]
|
||||
def _SkipIf0Blocks(self):
|
||||
count = 1
|
||||
while 1:
|
||||
token = self._GetNextToken()
|
||||
if token.token_type != tokenize.PREPROCESSOR:
|
||||
continue
|
||||
|
||||
result[key] = (type_name, default)
|
||||
return result
|
||||
name = token.name[1:].lstrip()
|
||||
if name.startswith('endif'):
|
||||
count -= 1
|
||||
if count == 0:
|
||||
break
|
||||
elif name.startswith('if'):
|
||||
count += 1
|
||||
|
||||
def handle_template(self):
|
||||
def _GetMatchingChar(self, open_paren, close_paren, GetNextToken=None):
|
||||
if GetNextToken is None:
|
||||
GetNextToken = self._GetNextToken
|
||||
# Assumes the current token is open_paren and we will consume
|
||||
# and return up to the close_paren.
|
||||
count = 1
|
||||
token = GetNextToken()
|
||||
while 1:
|
||||
if token.token_type == tokenize.SYNTAX:
|
||||
if token.name == open_paren:
|
||||
count += 1
|
||||
elif token.name == close_paren:
|
||||
count -= 1
|
||||
if count == 0:
|
||||
break
|
||||
yield token
|
||||
token = GetNextToken()
|
||||
yield token
|
||||
|
||||
def _GetParameters(self):
|
||||
return self._GetMatchingChar('(', ')')
|
||||
|
||||
def GetScope(self):
|
||||
return self._GetMatchingChar('{', '}')
|
||||
|
||||
def _GetNextToken(self):
|
||||
if self.token_queue:
|
||||
return self.token_queue.pop()
|
||||
try:
|
||||
return next(self.tokens)
|
||||
except StopIteration:
|
||||
return
|
||||
|
||||
def _AddBackToken(self, token):
|
||||
if token.whence == tokenize.WHENCE_STREAM:
|
||||
token.whence = tokenize.WHENCE_QUEUE
|
||||
self.token_queue.insert(0, token)
|
||||
else:
|
||||
assert token.whence == tokenize.WHENCE_QUEUE, token
|
||||
self.token_queue.append(token)
|
||||
|
||||
def _AddBackTokens(self, tokens):
|
||||
if tokens:
|
||||
if tokens[-1].whence == tokenize.WHENCE_STREAM:
|
||||
for token in tokens:
|
||||
token.whence = tokenize.WHENCE_QUEUE
|
||||
self.token_queue[:0] = reversed(tokens)
|
||||
else:
|
||||
assert tokens[-1].whence == tokenize.WHENCE_QUEUE, tokens
|
||||
self.token_queue.extend(reversed(tokens))
|
||||
|
||||
def GetName(self, seq=None):
|
||||
"""Returns ([tokens], next_token_info)."""
|
||||
GetNextToken = self._GetNextToken
|
||||
if seq is not None:
|
||||
it = iter(seq)
|
||||
GetNextToken = lambda: next(it)
|
||||
next_token = GetNextToken()
|
||||
tokens = []
|
||||
last_token_was_name = False
|
||||
while (next_token.token_type == tokenize.NAME or
|
||||
(next_token.token_type == tokenize.SYNTAX and
|
||||
next_token.name in ('::', '<'))):
|
||||
# Two NAMEs in a row means the identifier should terminate.
|
||||
# It's probably some sort of variable declaration.
|
||||
if last_token_was_name and next_token.token_type == tokenize.NAME:
|
||||
break
|
||||
last_token_was_name = next_token.token_type == tokenize.NAME
|
||||
tokens.append(next_token)
|
||||
# Handle templated names.
|
||||
if next_token.name == '<':
|
||||
tokens.extend(self._GetMatchingChar('<', '>', GetNextToken))
|
||||
last_token_was_name = True
|
||||
next_token = GetNextToken()
|
||||
return tokens, next_token
|
||||
|
||||
def GetMethod(self, modifiers, templated_types):
|
||||
return_type_and_name = self._GetTokensUpTo(tokenize.SYNTAX, '(')
|
||||
assert len(return_type_and_name) >= 1
|
||||
return self._GetMethod(return_type_and_name, modifiers, templated_types,
|
||||
False)
|
||||
|
||||
def _GetMethod(self, return_type_and_name, modifiers, templated_types,
|
||||
get_paren):
|
||||
template_portion = None
|
||||
if get_paren:
|
||||
token = self._GetNextToken()
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
if token.name == '<':
|
||||
# Handle templatized dtors.
|
||||
template_portion = [token]
|
||||
template_portion.extend(self._GetMatchingChar('<', '>'))
|
||||
token = self._GetNextToken()
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
assert token.name == '(', token
|
||||
|
||||
name = return_type_and_name.pop()
|
||||
# Handle templatized ctors.
|
||||
if name.name == '>':
|
||||
index = 1
|
||||
while return_type_and_name[index].name != '<':
|
||||
index += 1
|
||||
template_portion = return_type_and_name[index:] + [name]
|
||||
del return_type_and_name[index:]
|
||||
name = return_type_and_name.pop()
|
||||
elif name.name == ']':
|
||||
rt = return_type_and_name
|
||||
assert rt[-1].name == '[', return_type_and_name
|
||||
assert rt[-2].name == 'operator', return_type_and_name
|
||||
name_seq = return_type_and_name[-2:]
|
||||
del return_type_and_name[-2:]
|
||||
name = tokenize.Token(tokenize.NAME, 'operator[]',
|
||||
name_seq[0].start, name.end)
|
||||
# Get the open paren so _GetParameters() below works.
|
||||
unused_open_paren = self._GetNextToken()
|
||||
|
||||
# TODO(nnorwitz): store template_portion.
|
||||
return_type = return_type_and_name
|
||||
indices = name
|
||||
if return_type:
|
||||
indices = return_type[0]
|
||||
|
||||
# Force ctor for templatized ctors.
|
||||
if name.name == self.in_class and not modifiers:
|
||||
modifiers |= FUNCTION_CTOR
|
||||
parameters = list(self._GetParameters())
|
||||
del parameters[-1] # Remove trailing ')'.
|
||||
|
||||
# Handling operator() is especially weird.
|
||||
if name.name == 'operator' and not parameters:
|
||||
token = self._GetNextToken()
|
||||
assert token.name == '(', token
|
||||
parameters = list(self._GetParameters())
|
||||
del parameters[-1] # Remove trailing ')'.
|
||||
|
||||
token = self._GetNextToken()
|
||||
while token.token_type == tokenize.NAME:
|
||||
modifier_token = token
|
||||
token = self._GetNextToken()
|
||||
if modifier_token.name == 'const':
|
||||
modifiers |= FUNCTION_CONST
|
||||
elif modifier_token.name == '__attribute__':
|
||||
# TODO(nnorwitz): handle more __attribute__ details.
|
||||
modifiers |= FUNCTION_ATTRIBUTE
|
||||
assert token.name == '(', token
|
||||
# Consume everything between the (parens).
|
||||
unused_tokens = list(self._GetMatchingChar('(', ')'))
|
||||
token = self._GetNextToken()
|
||||
elif modifier_token.name == 'throw':
|
||||
modifiers |= FUNCTION_THROW
|
||||
assert token.name == '(', token
|
||||
# Consume everything between the (parens).
|
||||
unused_tokens = list(self._GetMatchingChar('(', ')'))
|
||||
token = self._GetNextToken()
|
||||
elif modifier_token.name == 'override':
|
||||
modifiers |= FUNCTION_OVERRIDE
|
||||
elif modifier_token.name == modifier_token.name.upper():
|
||||
# HACK(nnorwitz): assume that all upper-case names
|
||||
# are some macro we aren't expanding.
|
||||
modifiers |= FUNCTION_UNKNOWN_ANNOTATION
|
||||
else:
|
||||
self.HandleError('unexpected token', modifier_token)
|
||||
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
# Handle ctor initializers.
|
||||
if token.name == ':':
|
||||
# TODO(nnorwitz): anything else to handle for initializer list?
|
||||
while token.name != ';' and token.name != '{':
|
||||
token = self._GetNextToken()
|
||||
|
||||
# Handle pointer to functions that are really data but look
|
||||
# like method declarations.
|
||||
if token.name == '(':
|
||||
if parameters[0].name == '*':
|
||||
# name contains the return type.
|
||||
name = parameters.pop()
|
||||
# parameters contains the name of the data.
|
||||
modifiers = [p.name for p in parameters]
|
||||
# Already at the ( to open the parameter list.
|
||||
function_parameters = list(self._GetMatchingChar('(', ')'))
|
||||
del function_parameters[-1] # Remove trailing ')'.
|
||||
# TODO(nnorwitz): store the function_parameters.
|
||||
token = self._GetNextToken()
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
assert token.name == '<', token
|
||||
templated_types = self._GetTemplatedTypes()
|
||||
# TODO(nnorwitz): for now, just ignore the template params.
|
||||
assert token.name == ';', token
|
||||
return self._CreateVariable(indices, name.name, indices.name,
|
||||
modifiers, '', None)
|
||||
# At this point, we got something like:
|
||||
# return_type (type::*name_)(params);
|
||||
# This is a data member called name_ that is a function pointer.
|
||||
# With this code: void (sq_type::*field_)(string&);
|
||||
# We get: name=void return_type=[] parameters=sq_type ... field_
|
||||
# TODO(nnorwitz): is return_type always empty?
|
||||
# TODO(nnorwitz): this isn't even close to being correct.
|
||||
# Just put in something so we don't crash and can move on.
|
||||
real_name = parameters[-1]
|
||||
modifiers = [p.name for p in self._GetParameters()]
|
||||
del modifiers[-1] # Remove trailing ')'.
|
||||
return self._CreateVariable(indices, real_name.name, indices.name,
|
||||
modifiers, '', None)
|
||||
|
||||
if token.name == '{':
|
||||
body = list(self.GetScope())
|
||||
del body[-1] # Remove trailing '}'.
|
||||
else:
|
||||
body = None
|
||||
if token.name == '=':
|
||||
token = self._GetNextToken()
|
||||
if token.token_type == tokenize.NAME:
|
||||
if token.name == 'class':
|
||||
return self._GetClass(Class, VISIBILITY_PRIVATE, templated_types)
|
||||
elif token.name == 'struct':
|
||||
return self._GetClass(Struct, VISIBILITY_PUBLIC, templated_types)
|
||||
elif token.name == 'friend':
|
||||
return self.handle_friend()
|
||||
|
||||
if token.name == 'default' or token.name == 'delete':
|
||||
# Ignore explicitly defaulted and deleted special members
|
||||
# in C++11.
|
||||
token = self._GetNextToken()
|
||||
else:
|
||||
# Handle pure-virtual declarations.
|
||||
assert token.token_type == tokenize.CONSTANT, token
|
||||
assert token.name == '0', token
|
||||
modifiers |= FUNCTION_PURE_VIRTUAL
|
||||
token = self._GetNextToken()
|
||||
|
||||
if token.name == '[':
|
||||
# TODO(nnorwitz): store tokens and improve parsing.
|
||||
# template <typename T, size_t N> char (&ASH(T (&seq)[N]))[N];
|
||||
tokens = list(self._GetMatchingChar('[', ']'))
|
||||
token = self._GetNextToken()
|
||||
|
||||
assert token.name == ';', (token, return_type_and_name, parameters)
|
||||
|
||||
# Looks like we got a method, not a function.
|
||||
if len(return_type) > 2 and return_type[-1].name == '::':
|
||||
return_type, in_class = \
|
||||
self._GetReturnTypeAndClassName(return_type)
|
||||
return Method(indices.start, indices.end, name.name, in_class,
|
||||
return_type, parameters, modifiers, templated_types,
|
||||
body, self.namespace_stack)
|
||||
return Function(indices.start, indices.end, name.name, return_type,
|
||||
parameters, modifiers, templated_types, body,
|
||||
self.namespace_stack)
|
||||
|
||||
def _GetReturnTypeAndClassName(self, token_seq):
|
||||
# Splitting the return type from the class name in a method
|
||||
# can be tricky. For example, Return::Type::Is::Hard::To::Find().
|
||||
# Where is the return type and where is the class name?
|
||||
# The heuristic used is to pull the last name as the class name.
|
||||
# This includes all the templated type info.
|
||||
# TODO(nnorwitz): if there is only One name like in the
|
||||
# example above, punt and assume the last bit is the class name.
|
||||
|
||||
# Ignore a :: prefix, if exists so we can find the first real name.
|
||||
i = 0
|
||||
if token_seq[0].name == '::':
|
||||
i = 1
|
||||
# Ignore a :: suffix, if exists.
|
||||
end = len(token_seq) - 1
|
||||
if token_seq[end-1].name == '::':
|
||||
end -= 1
|
||||
|
||||
# Make a copy of the sequence so we can append a sentinel
|
||||
# value. This is required for GetName will has to have some
|
||||
# terminating condition beyond the last name.
|
||||
seq_copy = token_seq[i:end]
|
||||
seq_copy.append(tokenize.Token(tokenize.SYNTAX, '', 0, 0))
|
||||
names = []
|
||||
while i < end:
|
||||
# Iterate through the sequence parsing out each name.
|
||||
new_name, next = self.GetName(seq_copy[i:])
|
||||
assert new_name, 'Got empty new_name, next=%s' % next
|
||||
# We got a pointer or ref. Add it to the name.
|
||||
if next and next.token_type == tokenize.SYNTAX:
|
||||
new_name.append(next)
|
||||
names.append(new_name)
|
||||
i += len(new_name)
|
||||
|
||||
# Now that we have the names, it's time to undo what we did.
|
||||
|
||||
# Remove the sentinel value.
|
||||
names[-1].pop()
|
||||
# Flatten the token sequence for the return type.
|
||||
return_type = [e for seq in names[:-1] for e in seq]
|
||||
# The class name is the last name.
|
||||
class_name = names[-1]
|
||||
return return_type, class_name
|
||||
|
||||
def handle_bool(self):
|
||||
pass
|
||||
|
||||
def handle_char(self):
|
||||
pass
|
||||
|
||||
def handle_int(self):
|
||||
pass
|
||||
|
||||
def handle_long(self):
|
||||
pass
|
||||
|
||||
def handle_short(self):
|
||||
pass
|
||||
|
||||
def handle_double(self):
|
||||
pass
|
||||
|
||||
def handle_float(self):
|
||||
pass
|
||||
|
||||
def handle_void(self):
|
||||
pass
|
||||
|
||||
def handle_wchar_t(self):
|
||||
pass
|
||||
|
||||
def handle_unsigned(self):
|
||||
pass
|
||||
|
||||
def handle_signed(self):
|
||||
pass
|
||||
|
||||
def _GetNestedType(self, ctor):
|
||||
name = None
|
||||
name_tokens, token = self.GetName()
|
||||
if name_tokens:
|
||||
name = ''.join([t.name for t in name_tokens])
|
||||
|
||||
# Handle forward declarations.
|
||||
if token.token_type == tokenize.SYNTAX and token.name == ';':
|
||||
return ctor(token.start, token.end, name, None,
|
||||
self.namespace_stack)
|
||||
|
||||
if token.token_type == tokenize.NAME and self._handling_typedef:
|
||||
self._AddBackToken(token)
|
||||
return ctor(token.start, token.end, name, None,
|
||||
self.namespace_stack)
|
||||
|
||||
# Must be the type declaration.
|
||||
fields = list(self._GetMatchingChar('{', '}'))
|
||||
del fields[-1] # Remove trailing '}'.
|
||||
if token.token_type == tokenize.SYNTAX and token.name == '{':
|
||||
next = self._GetNextToken()
|
||||
new_type = ctor(token.start, token.end, name, fields,
|
||||
self.namespace_stack)
|
||||
# A name means this is an anonymous type and the name
|
||||
# is the variable declaration.
|
||||
if next.token_type != tokenize.NAME:
|
||||
return new_type
|
||||
name = new_type
|
||||
token = next
|
||||
|
||||
# Must be variable declaration using the type prefixed with keyword.
|
||||
assert token.token_type == tokenize.NAME, token
|
||||
return self._CreateVariable(token, token.name, name, [], '', None)
|
||||
|
||||
def handle_struct(self):
|
||||
# Special case the handling typedef/aliasing of structs here.
|
||||
# It would be a pain to handle in the class code.
|
||||
name_tokens, var_token = self.GetName()
|
||||
if name_tokens:
|
||||
next_token = self._GetNextToken()
|
||||
is_syntax = (var_token.token_type == tokenize.SYNTAX and
|
||||
var_token.name[0] in '*&')
|
||||
is_variable = (var_token.token_type == tokenize.NAME and
|
||||
next_token.name == ';')
|
||||
variable = var_token
|
||||
if is_syntax and not is_variable:
|
||||
variable = next_token
|
||||
temp = self._GetNextToken()
|
||||
if temp.token_type == tokenize.SYNTAX and temp.name == '(':
|
||||
# Handle methods declared to return a struct.
|
||||
t0 = name_tokens[0]
|
||||
struct = tokenize.Token(tokenize.NAME, 'struct',
|
||||
t0.start-7, t0.start-2)
|
||||
type_and_name = [struct]
|
||||
type_and_name.extend(name_tokens)
|
||||
type_and_name.extend((var_token, next_token))
|
||||
return self._GetMethod(type_and_name, 0, None, False)
|
||||
assert temp.name == ';', (temp, name_tokens, var_token)
|
||||
if is_syntax or (is_variable and not self._handling_typedef):
|
||||
modifiers = ['struct']
|
||||
type_name = ''.join([t.name for t in name_tokens])
|
||||
position = name_tokens[0]
|
||||
return self._CreateVariable(position, variable.name, type_name,
|
||||
modifiers, var_token.name, None)
|
||||
name_tokens.extend((var_token, next_token))
|
||||
self._AddBackTokens(name_tokens)
|
||||
else:
|
||||
self._AddBackToken(var_token)
|
||||
return self._GetClass(Struct, VISIBILITY_PUBLIC, None)
|
||||
|
||||
def handle_union(self):
|
||||
return self._GetNestedType(Union)
|
||||
|
||||
def handle_enum(self):
|
||||
return self._GetNestedType(Enum)
|
||||
|
||||
def handle_auto(self):
|
||||
# TODO(nnorwitz): warn about using auto? Probably not since it
|
||||
# will be reclaimed and useful for C++0x.
|
||||
pass
|
||||
|
||||
def handle_register(self):
|
||||
pass
|
||||
|
||||
def handle_const(self):
|
||||
pass
|
||||
|
||||
def handle_inline(self):
|
||||
pass
|
||||
|
||||
def handle_extern(self):
|
||||
pass
|
||||
|
||||
def handle_static(self):
|
||||
pass
|
||||
|
||||
def handle_virtual(self):
|
||||
# What follows must be a method.
|
||||
token = token2 = self._GetNextToken()
|
||||
if token.name == 'inline':
|
||||
# HACK(nnorwitz): handle inline dtors by ignoring 'inline'.
|
||||
token2 = self._GetNextToken()
|
||||
if token2.token_type == tokenize.SYNTAX and token2.name == '~':
|
||||
return self.GetMethod(FUNCTION_VIRTUAL + FUNCTION_DTOR, None)
|
||||
assert token.token_type == tokenize.NAME or token.name == '::', token
|
||||
return_type_and_name, _ = self._GetVarTokensUpToIgnoringTemplates(
|
||||
tokenize.SYNTAX, '(') # )
|
||||
return_type_and_name.insert(0, token)
|
||||
if token2 is not token:
|
||||
return_type_and_name.insert(1, token2)
|
||||
return self._GetMethod(return_type_and_name, FUNCTION_VIRTUAL,
|
||||
None, False)
|
||||
|
||||
def handle_volatile(self):
|
||||
pass
|
||||
|
||||
def handle_mutable(self):
|
||||
pass
|
||||
|
||||
def handle_public(self):
|
||||
assert self.in_class
|
||||
self.visibility = VISIBILITY_PUBLIC
|
||||
|
||||
def handle_protected(self):
|
||||
assert self.in_class
|
||||
self.visibility = VISIBILITY_PROTECTED
|
||||
|
||||
def handle_private(self):
|
||||
assert self.in_class
|
||||
self.visibility = VISIBILITY_PRIVATE
|
||||
|
||||
def handle_friend(self):
|
||||
tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
|
||||
assert tokens
|
||||
t0 = tokens[0]
|
||||
return Friend(t0.start, t0.end, tokens, self.namespace_stack)
|
||||
|
||||
def handle_static_cast(self):
|
||||
pass
|
||||
|
||||
def handle_const_cast(self):
|
||||
pass
|
||||
|
||||
def handle_dynamic_cast(self):
|
||||
pass
|
||||
|
||||
def handle_reinterpret_cast(self):
|
||||
pass
|
||||
|
||||
def handle_new(self):
|
||||
pass
|
||||
|
||||
def handle_delete(self):
|
||||
tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
|
||||
assert tokens
|
||||
return Delete(tokens[0].start, tokens[0].end, tokens)
|
||||
|
||||
def handle_typedef(self):
|
||||
token = self._GetNextToken()
|
||||
if (token.token_type == tokenize.NAME and
|
||||
keywords.IsKeyword(token.name)):
|
||||
# Token must be struct/enum/union/class.
|
||||
method = getattr(self, 'handle_' + token.name)
|
||||
self._handling_typedef = True
|
||||
tokens = [method()]
|
||||
self._handling_typedef = False
|
||||
else:
|
||||
tokens = [token]
|
||||
|
||||
# Get the remainder of the typedef up to the semi-colon.
|
||||
tokens.extend(self._GetTokensUpTo(tokenize.SYNTAX, ';'))
|
||||
|
||||
# TODO(nnorwitz): clean all this up.
|
||||
assert tokens
|
||||
name = tokens.pop()
|
||||
indices = name
|
||||
if tokens:
|
||||
indices = tokens[0]
|
||||
if not indices:
|
||||
indices = token
|
||||
if name.name == ')':
|
||||
# HACK(nnorwitz): Handle pointers to functions "properly".
|
||||
if (len(tokens) >= 4 and
|
||||
tokens[1].name == '(' and tokens[2].name == '*'):
|
||||
tokens.append(name)
|
||||
name = tokens[3]
|
||||
elif name.name == ']':
|
||||
# HACK(nnorwitz): Handle arrays properly.
|
||||
if len(tokens) >= 2:
|
||||
tokens.append(name)
|
||||
name = tokens[1]
|
||||
new_type = tokens
|
||||
if tokens and isinstance(tokens[0], tokenize.Token):
|
||||
new_type = self.converter.ToType(tokens)[0]
|
||||
return Typedef(indices.start, indices.end, name.name,
|
||||
new_type, self.namespace_stack)
|
||||
|
||||
def handle_typeid(self):
|
||||
pass # Not needed yet.
|
||||
|
||||
def handle_typename(self):
|
||||
pass # Not needed yet.
|
||||
|
||||
def _GetTemplatedTypes(self):
|
||||
result = {}
|
||||
tokens = list(self._GetMatchingChar('<', '>'))
|
||||
len_tokens = len(tokens) - 1 # Ignore trailing '>'.
|
||||
i = 0
|
||||
while i < len_tokens:
|
||||
key = tokens[i].name
|
||||
i += 1
|
||||
if keywords.IsKeyword(key) or key == ',':
|
||||
continue
|
||||
type_name = default = None
|
||||
if i < len_tokens:
|
||||
i += 1
|
||||
if tokens[i-1].name == '=':
|
||||
assert i < len_tokens, '%s %s' % (i, tokens)
|
||||
default, unused_next_token = self.GetName(tokens[i:])
|
||||
i += len(default)
|
||||
else:
|
||||
if tokens[i-1].name != ',':
|
||||
# We got something like: Type variable.
|
||||
# Re-adjust the key (variable) and type_name (Type).
|
||||
key = tokens[i-1].name
|
||||
type_name = tokens[i-2]
|
||||
|
||||
result[key] = (type_name, default)
|
||||
return result
|
||||
|
||||
def handle_template(self):
|
||||
token = self._GetNextToken()
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
assert token.name == '<', token
|
||||
templated_types = self._GetTemplatedTypes()
|
||||
# TODO(nnorwitz): for now, just ignore the template params.
|
||||
token = self._GetNextToken()
|
||||
if token.token_type == tokenize.NAME:
|
||||
if token.name == 'class':
|
||||
return self._GetClass(Class, VISIBILITY_PRIVATE, templated_types)
|
||||
elif token.name == 'struct':
|
||||
return self._GetClass(Struct, VISIBILITY_PUBLIC, templated_types)
|
||||
elif token.name == 'friend':
|
||||
return self.handle_friend()
|
||||
self._AddBackToken(token)
|
||||
tokens, last = self._GetVarTokensUpTo(tokenize.SYNTAX, '(', ';')
|
||||
tokens.append(last)
|
||||
self._AddBackTokens(tokens)
|
||||
if last.name == '(':
|
||||
return self.GetMethod(FUNCTION_NONE, templated_types)
|
||||
# Must be a variable definition.
|
||||
return None
|
||||
|
||||
def handle_true(self):
|
||||
pass # Nothing to do.
|
||||
|
||||
def handle_false(self):
|
||||
pass # Nothing to do.
|
||||
|
||||
def handle_asm(self):
|
||||
pass # Not needed yet.
|
||||
|
||||
def handle_class(self):
|
||||
return self._GetClass(Class, VISIBILITY_PRIVATE, None)
|
||||
|
||||
def _GetBases(self):
|
||||
# Get base classes.
|
||||
bases = []
|
||||
while 1:
|
||||
token = self._GetNextToken()
|
||||
assert token.token_type == tokenize.NAME, token
|
||||
# TODO(nnorwitz): store kind of inheritance...maybe.
|
||||
if token.name not in ('public', 'protected', 'private'):
|
||||
# If inheritance type is not specified, it is private.
|
||||
# Just put the token back so we can form a name.
|
||||
# TODO(nnorwitz): it would be good to warn about this.
|
||||
self._AddBackToken(token)
|
||||
tokens, last = self._GetVarTokensUpTo(tokenize.SYNTAX, '(', ';')
|
||||
tokens.append(last)
|
||||
self._AddBackTokens(tokens)
|
||||
if last.name == '(':
|
||||
return self.GetMethod(FUNCTION_NONE, templated_types)
|
||||
# Must be a variable definition.
|
||||
return None
|
||||
|
||||
def handle_true(self):
|
||||
pass # Nothing to do.
|
||||
|
||||
def handle_false(self):
|
||||
pass # Nothing to do.
|
||||
|
||||
def handle_asm(self):
|
||||
pass # Not needed yet.
|
||||
|
||||
def handle_class(self):
|
||||
return self._GetClass(Class, VISIBILITY_PRIVATE, None)
|
||||
|
||||
def _GetBases(self):
|
||||
# Get base classes.
|
||||
bases = []
|
||||
while 1:
|
||||
token = self._GetNextToken()
|
||||
assert token.token_type == tokenize.NAME, token
|
||||
# TODO(nnorwitz): store kind of inheritance...maybe.
|
||||
if token.name not in ('public', 'protected', 'private'):
|
||||
# If inheritance type is not specified, it is private.
|
||||
# Just put the token back so we can form a name.
|
||||
# TODO(nnorwitz): it would be good to warn about this.
|
||||
self._AddBackToken(token)
|
||||
else:
|
||||
# Check for virtual inheritance.
|
||||
token = self._GetNextToken()
|
||||
if token.name != 'virtual':
|
||||
self._AddBackToken(token)
|
||||
else:
|
||||
# TODO(nnorwitz): store that we got virtual for this base.
|
||||
pass
|
||||
base, next_token = self.GetName()
|
||||
bases_ast = self.converter.ToType(base)
|
||||
assert len(bases_ast) == 1, bases_ast
|
||||
bases.append(bases_ast[0])
|
||||
assert next_token.token_type == tokenize.SYNTAX, next_token
|
||||
if next_token.name == '{':
|
||||
token = next_token
|
||||
break
|
||||
# Support multiple inheritance.
|
||||
assert next_token.name == ',', next_token
|
||||
return bases, token
|
||||
|
||||
def _GetClass(self, class_type, visibility, templated_types):
|
||||
class_name = None
|
||||
class_token = self._GetNextToken()
|
||||
if class_token.token_type != tokenize.NAME:
|
||||
assert class_token.token_type == tokenize.SYNTAX, class_token
|
||||
token = class_token
|
||||
else:
|
||||
# Skip any macro (e.g. storage class specifiers) after the
|
||||
# 'class' keyword.
|
||||
next_token = self._GetNextToken()
|
||||
if next_token.token_type == tokenize.NAME:
|
||||
self._AddBackToken(next_token)
|
||||
else:
|
||||
self._AddBackTokens([class_token, next_token])
|
||||
name_tokens, token = self.GetName()
|
||||
class_name = ''.join([t.name for t in name_tokens])
|
||||
bases = None
|
||||
if token.token_type == tokenize.SYNTAX:
|
||||
if token.name == ';':
|
||||
# Forward declaration.
|
||||
return class_type(class_token.start, class_token.end,
|
||||
class_name, None, templated_types, None,
|
||||
self.namespace_stack)
|
||||
if token.name in '*&':
|
||||
# Inline forward declaration. Could be method or data.
|
||||
name_token = self._GetNextToken()
|
||||
next_token = self._GetNextToken()
|
||||
if next_token.name == ';':
|
||||
# Handle data
|
||||
modifiers = ['class']
|
||||
return self._CreateVariable(class_token, name_token.name,
|
||||
class_name,
|
||||
modifiers, token.name, None)
|
||||
else:
|
||||
# Assume this is a method.
|
||||
tokens = (class_token, token, name_token, next_token)
|
||||
self._AddBackTokens(tokens)
|
||||
return self.GetMethod(FUNCTION_NONE, None)
|
||||
if token.name == ':':
|
||||
bases, token = self._GetBases()
|
||||
|
||||
body = None
|
||||
if token.token_type == tokenize.SYNTAX and token.name == '{':
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
assert token.name == '{', token
|
||||
|
||||
ast = AstBuilder(self.GetScope(), self.filename, class_name,
|
||||
visibility, self.namespace_stack)
|
||||
body = list(ast.Generate())
|
||||
|
||||
if not self._handling_typedef:
|
||||
token = self._GetNextToken()
|
||||
if token.token_type != tokenize.NAME:
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
assert token.name == ';', token
|
||||
else:
|
||||
new_class = class_type(class_token.start, class_token.end,
|
||||
class_name, bases, None,
|
||||
body, self.namespace_stack)
|
||||
|
||||
modifiers = []
|
||||
return self._CreateVariable(class_token,
|
||||
token.name, new_class,
|
||||
modifiers, token.name, None)
|
||||
else:
|
||||
if not self._handling_typedef:
|
||||
self.HandleError('non-typedef token', token)
|
||||
self._AddBackToken(token)
|
||||
|
||||
return class_type(class_token.start, class_token.end, class_name,
|
||||
bases, templated_types, body, self.namespace_stack)
|
||||
|
||||
def handle_namespace(self):
|
||||
else:
|
||||
# Check for virtual inheritance.
|
||||
token = self._GetNextToken()
|
||||
# Support anonymous namespaces.
|
||||
name = None
|
||||
if token.token_type == tokenize.NAME:
|
||||
name = token.name
|
||||
token = self._GetNextToken()
|
||||
self.namespace_stack.append(name)
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
# Create an internal token that denotes when the namespace is complete.
|
||||
internal_token = tokenize.Token(_INTERNAL_TOKEN, _NAMESPACE_POP,
|
||||
None, None)
|
||||
internal_token.whence = token.whence
|
||||
if token.name == '=':
|
||||
# TODO(nnorwitz): handle aliasing namespaces.
|
||||
name, next_token = self.GetName()
|
||||
assert next_token.name == ';', next_token
|
||||
self._AddBackToken(internal_token)
|
||||
if token.name != 'virtual':
|
||||
self._AddBackToken(token)
|
||||
else:
|
||||
assert token.name == '{', token
|
||||
tokens = list(self.GetScope())
|
||||
# Replace the trailing } with the internal namespace pop token.
|
||||
tokens[-1] = internal_token
|
||||
# Handle namespace with nothing in it.
|
||||
self._AddBackTokens(tokens)
|
||||
return None
|
||||
# TODO(nnorwitz): store that we got virtual for this base.
|
||||
pass
|
||||
base, next_token = self.GetName()
|
||||
bases_ast = self.converter.ToType(base)
|
||||
assert len(bases_ast) == 1, bases_ast
|
||||
bases.append(bases_ast[0])
|
||||
assert next_token.token_type == tokenize.SYNTAX, next_token
|
||||
if next_token.name == '{':
|
||||
token = next_token
|
||||
break
|
||||
# Support multiple inheritance.
|
||||
assert next_token.name == ',', next_token
|
||||
return bases, token
|
||||
|
||||
def handle_using(self):
|
||||
tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
|
||||
assert tokens
|
||||
return Using(tokens[0].start, tokens[0].end, tokens)
|
||||
def _GetClass(self, class_type, visibility, templated_types):
|
||||
class_name = None
|
||||
class_token = self._GetNextToken()
|
||||
if class_token.token_type != tokenize.NAME:
|
||||
assert class_token.token_type == tokenize.SYNTAX, class_token
|
||||
token = class_token
|
||||
else:
|
||||
# Skip any macro (e.g. storage class specifiers) after the
|
||||
# 'class' keyword.
|
||||
next_token = self._GetNextToken()
|
||||
if next_token.token_type == tokenize.NAME:
|
||||
self._AddBackToken(next_token)
|
||||
else:
|
||||
self._AddBackTokens([class_token, next_token])
|
||||
name_tokens, token = self.GetName()
|
||||
class_name = ''.join([t.name for t in name_tokens])
|
||||
bases = None
|
||||
if token.token_type == tokenize.SYNTAX:
|
||||
if token.name == ';':
|
||||
# Forward declaration.
|
||||
return class_type(class_token.start, class_token.end,
|
||||
class_name, None, templated_types, None,
|
||||
self.namespace_stack)
|
||||
if token.name in '*&':
|
||||
# Inline forward declaration. Could be method or data.
|
||||
name_token = self._GetNextToken()
|
||||
next_token = self._GetNextToken()
|
||||
if next_token.name == ';':
|
||||
# Handle data
|
||||
modifiers = ['class']
|
||||
return self._CreateVariable(class_token, name_token.name,
|
||||
class_name,
|
||||
modifiers, token.name, None)
|
||||
else:
|
||||
# Assume this is a method.
|
||||
tokens = (class_token, token, name_token, next_token)
|
||||
self._AddBackTokens(tokens)
|
||||
return self.GetMethod(FUNCTION_NONE, None)
|
||||
if token.name == ':':
|
||||
bases, token = self._GetBases()
|
||||
|
||||
def handle_explicit(self):
|
||||
assert self.in_class
|
||||
# Nothing much to do.
|
||||
# TODO(nnorwitz): maybe verify the method name == class name.
|
||||
# This must be a ctor.
|
||||
return self.GetMethod(FUNCTION_CTOR, None)
|
||||
body = None
|
||||
if token.token_type == tokenize.SYNTAX and token.name == '{':
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
assert token.name == '{', token
|
||||
|
||||
def handle_this(self):
|
||||
pass # Nothing to do.
|
||||
ast = AstBuilder(self.GetScope(), self.filename, class_name,
|
||||
visibility, self.namespace_stack)
|
||||
body = list(ast.Generate())
|
||||
|
||||
def handle_operator(self):
|
||||
# Pull off the next token(s?) and make that part of the method name.
|
||||
pass
|
||||
|
||||
def handle_sizeof(self):
|
||||
pass
|
||||
|
||||
def handle_case(self):
|
||||
pass
|
||||
|
||||
def handle_switch(self):
|
||||
pass
|
||||
|
||||
def handle_default(self):
|
||||
if not self._handling_typedef:
|
||||
token = self._GetNextToken()
|
||||
assert token.token_type == tokenize.SYNTAX
|
||||
assert token.name == ':'
|
||||
if token.token_type != tokenize.NAME:
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
assert token.name == ';', token
|
||||
else:
|
||||
new_class = class_type(class_token.start, class_token.end,
|
||||
class_name, bases, None,
|
||||
body, self.namespace_stack)
|
||||
|
||||
def handle_if(self):
|
||||
pass
|
||||
modifiers = []
|
||||
return self._CreateVariable(class_token,
|
||||
token.name, new_class,
|
||||
modifiers, token.name, None)
|
||||
else:
|
||||
if not self._handling_typedef:
|
||||
self.HandleError('non-typedef token', token)
|
||||
self._AddBackToken(token)
|
||||
|
||||
def handle_else(self):
|
||||
pass
|
||||
return class_type(class_token.start, class_token.end, class_name,
|
||||
bases, templated_types, body, self.namespace_stack)
|
||||
|
||||
def handle_return(self):
|
||||
tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
|
||||
if not tokens:
|
||||
return Return(self.current_token.start, self.current_token.end, None)
|
||||
return Return(tokens[0].start, tokens[0].end, tokens)
|
||||
def handle_namespace(self):
|
||||
token = self._GetNextToken()
|
||||
# Support anonymous namespaces.
|
||||
name = None
|
||||
if token.token_type == tokenize.NAME:
|
||||
name = token.name
|
||||
token = self._GetNextToken()
|
||||
self.namespace_stack.append(name)
|
||||
assert token.token_type == tokenize.SYNTAX, token
|
||||
# Create an internal token that denotes when the namespace is complete.
|
||||
internal_token = tokenize.Token(_INTERNAL_TOKEN, _NAMESPACE_POP,
|
||||
None, None)
|
||||
internal_token.whence = token.whence
|
||||
if token.name == '=':
|
||||
# TODO(nnorwitz): handle aliasing namespaces.
|
||||
name, next_token = self.GetName()
|
||||
assert next_token.name == ';', next_token
|
||||
self._AddBackToken(internal_token)
|
||||
else:
|
||||
assert token.name == '{', token
|
||||
tokens = list(self.GetScope())
|
||||
# Replace the trailing } with the internal namespace pop token.
|
||||
tokens[-1] = internal_token
|
||||
# Handle namespace with nothing in it.
|
||||
self._AddBackTokens(tokens)
|
||||
return None
|
||||
|
||||
def handle_goto(self):
|
||||
tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
|
||||
assert len(tokens) == 1, str(tokens)
|
||||
return Goto(tokens[0].start, tokens[0].end, tokens[0].name)
|
||||
def handle_using(self):
|
||||
tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
|
||||
assert tokens
|
||||
return Using(tokens[0].start, tokens[0].end, tokens)
|
||||
|
||||
def handle_try(self):
|
||||
pass # Not needed yet.
|
||||
def handle_explicit(self):
|
||||
assert self.in_class
|
||||
# Nothing much to do.
|
||||
# TODO(nnorwitz): maybe verify the method name == class name.
|
||||
# This must be a ctor.
|
||||
return self.GetMethod(FUNCTION_CTOR, None)
|
||||
|
||||
def handle_catch(self):
|
||||
pass # Not needed yet.
|
||||
def handle_this(self):
|
||||
pass # Nothing to do.
|
||||
|
||||
def handle_throw(self):
|
||||
pass # Not needed yet.
|
||||
def handle_operator(self):
|
||||
# Pull off the next token(s?) and make that part of the method name.
|
||||
pass
|
||||
|
||||
def handle_while(self):
|
||||
pass
|
||||
def handle_sizeof(self):
|
||||
pass
|
||||
|
||||
def handle_do(self):
|
||||
pass
|
||||
def handle_case(self):
|
||||
pass
|
||||
|
||||
def handle_for(self):
|
||||
pass
|
||||
def handle_switch(self):
|
||||
pass
|
||||
|
||||
def handle_break(self):
|
||||
self._IgnoreUpTo(tokenize.SYNTAX, ';')
|
||||
def handle_default(self):
|
||||
token = self._GetNextToken()
|
||||
assert token.token_type == tokenize.SYNTAX
|
||||
assert token.name == ':'
|
||||
|
||||
def handle_continue(self):
|
||||
self._IgnoreUpTo(tokenize.SYNTAX, ';')
|
||||
def handle_if(self):
|
||||
pass
|
||||
|
||||
def handle_else(self):
|
||||
pass
|
||||
|
||||
def handle_return(self):
|
||||
tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
|
||||
if not tokens:
|
||||
return Return(self.current_token.start, self.current_token.end, None)
|
||||
return Return(tokens[0].start, tokens[0].end, tokens)
|
||||
|
||||
def handle_goto(self):
|
||||
tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
|
||||
assert len(tokens) == 1, str(tokens)
|
||||
return Goto(tokens[0].start, tokens[0].end, tokens[0].name)
|
||||
|
||||
def handle_try(self):
|
||||
pass # Not needed yet.
|
||||
|
||||
def handle_catch(self):
|
||||
pass # Not needed yet.
|
||||
|
||||
def handle_throw(self):
|
||||
pass # Not needed yet.
|
||||
|
||||
def handle_while(self):
|
||||
pass
|
||||
|
||||
def handle_do(self):
|
||||
pass
|
||||
|
||||
def handle_for(self):
|
||||
pass
|
||||
|
||||
def handle_break(self):
|
||||
self._IgnoreUpTo(tokenize.SYNTAX, ';')
|
||||
|
||||
def handle_continue(self):
|
||||
self._IgnoreUpTo(tokenize.SYNTAX, ';')
|
||||
|
||||
|
||||
def BuilderFromSource(source, filename):
|
||||
"""Utility method that returns an AstBuilder from source code.
|
||||
"""Utility method that returns an AstBuilder from source code.
|
||||
|
||||
Args:
|
||||
source: 'C++ source code'
|
||||
@@ -1698,64 +1710,64 @@ def BuilderFromSource(source, filename):
|
||||
Returns:
|
||||
AstBuilder
|
||||
"""
|
||||
return AstBuilder(tokenize.GetTokens(source), filename)
|
||||
return AstBuilder(tokenize.GetTokens(source), filename)
|
||||
|
||||
|
||||
def PrintIndentifiers(filename, should_print):
|
||||
"""Prints all identifiers for a C++ source file.
|
||||
"""Prints all identifiers for a C++ source file.
|
||||
|
||||
Args:
|
||||
filename: 'file1'
|
||||
should_print: predicate with signature: bool Function(token)
|
||||
"""
|
||||
source = utils.ReadFile(filename, False)
|
||||
if source is None:
|
||||
sys.stderr.write('Unable to find: %s\n' % filename)
|
||||
return
|
||||
source = utils.ReadFile(filename, False)
|
||||
if source is None:
|
||||
sys.stderr.write('Unable to find: %s\n' % filename)
|
||||
return
|
||||
|
||||
#print('Processing %s' % actual_filename)
|
||||
builder = BuilderFromSource(source, filename)
|
||||
try:
|
||||
for node in builder.Generate():
|
||||
if should_print(node):
|
||||
print(node.name)
|
||||
except KeyboardInterrupt:
|
||||
return
|
||||
except:
|
||||
pass
|
||||
#print('Processing %s' % actual_filename)
|
||||
builder = BuilderFromSource(source, filename)
|
||||
try:
|
||||
for node in builder.Generate():
|
||||
if should_print(node):
|
||||
print(node.name)
|
||||
except KeyboardInterrupt:
|
||||
return
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def PrintAllIndentifiers(filenames, should_print):
|
||||
"""Prints all identifiers for each C++ source file in filenames.
|
||||
"""Prints all identifiers for each C++ source file in filenames.
|
||||
|
||||
Args:
|
||||
filenames: ['file1', 'file2', ...]
|
||||
should_print: predicate with signature: bool Function(token)
|
||||
"""
|
||||
for path in filenames:
|
||||
PrintIndentifiers(path, should_print)
|
||||
for path in filenames:
|
||||
PrintIndentifiers(path, should_print)
|
||||
|
||||
|
||||
def main(argv):
|
||||
for filename in argv[1:]:
|
||||
source = utils.ReadFile(filename)
|
||||
if source is None:
|
||||
continue
|
||||
for filename in argv[1:]:
|
||||
source = utils.ReadFile(filename)
|
||||
if source is None:
|
||||
continue
|
||||
|
||||
print('Processing %s' % filename)
|
||||
builder = BuilderFromSource(source, filename)
|
||||
try:
|
||||
entire_ast = filter(None, builder.Generate())
|
||||
except KeyboardInterrupt:
|
||||
return
|
||||
except:
|
||||
# Already printed a warning, print the traceback and continue.
|
||||
traceback.print_exc()
|
||||
else:
|
||||
if utils.DEBUG:
|
||||
for ast in entire_ast:
|
||||
print(ast)
|
||||
print('Processing %s' % filename)
|
||||
builder = BuilderFromSource(source, filename)
|
||||
try:
|
||||
entire_ast = filter(None, builder.Generate())
|
||||
except KeyboardInterrupt:
|
||||
return
|
||||
except:
|
||||
# Already printed a warning, print the traceback and continue.
|
||||
traceback.print_exc()
|
||||
else:
|
||||
if utils.DEBUG:
|
||||
for ast in entire_ast:
|
||||
print(ast)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
||||
main(sys.argv)
|
||||
|
||||
@@ -35,11 +35,11 @@ from cpp import utils
|
||||
|
||||
# Preserve compatibility with Python 2.3.
|
||||
try:
|
||||
_dummy = set
|
||||
_dummy = set
|
||||
except NameError:
|
||||
import sets
|
||||
import sets
|
||||
|
||||
set = sets.Set
|
||||
set = sets.Set
|
||||
|
||||
_VERSION = (1, 0, 1) # The version of this script.
|
||||
# How many spaces to indent. Can set me with the INDENT environment variable.
|
||||
@@ -47,202 +47,199 @@ _INDENT = 2
|
||||
|
||||
|
||||
def _RenderType(ast_type):
|
||||
"""Renders the potentially recursively templated type into a string.
|
||||
"""Renders the potentially recursively templated type into a string.
|
||||
|
||||
Args:
|
||||
ast_type: The AST of the type.
|
||||
|
||||
Returns:
|
||||
Rendered string and a boolean to indicate whether we have multiple args
|
||||
(which is not handled correctly).
|
||||
Rendered string of the type.
|
||||
"""
|
||||
has_multiarg_error = False
|
||||
# Add modifiers like 'const'.
|
||||
modifiers = ''
|
||||
if ast_type.modifiers:
|
||||
modifiers = ' '.join(ast_type.modifiers) + ' '
|
||||
return_type = modifiers + ast_type.name
|
||||
if ast_type.templated_types:
|
||||
# Collect template args.
|
||||
template_args = []
|
||||
for arg in ast_type.templated_types:
|
||||
rendered_arg, e = _RenderType(arg)
|
||||
if e: has_multiarg_error = True
|
||||
template_args.append(rendered_arg)
|
||||
return_type += '<' + ', '.join(template_args) + '>'
|
||||
# We are actually not handling multi-template-args correctly. So mark it.
|
||||
if len(template_args) > 1:
|
||||
has_multiarg_error = True
|
||||
if ast_type.pointer:
|
||||
return_type += '*'
|
||||
if ast_type.reference:
|
||||
return_type += '&'
|
||||
return return_type, has_multiarg_error
|
||||
# Add modifiers like 'const'.
|
||||
modifiers = ''
|
||||
if ast_type.modifiers:
|
||||
modifiers = ' '.join(ast_type.modifiers) + ' '
|
||||
return_type = modifiers + ast_type.name
|
||||
if ast_type.templated_types:
|
||||
# Collect template args.
|
||||
template_args = []
|
||||
for arg in ast_type.templated_types:
|
||||
rendered_arg = _RenderType(arg)
|
||||
template_args.append(rendered_arg)
|
||||
return_type += '<' + ', '.join(template_args) + '>'
|
||||
if ast_type.pointer:
|
||||
return_type += '*'
|
||||
if ast_type.reference:
|
||||
return_type += '&'
|
||||
return return_type
|
||||
|
||||
|
||||
def _GetNumParameters(parameters, source):
|
||||
num_parameters = len(parameters)
|
||||
if num_parameters == 1:
|
||||
first_param = parameters[0]
|
||||
if source[first_param.start:first_param.end].strip() == 'void':
|
||||
# We must treat T(void) as a function with no parameters.
|
||||
return 0
|
||||
return num_parameters
|
||||
def _GenerateArg(source):
|
||||
"""Strips out comments, default arguments, and redundant spaces from a single argument.
|
||||
|
||||
Args:
|
||||
source: A string for a single argument.
|
||||
|
||||
Returns:
|
||||
Rendered string of the argument.
|
||||
"""
|
||||
# Remove end of line comments before eliminating newlines.
|
||||
arg = re.sub(r'//.*', '', source)
|
||||
|
||||
# Remove c-style comments.
|
||||
arg = re.sub(r'/\*.*\*/', '', arg)
|
||||
|
||||
# Remove default arguments.
|
||||
arg = re.sub(r'=.*', '', arg)
|
||||
|
||||
# Collapse spaces and newlines into a single space.
|
||||
arg = re.sub(r'\s+', ' ', arg)
|
||||
return arg.strip()
|
||||
|
||||
|
||||
def _EscapeForMacro(s):
|
||||
"""Escapes a string for use as an argument to a C++ macro."""
|
||||
paren_count = 0
|
||||
for c in s:
|
||||
if c == '(':
|
||||
paren_count += 1
|
||||
elif c == ')':
|
||||
paren_count -= 1
|
||||
elif c == ',' and paren_count == 0:
|
||||
return '(' + s + ')'
|
||||
return s
|
||||
|
||||
|
||||
def _GenerateMethods(output_lines, source, class_node):
|
||||
function_type = (ast.FUNCTION_VIRTUAL | ast.FUNCTION_PURE_VIRTUAL |
|
||||
ast.FUNCTION_OVERRIDE)
|
||||
ctor_or_dtor = ast.FUNCTION_CTOR | ast.FUNCTION_DTOR
|
||||
indent = ' ' * _INDENT
|
||||
function_type = (
|
||||
ast.FUNCTION_VIRTUAL | ast.FUNCTION_PURE_VIRTUAL | ast.FUNCTION_OVERRIDE)
|
||||
ctor_or_dtor = ast.FUNCTION_CTOR | ast.FUNCTION_DTOR
|
||||
indent = ' ' * _INDENT
|
||||
|
||||
for node in class_node.body:
|
||||
# We only care about virtual functions.
|
||||
if (isinstance(node, ast.Function) and
|
||||
node.modifiers & function_type and
|
||||
not node.modifiers & ctor_or_dtor):
|
||||
# Pick out all the elements we need from the original function.
|
||||
const = ''
|
||||
if node.modifiers & ast.FUNCTION_CONST:
|
||||
const = 'CONST_'
|
||||
num_parameters = _GetNumParameters(node.parameters, source)
|
||||
return_type = 'void'
|
||||
if node.return_type:
|
||||
return_type, has_multiarg_error = _RenderType(node.return_type)
|
||||
if has_multiarg_error:
|
||||
for line in [
|
||||
'// The following line won\'t really compile, as the return',
|
||||
'// type has multiple template arguments. To fix it, use a',
|
||||
'// typedef for the return type.']:
|
||||
output_lines.append(indent + line)
|
||||
tmpl = ''
|
||||
if class_node.templated_types:
|
||||
tmpl = '_T'
|
||||
mock_method_macro = 'MOCK_%sMETHOD%d%s' % (const, num_parameters, tmpl)
|
||||
for node in class_node.body:
|
||||
# We only care about virtual functions.
|
||||
if (isinstance(node, ast.Function) and node.modifiers & function_type and
|
||||
not node.modifiers & ctor_or_dtor):
|
||||
# Pick out all the elements we need from the original function.
|
||||
modifiers = 'override'
|
||||
if node.modifiers & ast.FUNCTION_CONST:
|
||||
modifiers = 'const, ' + modifiers
|
||||
|
||||
args = ''
|
||||
if node.parameters:
|
||||
# Get the full text of the parameters from the start
|
||||
# of the first parameter to the end of the last parameter.
|
||||
start = node.parameters[0].start
|
||||
end = node.parameters[-1].end
|
||||
# Remove // comments.
|
||||
args_strings = re.sub(r'//.*', '', source[start:end])
|
||||
# Remove /* comments */.
|
||||
args_strings = re.sub(r'/\*.*\*/', '', args_strings)
|
||||
# Remove default arguments.
|
||||
args_strings = re.sub(r'=.*,', ',', args_strings)
|
||||
args_strings = re.sub(r'=.*', '', args_strings)
|
||||
# Condense multiple spaces and eliminate newlines putting the
|
||||
# parameters together on a single line. Ensure there is a
|
||||
# space in an argument which is split by a newline without
|
||||
# intervening whitespace, e.g.: int\nBar
|
||||
args = re.sub(' +', ' ', args_strings.replace('\n', ' '))
|
||||
return_type = 'void'
|
||||
if node.return_type:
|
||||
return_type = _EscapeForMacro(_RenderType(node.return_type))
|
||||
|
||||
# Create the mock method definition.
|
||||
output_lines.extend(['%s%s(%s,' % (indent, mock_method_macro, node.name),
|
||||
'%s%s(%s));' % (indent * 3, return_type, args)])
|
||||
args = []
|
||||
for p in node.parameters:
|
||||
arg = _GenerateArg(source[p.start:p.end])
|
||||
args.append(_EscapeForMacro(arg))
|
||||
|
||||
# Create the mock method definition.
|
||||
output_lines.extend([
|
||||
'%sMOCK_METHOD(%s, %s, (%s), (%s));' %
|
||||
(indent, return_type, node.name, ', '.join(args), modifiers)
|
||||
])
|
||||
|
||||
|
||||
def _GenerateMocks(filename, source, ast_list, desired_class_names):
|
||||
processed_class_names = set()
|
||||
lines = []
|
||||
for node in ast_list:
|
||||
if (isinstance(node, ast.Class) and node.body and
|
||||
# desired_class_names being None means that all classes are selected.
|
||||
(not desired_class_names or node.name in desired_class_names)):
|
||||
class_name = node.name
|
||||
parent_name = class_name
|
||||
processed_class_names.add(class_name)
|
||||
class_node = node
|
||||
# Add namespace before the class.
|
||||
if class_node.namespace:
|
||||
lines.extend(['namespace %s {' % n for n in class_node.namespace]) # }
|
||||
lines.append('')
|
||||
processed_class_names = set()
|
||||
lines = []
|
||||
for node in ast_list:
|
||||
if (isinstance(node, ast.Class) and node.body and
|
||||
# desired_class_names being None means that all classes are selected.
|
||||
(not desired_class_names or node.name in desired_class_names)):
|
||||
class_name = node.name
|
||||
parent_name = class_name
|
||||
processed_class_names.add(class_name)
|
||||
class_node = node
|
||||
# Add namespace before the class.
|
||||
if class_node.namespace:
|
||||
lines.extend(['namespace %s {' % n for n in class_node.namespace]) # }
|
||||
lines.append('')
|
||||
|
||||
# Add template args for templated classes.
|
||||
if class_node.templated_types:
|
||||
# TODO(paulchang): The AST doesn't preserve template argument order,
|
||||
# so we have to make up names here.
|
||||
# TODO(paulchang): Handle non-type template arguments (e.g.
|
||||
# template<typename T, int N>).
|
||||
template_arg_count = len(class_node.templated_types.keys())
|
||||
template_args = ['T%d' % n for n in range(template_arg_count)]
|
||||
template_decls = ['typename ' + arg for arg in template_args]
|
||||
lines.append('template <' + ', '.join(template_decls) + '>')
|
||||
parent_name += '<' + ', '.join(template_args) + '>'
|
||||
# Add template args for templated classes.
|
||||
if class_node.templated_types:
|
||||
# TODO(paulchang): The AST doesn't preserve template argument order,
|
||||
# so we have to make up names here.
|
||||
# TODO(paulchang): Handle non-type template arguments (e.g.
|
||||
# template<typename T, int N>).
|
||||
template_arg_count = len(class_node.templated_types.keys())
|
||||
template_args = ['T%d' % n for n in range(template_arg_count)]
|
||||
template_decls = ['typename ' + arg for arg in template_args]
|
||||
lines.append('template <' + ', '.join(template_decls) + '>')
|
||||
parent_name += '<' + ', '.join(template_args) + '>'
|
||||
|
||||
# Add the class prolog.
|
||||
lines.append('class Mock%s : public %s {' # }
|
||||
% (class_name, parent_name))
|
||||
lines.append('%spublic:' % (' ' * (_INDENT // 2)))
|
||||
# Add the class prolog.
|
||||
lines.append('class Mock%s : public %s {' # }
|
||||
% (class_name, parent_name))
|
||||
lines.append('%spublic:' % (' ' * (_INDENT // 2)))
|
||||
|
||||
# Add all the methods.
|
||||
_GenerateMethods(lines, source, class_node)
|
||||
# Add all the methods.
|
||||
_GenerateMethods(lines, source, class_node)
|
||||
|
||||
# Close the class.
|
||||
if lines:
|
||||
# If there are no virtual methods, no need for a public label.
|
||||
if len(lines) == 2:
|
||||
del lines[-1]
|
||||
# Close the class.
|
||||
if lines:
|
||||
# If there are no virtual methods, no need for a public label.
|
||||
if len(lines) == 2:
|
||||
del lines[-1]
|
||||
|
||||
# Only close the class if there really is a class.
|
||||
lines.append('};')
|
||||
lines.append('') # Add an extra newline.
|
||||
# Only close the class if there really is a class.
|
||||
lines.append('};')
|
||||
lines.append('') # Add an extra newline.
|
||||
|
||||
# Close the namespace.
|
||||
if class_node.namespace:
|
||||
for i in range(len(class_node.namespace) - 1, -1, -1):
|
||||
lines.append('} // namespace %s' % class_node.namespace[i])
|
||||
lines.append('') # Add an extra newline.
|
||||
# Close the namespace.
|
||||
if class_node.namespace:
|
||||
for i in range(len(class_node.namespace) - 1, -1, -1):
|
||||
lines.append('} // namespace %s' % class_node.namespace[i])
|
||||
lines.append('') # Add an extra newline.
|
||||
|
||||
if desired_class_names:
|
||||
missing_class_name_list = list(desired_class_names - processed_class_names)
|
||||
if missing_class_name_list:
|
||||
missing_class_name_list.sort()
|
||||
sys.stderr.write('Class(es) not found in %s: %s\n' %
|
||||
(filename, ', '.join(missing_class_name_list)))
|
||||
elif not processed_class_names:
|
||||
sys.stderr.write('No class found in %s\n' % filename)
|
||||
if desired_class_names:
|
||||
missing_class_name_list = list(desired_class_names - processed_class_names)
|
||||
if missing_class_name_list:
|
||||
missing_class_name_list.sort()
|
||||
sys.stderr.write('Class(es) not found in %s: %s\n' %
|
||||
(filename, ', '.join(missing_class_name_list)))
|
||||
elif not processed_class_names:
|
||||
sys.stderr.write('No class found in %s\n' % filename)
|
||||
|
||||
return lines
|
||||
return lines
|
||||
|
||||
|
||||
def main(argv=sys.argv):
|
||||
if len(argv) < 2:
|
||||
sys.stderr.write('Google Mock Class Generator v%s\n\n' %
|
||||
'.'.join(map(str, _VERSION)))
|
||||
sys.stderr.write(__doc__)
|
||||
return 1
|
||||
if len(argv) < 2:
|
||||
sys.stderr.write('Google Mock Class Generator v%s\n\n' %
|
||||
'.'.join(map(str, _VERSION)))
|
||||
sys.stderr.write(__doc__)
|
||||
return 1
|
||||
|
||||
global _INDENT
|
||||
try:
|
||||
_INDENT = int(os.environ['INDENT'])
|
||||
except KeyError:
|
||||
pass
|
||||
except:
|
||||
sys.stderr.write('Unable to use indent of %s\n' % os.environ.get('INDENT'))
|
||||
global _INDENT
|
||||
try:
|
||||
_INDENT = int(os.environ['INDENT'])
|
||||
except KeyError:
|
||||
pass
|
||||
except:
|
||||
sys.stderr.write('Unable to use indent of %s\n' % os.environ.get('INDENT'))
|
||||
|
||||
filename = argv[1]
|
||||
desired_class_names = None # None means all classes in the source file.
|
||||
if len(argv) >= 3:
|
||||
desired_class_names = set(argv[2:])
|
||||
source = utils.ReadFile(filename)
|
||||
if source is None:
|
||||
return 1
|
||||
filename = argv[1]
|
||||
desired_class_names = None # None means all classes in the source file.
|
||||
if len(argv) >= 3:
|
||||
desired_class_names = set(argv[2:])
|
||||
source = utils.ReadFile(filename)
|
||||
if source is None:
|
||||
return 1
|
||||
|
||||
builder = ast.BuilderFromSource(source, filename)
|
||||
try:
|
||||
entire_ast = filter(None, builder.Generate())
|
||||
except KeyboardInterrupt:
|
||||
return
|
||||
except:
|
||||
# An error message was already printed since we couldn't parse.
|
||||
sys.exit(1)
|
||||
else:
|
||||
lines = _GenerateMocks(filename, source, entire_ast, desired_class_names)
|
||||
sys.stdout.write('\n'.join(lines))
|
||||
builder = ast.BuilderFromSource(source, filename)
|
||||
try:
|
||||
entire_ast = filter(None, builder.Generate())
|
||||
except KeyboardInterrupt:
|
||||
return
|
||||
except:
|
||||
# An error message was already printed since we couldn't parse.
|
||||
sys.exit(1)
|
||||
else:
|
||||
lines = _GenerateMocks(filename, source, entire_ast, desired_class_names)
|
||||
sys.stdout.write('\n'.join(lines))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
||||
main(sys.argv)
|
||||
|
||||
@@ -29,43 +29,43 @@ from cpp import gmock_class
|
||||
|
||||
|
||||
class TestCase(unittest.TestCase):
|
||||
"""Helper class that adds assert methods."""
|
||||
"""Helper class that adds assert methods."""
|
||||
|
||||
@staticmethod
|
||||
def StripLeadingWhitespace(lines):
|
||||
"""Strip leading whitespace in each line in 'lines'."""
|
||||
return '\n'.join([s.lstrip() for s in lines.split('\n')])
|
||||
@staticmethod
|
||||
def StripLeadingWhitespace(lines):
|
||||
"""Strip leading whitespace in each line in 'lines'."""
|
||||
return '\n'.join([s.lstrip() for s in lines.split('\n')])
|
||||
|
||||
def assertEqualIgnoreLeadingWhitespace(self, expected_lines, lines):
|
||||
"""Specialized assert that ignores the indent level."""
|
||||
self.assertEqual(expected_lines, self.StripLeadingWhitespace(lines))
|
||||
def assertEqualIgnoreLeadingWhitespace(self, expected_lines, lines):
|
||||
"""Specialized assert that ignores the indent level."""
|
||||
self.assertEqual(expected_lines, self.StripLeadingWhitespace(lines))
|
||||
|
||||
|
||||
class GenerateMethodsTest(TestCase):
|
||||
|
||||
@staticmethod
|
||||
def GenerateMethodSource(cpp_source):
|
||||
"""Convert C++ source to Google Mock output source lines."""
|
||||
method_source_lines = []
|
||||
# <test> is a pseudo-filename, it is not read or written.
|
||||
builder = ast.BuilderFromSource(cpp_source, '<test>')
|
||||
ast_list = list(builder.Generate())
|
||||
gmock_class._GenerateMethods(method_source_lines, cpp_source, ast_list[0])
|
||||
return '\n'.join(method_source_lines)
|
||||
@staticmethod
|
||||
def GenerateMethodSource(cpp_source):
|
||||
"""Convert C++ source to Google Mock output source lines."""
|
||||
method_source_lines = []
|
||||
# <test> is a pseudo-filename, it is not read or written.
|
||||
builder = ast.BuilderFromSource(cpp_source, '<test>')
|
||||
ast_list = list(builder.Generate())
|
||||
gmock_class._GenerateMethods(method_source_lines, cpp_source, ast_list[0])
|
||||
return '\n'.join(method_source_lines)
|
||||
|
||||
def testSimpleMethod(self):
|
||||
source = """
|
||||
def testSimpleMethod(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual int Bar();
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD0(Bar,\nint());',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(int, Bar, (), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testSimpleConstructorsAndDestructor(self):
|
||||
source = """
|
||||
def testSimpleConstructorsAndDestructor(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
Foo();
|
||||
@@ -76,26 +76,26 @@ class Foo {
|
||||
virtual int Bar() = 0;
|
||||
};
|
||||
"""
|
||||
# The constructors and destructor should be ignored.
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD0(Bar,\nint());',
|
||||
self.GenerateMethodSource(source))
|
||||
# The constructors and destructor should be ignored.
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(int, Bar, (), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testVirtualDestructor(self):
|
||||
source = """
|
||||
def testVirtualDestructor(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual ~Foo();
|
||||
virtual int Bar() = 0;
|
||||
};
|
||||
"""
|
||||
# The destructor should be ignored.
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD0(Bar,\nint());',
|
||||
self.GenerateMethodSource(source))
|
||||
# The destructor should be ignored.
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(int, Bar, (), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testExplicitlyDefaultedConstructorsAndDestructor(self):
|
||||
source = """
|
||||
def testExplicitlyDefaultedConstructorsAndDestructor(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
Foo() = default;
|
||||
@@ -105,13 +105,13 @@ class Foo {
|
||||
virtual int Bar() = 0;
|
||||
};
|
||||
"""
|
||||
# The constructors and destructor should be ignored.
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD0(Bar,\nint());',
|
||||
self.GenerateMethodSource(source))
|
||||
# The constructors and destructor should be ignored.
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(int, Bar, (), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testExplicitlyDeletedConstructorsAndDestructor(self):
|
||||
source = """
|
||||
def testExplicitlyDeletedConstructorsAndDestructor(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
Foo() = delete;
|
||||
@@ -121,69 +121,69 @@ class Foo {
|
||||
virtual int Bar() = 0;
|
||||
};
|
||||
"""
|
||||
# The constructors and destructor should be ignored.
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD0(Bar,\nint());',
|
||||
self.GenerateMethodSource(source))
|
||||
# The constructors and destructor should be ignored.
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(int, Bar, (), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testSimpleOverrideMethod(self):
|
||||
source = """
|
||||
def testSimpleOverrideMethod(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
int Bar() override;
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD0(Bar,\nint());',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(int, Bar, (), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testSimpleConstMethod(self):
|
||||
source = """
|
||||
def testSimpleConstMethod(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual void Bar(bool flag) const;
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_CONST_METHOD1(Bar,\nvoid(bool flag));',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(void, Bar, (bool flag), (const, override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testExplicitVoid(self):
|
||||
source = """
|
||||
def testExplicitVoid(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual int Bar(void);
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD0(Bar,\nint(void));',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(int, Bar, (void), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testStrangeNewlineInParameter(self):
|
||||
source = """
|
||||
def testStrangeNewlineInParameter(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual void Bar(int
|
||||
a) = 0;
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD1(Bar,\nvoid(int a));',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(void, Bar, (int a), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testDefaultParameters(self):
|
||||
source = """
|
||||
def testDefaultParameters(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual void Bar(int a, char c = 'x') = 0;
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD2(Bar,\nvoid(int a, char c ));',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(void, Bar, (int a, char c), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testMultipleDefaultParameters(self):
|
||||
source = """
|
||||
def testMultipleDefaultParameters(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual void Bar(
|
||||
@@ -195,47 +195,58 @@ class Foo {
|
||||
int const *& rp = aDefaultPointer) = 0;
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
"MOCK_METHOD7(Bar,\n"
|
||||
"void(int a , char c , const int* const p , const std::string& s , char tab[] , int const *& rp ));",
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(void, Bar, '
|
||||
'(int a, char c, const int* const p, const std::string& s, char tab[], int const *& rp), '
|
||||
'(override));', self.GenerateMethodSource(source))
|
||||
|
||||
def testConstDefaultParameter(self):
|
||||
source = """
|
||||
def testMultipleSingleLineDefaultParameters(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual void Bar(int a = 42, int b = 43, int c = 44) = 0;
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(void, Bar, (int a, int b, int c), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testConstDefaultParameter(self):
|
||||
source = """
|
||||
class Test {
|
||||
public:
|
||||
virtual bool Bar(const int test_arg = 42) = 0;
|
||||
};
|
||||
"""
|
||||
expected = 'MOCK_METHOD1(Bar,\nbool(const int test_arg ));'
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(bool, Bar, (const int test_arg), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testConstRefDefaultParameter(self):
|
||||
source = """
|
||||
def testConstRefDefaultParameter(self):
|
||||
source = """
|
||||
class Test {
|
||||
public:
|
||||
virtual bool Bar(const std::string& test_arg = "42" ) = 0;
|
||||
};
|
||||
"""
|
||||
expected = 'MOCK_METHOD1(Bar,\nbool(const std::string& test_arg ));'
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(bool, Bar, (const std::string& test_arg), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testRemovesCommentsWhenDefaultsArePresent(self):
|
||||
source = """
|
||||
def testRemovesCommentsWhenDefaultsArePresent(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual void Bar(int a = 42 /* a comment */,
|
||||
char /* other comment */ c= 'x') = 0;
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD2(Bar,\nvoid(int a , char c));',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(void, Bar, (int a, char c), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testDoubleSlashCommentsInParameterListAreRemoved(self):
|
||||
source = """
|
||||
def testDoubleSlashCommentsInParameterListAreRemoved(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual void Bar(int a, // inline comments should be elided.
|
||||
@@ -243,117 +254,111 @@ class Foo {
|
||||
) const = 0;
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_CONST_METHOD2(Bar,\nvoid(int a, int b));',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(void, Bar, (int a, int b), (const, override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testCStyleCommentsInParameterListAreNotRemoved(self):
|
||||
# NOTE(nnorwitz): I'm not sure if it's the best behavior to keep these
|
||||
# comments. Also note that C style comments after the last parameter
|
||||
# are still elided.
|
||||
source = """
|
||||
def testCStyleCommentsInParameterListAreNotRemoved(self):
|
||||
# NOTE(nnorwitz): I'm not sure if it's the best behavior to keep these
|
||||
# comments. Also note that C style comments after the last parameter
|
||||
# are still elided.
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual const string& Bar(int /* keeper */, int b);
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD2(Bar,\nconst string&(int , int b));',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(const string&, Bar, (int, int b), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testArgsOfTemplateTypes(self):
|
||||
source = """
|
||||
def testArgsOfTemplateTypes(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual int Bar(const vector<int>& v, map<int, string>* output);
|
||||
};"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD2(Bar,\n'
|
||||
'int(const vector<int>& v, map<int, string>* output));',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(int, Bar, (const vector<int>& v, (map<int, string>* output)), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testReturnTypeWithOneTemplateArg(self):
|
||||
source = """
|
||||
def testReturnTypeWithOneTemplateArg(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual vector<int>* Bar(int n);
|
||||
};"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD1(Bar,\nvector<int>*(int n));',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(vector<int>*, Bar, (int n), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testReturnTypeWithManyTemplateArgs(self):
|
||||
source = """
|
||||
def testReturnTypeWithManyTemplateArgs(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual map<int, string> Bar();
|
||||
};"""
|
||||
# Comparing the comment text is brittle - we'll think of something
|
||||
# better in case this gets annoying, but for now let's keep it simple.
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'// The following line won\'t really compile, as the return\n'
|
||||
'// type has multiple template arguments. To fix it, use a\n'
|
||||
'// typedef for the return type.\n'
|
||||
'MOCK_METHOD0(Bar,\nmap<int, string>());',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD((map<int, string>), Bar, (), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testSimpleMethodInTemplatedClass(self):
|
||||
source = """
|
||||
def testSimpleMethodInTemplatedClass(self):
|
||||
source = """
|
||||
template<class T>
|
||||
class Foo {
|
||||
public:
|
||||
virtual int Bar();
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD0_T(Bar,\nint());',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(int, Bar, (), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testPointerArgWithoutNames(self):
|
||||
source = """
|
||||
def testPointerArgWithoutNames(self):
|
||||
source = """
|
||||
class Foo {
|
||||
virtual int Bar(C*);
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD1(Bar,\nint(C*));',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(int, Bar, (C*), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testReferenceArgWithoutNames(self):
|
||||
source = """
|
||||
def testReferenceArgWithoutNames(self):
|
||||
source = """
|
||||
class Foo {
|
||||
virtual int Bar(C&);
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD1(Bar,\nint(C&));',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(int, Bar, (C&), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testArrayArgWithoutNames(self):
|
||||
source = """
|
||||
def testArrayArgWithoutNames(self):
|
||||
source = """
|
||||
class Foo {
|
||||
virtual int Bar(C[]);
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD1(Bar,\nint(C[]));',
|
||||
self.GenerateMethodSource(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD(int, Bar, (C[]), (override));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
|
||||
class GenerateMocksTest(TestCase):
|
||||
|
||||
@staticmethod
|
||||
def GenerateMocks(cpp_source):
|
||||
"""Convert C++ source to complete Google Mock output source."""
|
||||
# <test> is a pseudo-filename, it is not read or written.
|
||||
filename = '<test>'
|
||||
builder = ast.BuilderFromSource(cpp_source, filename)
|
||||
ast_list = list(builder.Generate())
|
||||
lines = gmock_class._GenerateMocks(filename, cpp_source, ast_list, None)
|
||||
return '\n'.join(lines)
|
||||
@staticmethod
|
||||
def GenerateMocks(cpp_source):
|
||||
"""Convert C++ source to complete Google Mock output source."""
|
||||
# <test> is a pseudo-filename, it is not read or written.
|
||||
filename = '<test>'
|
||||
builder = ast.BuilderFromSource(cpp_source, filename)
|
||||
ast_list = list(builder.Generate())
|
||||
lines = gmock_class._GenerateMocks(filename, cpp_source, ast_list, None)
|
||||
return '\n'.join(lines)
|
||||
|
||||
def testNamespaces(self):
|
||||
source = """
|
||||
def testNamespaces(self):
|
||||
source = """
|
||||
namespace Foo {
|
||||
namespace Bar { class Forward; }
|
||||
namespace Baz {
|
||||
@@ -366,96 +371,91 @@ class Test {
|
||||
} // namespace Baz
|
||||
} // namespace Foo
|
||||
"""
|
||||
expected = """\
|
||||
expected = """\
|
||||
namespace Foo {
|
||||
namespace Baz {
|
||||
|
||||
class MockTest : public Test {
|
||||
public:
|
||||
MOCK_METHOD0(Foo,
|
||||
void());
|
||||
MOCK_METHOD(void, Foo, (), (override));
|
||||
};
|
||||
|
||||
} // namespace Baz
|
||||
} // namespace Foo
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMocks(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(expected,
|
||||
self.GenerateMocks(source))
|
||||
|
||||
def testClassWithStorageSpecifierMacro(self):
|
||||
source = """
|
||||
def testClassWithStorageSpecifierMacro(self):
|
||||
source = """
|
||||
class STORAGE_SPECIFIER Test {
|
||||
public:
|
||||
virtual void Foo();
|
||||
};
|
||||
"""
|
||||
expected = """\
|
||||
expected = """\
|
||||
class MockTest : public Test {
|
||||
public:
|
||||
MOCK_METHOD0(Foo,
|
||||
void());
|
||||
MOCK_METHOD(void, Foo, (), (override));
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMocks(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(expected,
|
||||
self.GenerateMocks(source))
|
||||
|
||||
def testTemplatedForwardDeclaration(self):
|
||||
source = """
|
||||
def testTemplatedForwardDeclaration(self):
|
||||
source = """
|
||||
template <class T> class Forward; // Forward declaration should be ignored.
|
||||
class Test {
|
||||
public:
|
||||
virtual void Foo();
|
||||
};
|
||||
"""
|
||||
expected = """\
|
||||
expected = """\
|
||||
class MockTest : public Test {
|
||||
public:
|
||||
MOCK_METHOD0(Foo,
|
||||
void());
|
||||
MOCK_METHOD(void, Foo, (), (override));
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMocks(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(expected,
|
||||
self.GenerateMocks(source))
|
||||
|
||||
def testTemplatedClass(self):
|
||||
source = """
|
||||
def testTemplatedClass(self):
|
||||
source = """
|
||||
template <typename S, typename T>
|
||||
class Test {
|
||||
public:
|
||||
virtual void Foo();
|
||||
};
|
||||
"""
|
||||
expected = """\
|
||||
expected = """\
|
||||
template <typename T0, typename T1>
|
||||
class MockTest : public Test<T0, T1> {
|
||||
public:
|
||||
MOCK_METHOD0_T(Foo,
|
||||
void());
|
||||
MOCK_METHOD(void, Foo, (), (override));
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMocks(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(expected,
|
||||
self.GenerateMocks(source))
|
||||
|
||||
def testTemplateInATemplateTypedef(self):
|
||||
source = """
|
||||
def testTemplateInATemplateTypedef(self):
|
||||
source = """
|
||||
class Test {
|
||||
public:
|
||||
typedef std::vector<std::list<int>> FooType;
|
||||
virtual void Bar(const FooType& test_arg);
|
||||
};
|
||||
"""
|
||||
expected = """\
|
||||
expected = """\
|
||||
class MockTest : public Test {
|
||||
public:
|
||||
MOCK_METHOD1(Bar,
|
||||
void(const FooType& test_arg));
|
||||
MOCK_METHOD(void, Bar, (const FooType& test_arg), (override));
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMocks(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(expected,
|
||||
self.GenerateMocks(source))
|
||||
|
||||
def testTemplateInATemplateTypedefWithComma(self):
|
||||
source = """
|
||||
def testTemplateInATemplateTypedefWithComma(self):
|
||||
source = """
|
||||
class Test {
|
||||
public:
|
||||
typedef std::function<void(
|
||||
@@ -463,18 +463,33 @@ class Test {
|
||||
virtual void Bar(const FooType& test_arg);
|
||||
};
|
||||
"""
|
||||
expected = """\
|
||||
expected = """\
|
||||
class MockTest : public Test {
|
||||
public:
|
||||
MOCK_METHOD1(Bar,
|
||||
void(const FooType& test_arg));
|
||||
MOCK_METHOD(void, Bar, (const FooType& test_arg), (override));
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMocks(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(expected,
|
||||
self.GenerateMocks(source))
|
||||
|
||||
def testEnumType(self):
|
||||
source = """
|
||||
def testParenthesizedCommaInArg(self):
|
||||
source = """
|
||||
class Test {
|
||||
public:
|
||||
virtual void Bar(std::function<void(int, int)> f);
|
||||
};
|
||||
"""
|
||||
expected = """\
|
||||
class MockTest : public Test {
|
||||
public:
|
||||
MOCK_METHOD(void, Bar, (std::function<void(int, int)> f), (override));
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(expected,
|
||||
self.GenerateMocks(source))
|
||||
|
||||
def testEnumType(self):
|
||||
source = """
|
||||
class Test {
|
||||
public:
|
||||
enum Bar {
|
||||
@@ -483,18 +498,17 @@ class Test {
|
||||
virtual void Foo();
|
||||
};
|
||||
"""
|
||||
expected = """\
|
||||
expected = """\
|
||||
class MockTest : public Test {
|
||||
public:
|
||||
MOCK_METHOD0(Foo,
|
||||
void());
|
||||
MOCK_METHOD(void, Foo, (), (override));
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMocks(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(expected,
|
||||
self.GenerateMocks(source))
|
||||
|
||||
def testEnumClassType(self):
|
||||
source = """
|
||||
def testEnumClassType(self):
|
||||
source = """
|
||||
class Test {
|
||||
public:
|
||||
enum class Bar {
|
||||
@@ -503,18 +517,17 @@ class Test {
|
||||
virtual void Foo();
|
||||
};
|
||||
"""
|
||||
expected = """\
|
||||
expected = """\
|
||||
class MockTest : public Test {
|
||||
public:
|
||||
MOCK_METHOD0(Foo,
|
||||
void());
|
||||
MOCK_METHOD(void, Foo, (), (override));
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMocks(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(expected,
|
||||
self.GenerateMocks(source))
|
||||
|
||||
def testStdFunction(self):
|
||||
source = """
|
||||
def testStdFunction(self):
|
||||
source = """
|
||||
class Test {
|
||||
public:
|
||||
Test(std::function<int(std::string)> foo) : foo_(foo) {}
|
||||
@@ -525,16 +538,15 @@ class Test {
|
||||
std::function<int(std::string)> foo_;
|
||||
};
|
||||
"""
|
||||
expected = """\
|
||||
expected = """\
|
||||
class MockTest : public Test {
|
||||
public:
|
||||
MOCK_METHOD0(foo,
|
||||
std::function<int (std::string)>());
|
||||
MOCK_METHOD(std::function<int (std::string)>, foo, (), (override));
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMocks(source))
|
||||
self.assertEqualIgnoreLeadingWhitespace(expected,
|
||||
self.GenerateMocks(source))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
unittest.main()
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
// utilities for defining matchers.
|
||||
|
||||
#include "gmock/gmock-matchers.h"
|
||||
#include "gmock/gmock-generated-matchers.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file tests the function mocker classes.
|
||||
#include "gmock/gmock-generated-function-mockers.h"
|
||||
#include "gmock/gmock-function-mocker.h"
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// MSDN says the header file to be included for STDMETHOD is BaseTyps.h but
|
||||
@@ -183,182 +183,238 @@ class MockFoo : public FooInterface {
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
|
||||
};
|
||||
|
||||
class LegacyMockFoo : public FooInterface {
|
||||
public:
|
||||
LegacyMockFoo() {}
|
||||
|
||||
// Makes sure that a mock function parameter can be named.
|
||||
MOCK_METHOD1(VoidReturning, void(int n)); // NOLINT
|
||||
|
||||
MOCK_METHOD0(Nullary, int()); // NOLINT
|
||||
|
||||
// Makes sure that a mock function parameter can be unnamed.
|
||||
MOCK_METHOD1(Unary, bool(int)); // NOLINT
|
||||
MOCK_METHOD2(Binary, long(short, int)); // NOLINT
|
||||
MOCK_METHOD10(Decimal, int(bool, char, short, int, long, float, // NOLINT
|
||||
double, unsigned, char*, const std::string& str));
|
||||
|
||||
MOCK_METHOD1(TakesNonConstReference, bool(int&)); // NOLINT
|
||||
MOCK_METHOD1(TakesConstReference, std::string(const int&));
|
||||
MOCK_METHOD1(TakesConst, bool(const int)); // NOLINT
|
||||
|
||||
// Tests that the function return type can contain unprotected comma.
|
||||
MOCK_METHOD0(ReturnTypeWithComma, std::map<int, std::string>());
|
||||
MOCK_CONST_METHOD1(ReturnTypeWithComma,
|
||||
std::map<int, std::string>(int)); // NOLINT
|
||||
|
||||
MOCK_METHOD0(OverloadedOnArgumentNumber, int()); // NOLINT
|
||||
MOCK_METHOD1(OverloadedOnArgumentNumber, int(int)); // NOLINT
|
||||
|
||||
MOCK_METHOD1(OverloadedOnArgumentType, int(int)); // NOLINT
|
||||
MOCK_METHOD1(OverloadedOnArgumentType, char(char)); // NOLINT
|
||||
|
||||
MOCK_METHOD0(OverloadedOnConstness, int()); // NOLINT
|
||||
MOCK_CONST_METHOD0(OverloadedOnConstness, char()); // NOLINT
|
||||
|
||||
MOCK_METHOD1(TypeWithHole, int(int (*)())); // NOLINT
|
||||
MOCK_METHOD1(TypeWithComma,
|
||||
int(const std::map<int, std::string>&)); // NOLINT
|
||||
MOCK_METHOD1(TypeWithTemplatedCopyCtor,
|
||||
int(const TemplatedCopyable<int>&)); // NOLINT
|
||||
|
||||
MOCK_METHOD1(ReturnsFunctionPointer1, int (*(int))(bool));
|
||||
MOCK_METHOD1(ReturnsFunctionPointer2, fn_ptr(int));
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTNullary, int());
|
||||
MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTUnary, bool(int)); // NOLINT
|
||||
MOCK_METHOD10_WITH_CALLTYPE(STDMETHODCALLTYPE, CTDecimal,
|
||||
int(bool b, char c, short d, int e, // NOLINT
|
||||
long f, float g, double h, // NOLINT
|
||||
unsigned i, char* j, const std::string& k));
|
||||
MOCK_CONST_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTConst,
|
||||
char(int)); // NOLINT
|
||||
|
||||
// Tests that the function return type can contain unprotected comma.
|
||||
MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTReturnTypeWithComma,
|
||||
std::map<int, std::string>());
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockFoo);
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
class MockMethodFunctionMockerTest : public testing::Test {
|
||||
template <class T>
|
||||
class FunctionMockerTest : public testing::Test {
|
||||
protected:
|
||||
MockMethodFunctionMockerTest() : foo_(&mock_foo_) {}
|
||||
FunctionMockerTest() : foo_(&mock_foo_) {}
|
||||
|
||||
FooInterface* const foo_;
|
||||
MockFoo mock_foo_;
|
||||
T mock_foo_;
|
||||
};
|
||||
using FunctionMockerTestTypes = ::testing::Types<MockFoo, LegacyMockFoo>;
|
||||
TYPED_TEST_SUITE(FunctionMockerTest, FunctionMockerTestTypes);
|
||||
|
||||
// Tests mocking a void-returning function.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksVoidFunction) {
|
||||
EXPECT_CALL(mock_foo_, VoidReturning(Lt(100)));
|
||||
foo_->VoidReturning(0);
|
||||
TYPED_TEST(FunctionMockerTest, MocksVoidFunction) {
|
||||
EXPECT_CALL(this->mock_foo_, VoidReturning(Lt(100)));
|
||||
this->foo_->VoidReturning(0);
|
||||
}
|
||||
|
||||
// Tests mocking a nullary function.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksNullaryFunction) {
|
||||
EXPECT_CALL(mock_foo_, Nullary())
|
||||
TYPED_TEST(FunctionMockerTest, MocksNullaryFunction) {
|
||||
EXPECT_CALL(this->mock_foo_, Nullary())
|
||||
.WillOnce(DoDefault())
|
||||
.WillOnce(Return(1));
|
||||
|
||||
EXPECT_EQ(0, foo_->Nullary());
|
||||
EXPECT_EQ(1, foo_->Nullary());
|
||||
EXPECT_EQ(0, this->foo_->Nullary());
|
||||
EXPECT_EQ(1, this->foo_->Nullary());
|
||||
}
|
||||
|
||||
// Tests mocking a unary function.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksUnaryFunction) {
|
||||
EXPECT_CALL(mock_foo_, Unary(Eq(2)))
|
||||
.Times(2)
|
||||
.WillOnce(Return(true));
|
||||
TYPED_TEST(FunctionMockerTest, MocksUnaryFunction) {
|
||||
EXPECT_CALL(this->mock_foo_, Unary(Eq(2))).Times(2).WillOnce(Return(true));
|
||||
|
||||
EXPECT_TRUE(foo_->Unary(2));
|
||||
EXPECT_FALSE(foo_->Unary(2));
|
||||
EXPECT_TRUE(this->foo_->Unary(2));
|
||||
EXPECT_FALSE(this->foo_->Unary(2));
|
||||
}
|
||||
|
||||
// Tests mocking a binary function.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksBinaryFunction) {
|
||||
EXPECT_CALL(mock_foo_, Binary(2, _))
|
||||
.WillOnce(Return(3));
|
||||
TYPED_TEST(FunctionMockerTest, MocksBinaryFunction) {
|
||||
EXPECT_CALL(this->mock_foo_, Binary(2, _)).WillOnce(Return(3));
|
||||
|
||||
EXPECT_EQ(3, foo_->Binary(2, 1));
|
||||
EXPECT_EQ(3, this->foo_->Binary(2, 1));
|
||||
}
|
||||
|
||||
// Tests mocking a decimal function.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksDecimalFunction) {
|
||||
EXPECT_CALL(mock_foo_, Decimal(true, 'a', 0, 0, 1L, A<float>(),
|
||||
Lt(100), 5U, NULL, "hi"))
|
||||
TYPED_TEST(FunctionMockerTest, MocksDecimalFunction) {
|
||||
EXPECT_CALL(this->mock_foo_,
|
||||
Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U, NULL, "hi"))
|
||||
.WillOnce(Return(5));
|
||||
|
||||
EXPECT_EQ(5, foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi"));
|
||||
EXPECT_EQ(5, this->foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi"));
|
||||
}
|
||||
|
||||
// Tests mocking a function that takes a non-const reference.
|
||||
TEST_F(MockMethodFunctionMockerTest,
|
||||
MocksFunctionWithNonConstReferenceArgument) {
|
||||
TYPED_TEST(FunctionMockerTest, MocksFunctionWithNonConstReferenceArgument) {
|
||||
int a = 0;
|
||||
EXPECT_CALL(mock_foo_, TakesNonConstReference(Ref(a)))
|
||||
EXPECT_CALL(this->mock_foo_, TakesNonConstReference(Ref(a)))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_TRUE(foo_->TakesNonConstReference(a));
|
||||
EXPECT_TRUE(this->foo_->TakesNonConstReference(a));
|
||||
}
|
||||
|
||||
// Tests mocking a function that takes a const reference.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksFunctionWithConstReferenceArgument) {
|
||||
TYPED_TEST(FunctionMockerTest, MocksFunctionWithConstReferenceArgument) {
|
||||
int a = 0;
|
||||
EXPECT_CALL(mock_foo_, TakesConstReference(Ref(a)))
|
||||
EXPECT_CALL(this->mock_foo_, TakesConstReference(Ref(a)))
|
||||
.WillOnce(Return("Hello"));
|
||||
|
||||
EXPECT_EQ("Hello", foo_->TakesConstReference(a));
|
||||
EXPECT_EQ("Hello", this->foo_->TakesConstReference(a));
|
||||
}
|
||||
|
||||
// Tests mocking a function that takes a const variable.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksFunctionWithConstArgument) {
|
||||
EXPECT_CALL(mock_foo_, TakesConst(Lt(10)))
|
||||
.WillOnce(DoDefault());
|
||||
TYPED_TEST(FunctionMockerTest, MocksFunctionWithConstArgument) {
|
||||
EXPECT_CALL(this->mock_foo_, TakesConst(Lt(10))).WillOnce(DoDefault());
|
||||
|
||||
EXPECT_FALSE(foo_->TakesConst(5));
|
||||
EXPECT_FALSE(this->foo_->TakesConst(5));
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the number of arguments.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksFunctionsOverloadedOnArgumentNumber) {
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentNumber())
|
||||
TYPED_TEST(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentNumber) {
|
||||
EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentNumber())
|
||||
.WillOnce(Return(1));
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentNumber(_))
|
||||
EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentNumber(_))
|
||||
.WillOnce(Return(2));
|
||||
|
||||
EXPECT_EQ(2, foo_->OverloadedOnArgumentNumber(1));
|
||||
EXPECT_EQ(1, foo_->OverloadedOnArgumentNumber());
|
||||
EXPECT_EQ(2, this->foo_->OverloadedOnArgumentNumber(1));
|
||||
EXPECT_EQ(1, this->foo_->OverloadedOnArgumentNumber());
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the types of argument.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksFunctionsOverloadedOnArgumentType) {
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentType(An<int>()))
|
||||
TYPED_TEST(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentType) {
|
||||
EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentType(An<int>()))
|
||||
.WillOnce(Return(1));
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentType(TypedEq<char>('a')))
|
||||
EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentType(TypedEq<char>('a')))
|
||||
.WillOnce(Return('b'));
|
||||
|
||||
EXPECT_EQ(1, foo_->OverloadedOnArgumentType(0));
|
||||
EXPECT_EQ('b', foo_->OverloadedOnArgumentType('a'));
|
||||
EXPECT_EQ(1, this->foo_->OverloadedOnArgumentType(0));
|
||||
EXPECT_EQ('b', this->foo_->OverloadedOnArgumentType('a'));
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the const-ness of this object.
|
||||
TEST_F(MockMethodFunctionMockerTest,
|
||||
MocksFunctionsOverloadedOnConstnessOfThis) {
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnConstness());
|
||||
EXPECT_CALL(Const(mock_foo_), OverloadedOnConstness())
|
||||
TYPED_TEST(FunctionMockerTest, MocksFunctionsOverloadedOnConstnessOfThis) {
|
||||
EXPECT_CALL(this->mock_foo_, OverloadedOnConstness());
|
||||
EXPECT_CALL(Const(this->mock_foo_), OverloadedOnConstness())
|
||||
.WillOnce(Return('a'));
|
||||
|
||||
EXPECT_EQ(0, foo_->OverloadedOnConstness());
|
||||
EXPECT_EQ('a', Const(*foo_).OverloadedOnConstness());
|
||||
EXPECT_EQ(0, this->foo_->OverloadedOnConstness());
|
||||
EXPECT_EQ('a', Const(*this->foo_).OverloadedOnConstness());
|
||||
}
|
||||
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksReturnTypeWithComma) {
|
||||
TYPED_TEST(FunctionMockerTest, MocksReturnTypeWithComma) {
|
||||
const std::map<int, std::string> a_map;
|
||||
EXPECT_CALL(mock_foo_, ReturnTypeWithComma())
|
||||
.WillOnce(Return(a_map));
|
||||
EXPECT_CALL(mock_foo_, ReturnTypeWithComma(42))
|
||||
.WillOnce(Return(a_map));
|
||||
EXPECT_CALL(this->mock_foo_, ReturnTypeWithComma()).WillOnce(Return(a_map));
|
||||
EXPECT_CALL(this->mock_foo_, ReturnTypeWithComma(42)).WillOnce(Return(a_map));
|
||||
|
||||
EXPECT_EQ(a_map, mock_foo_.ReturnTypeWithComma());
|
||||
EXPECT_EQ(a_map, mock_foo_.ReturnTypeWithComma(42));
|
||||
EXPECT_EQ(a_map, this->mock_foo_.ReturnTypeWithComma());
|
||||
EXPECT_EQ(a_map, this->mock_foo_.ReturnTypeWithComma(42));
|
||||
}
|
||||
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksTypeWithTemplatedCopyCtor) {
|
||||
EXPECT_CALL(mock_foo_, TypeWithTemplatedCopyCtor(_)).WillOnce(Return(true));
|
||||
EXPECT_TRUE(foo_->TypeWithTemplatedCopyCtor(TemplatedCopyable<int>()));
|
||||
TYPED_TEST(FunctionMockerTest, MocksTypeWithTemplatedCopyCtor) {
|
||||
EXPECT_CALL(this->mock_foo_, TypeWithTemplatedCopyCtor(_))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_TRUE(this->foo_->TypeWithTemplatedCopyCtor(TemplatedCopyable<int>()));
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// Tests mocking a nullary function with calltype.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksNullaryFunctionWithCallType) {
|
||||
EXPECT_CALL(mock_foo_, CTNullary())
|
||||
TYPED_TEST(FunctionMockerTest, MocksNullaryFunctionWithCallType) {
|
||||
EXPECT_CALL(this->mock_foo_, CTNullary())
|
||||
.WillOnce(Return(-1))
|
||||
.WillOnce(Return(0));
|
||||
|
||||
EXPECT_EQ(-1, foo_->CTNullary());
|
||||
EXPECT_EQ(0, foo_->CTNullary());
|
||||
EXPECT_EQ(-1, this->foo_->CTNullary());
|
||||
EXPECT_EQ(0, this->foo_->CTNullary());
|
||||
}
|
||||
|
||||
// Tests mocking a unary function with calltype.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksUnaryFunctionWithCallType) {
|
||||
EXPECT_CALL(mock_foo_, CTUnary(Eq(2)))
|
||||
TYPED_TEST(FunctionMockerTest, MocksUnaryFunctionWithCallType) {
|
||||
EXPECT_CALL(this->mock_foo_, CTUnary(Eq(2)))
|
||||
.Times(2)
|
||||
.WillOnce(Return(true))
|
||||
.WillOnce(Return(false));
|
||||
|
||||
EXPECT_TRUE(foo_->CTUnary(2));
|
||||
EXPECT_FALSE(foo_->CTUnary(2));
|
||||
EXPECT_TRUE(this->foo_->CTUnary(2));
|
||||
EXPECT_FALSE(this->foo_->CTUnary(2));
|
||||
}
|
||||
|
||||
// Tests mocking a decimal function with calltype.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksDecimalFunctionWithCallType) {
|
||||
EXPECT_CALL(mock_foo_, CTDecimal(true, 'a', 0, 0, 1L, A<float>(),
|
||||
Lt(100), 5U, NULL, "hi"))
|
||||
TYPED_TEST(FunctionMockerTest, MocksDecimalFunctionWithCallType) {
|
||||
EXPECT_CALL(this->mock_foo_, CTDecimal(true, 'a', 0, 0, 1L, A<float>(),
|
||||
Lt(100), 5U, NULL, "hi"))
|
||||
.WillOnce(Return(10));
|
||||
|
||||
EXPECT_EQ(10, foo_->CTDecimal(true, 'a', 0, 0, 1, 0, 0, 5, NULL, "hi"));
|
||||
EXPECT_EQ(10, this->foo_->CTDecimal(true, 'a', 0, 0, 1, 0, 0, 5, NULL, "hi"));
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the const-ness of this object.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksFunctionsConstFunctionWithCallType) {
|
||||
EXPECT_CALL(Const(mock_foo_), CTConst(_))
|
||||
.WillOnce(Return('a'));
|
||||
TYPED_TEST(FunctionMockerTest, MocksFunctionsConstFunctionWithCallType) {
|
||||
EXPECT_CALL(Const(this->mock_foo_), CTConst(_)).WillOnce(Return('a'));
|
||||
|
||||
EXPECT_EQ('a', Const(*foo_).CTConst(0));
|
||||
EXPECT_EQ('a', Const(*this->foo_).CTConst(0));
|
||||
}
|
||||
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksReturnTypeWithCommaAndCallType) {
|
||||
TYPED_TEST(FunctionMockerTest, MocksReturnTypeWithCommaAndCallType) {
|
||||
const std::map<int, std::string> a_map;
|
||||
EXPECT_CALL(mock_foo_, CTReturnTypeWithComma())
|
||||
.WillOnce(Return(a_map));
|
||||
EXPECT_CALL(this->mock_foo_, CTReturnTypeWithComma()).WillOnce(Return(a_map));
|
||||
|
||||
EXPECT_EQ(a_map, mock_foo_.CTReturnTypeWithComma());
|
||||
EXPECT_EQ(a_map, this->mock_foo_.CTReturnTypeWithComma());
|
||||
}
|
||||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
@@ -373,20 +429,33 @@ class MockB {
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockB);
|
||||
};
|
||||
|
||||
class LegacyMockB {
|
||||
public:
|
||||
LegacyMockB() {}
|
||||
|
||||
MOCK_METHOD0(DoB, void());
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockB);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ExpectCallTest : public ::testing::Test {};
|
||||
using ExpectCallTestTypes = ::testing::Types<MockB, LegacyMockB>;
|
||||
TYPED_TEST_SUITE(ExpectCallTest, ExpectCallTestTypes);
|
||||
|
||||
// Tests that functions with no EXPECT_CALL() rules can be called any
|
||||
// number of times.
|
||||
TEST(MockMethodExpectCallTest, UnmentionedFunctionCanBeCalledAnyNumberOfTimes) {
|
||||
{
|
||||
MockB b;
|
||||
}
|
||||
TYPED_TEST(ExpectCallTest, UnmentionedFunctionCanBeCalledAnyNumberOfTimes) {
|
||||
{ TypeParam b; }
|
||||
|
||||
{
|
||||
MockB b;
|
||||
TypeParam b;
|
||||
b.DoB();
|
||||
}
|
||||
|
||||
{
|
||||
MockB b;
|
||||
TypeParam b;
|
||||
b.DoB();
|
||||
b.DoB();
|
||||
}
|
||||
@@ -425,9 +494,33 @@ class MockStack : public StackInterface<T> {
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStack);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class LegacyMockStack : public StackInterface<T> {
|
||||
public:
|
||||
LegacyMockStack() {}
|
||||
|
||||
MOCK_METHOD1_T(Push, void(const T& elem));
|
||||
MOCK_METHOD0_T(Pop, void());
|
||||
MOCK_CONST_METHOD0_T(GetSize, int()); // NOLINT
|
||||
MOCK_CONST_METHOD0_T(GetTop, const T&());
|
||||
|
||||
// Tests that the function return type can contain unprotected comma.
|
||||
MOCK_METHOD0_T(ReturnTypeWithComma, std::map<int, int>());
|
||||
MOCK_CONST_METHOD1_T(ReturnTypeWithComma, std::map<int, int>(int)); // NOLINT
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockStack);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TemplateMockTest : public ::testing::Test {};
|
||||
using TemplateMockTestTypes =
|
||||
::testing::Types<MockStack<int>, LegacyMockStack<int>>;
|
||||
TYPED_TEST_SUITE(TemplateMockTest, TemplateMockTestTypes);
|
||||
|
||||
// Tests that template mock works.
|
||||
TEST(MockMethodTemplateMockTest, Works) {
|
||||
MockStack<int> mock;
|
||||
TYPED_TEST(TemplateMockTest, Works) {
|
||||
TypeParam mock;
|
||||
|
||||
EXPECT_CALL(mock, GetSize())
|
||||
.WillOnce(Return(0))
|
||||
@@ -448,8 +541,8 @@ TEST(MockMethodTemplateMockTest, Works) {
|
||||
EXPECT_EQ(0, mock.GetSize());
|
||||
}
|
||||
|
||||
TEST(MockMethodTemplateMockTest, MethodWithCommaInReturnTypeWorks) {
|
||||
MockStack<int> mock;
|
||||
TYPED_TEST(TemplateMockTest, MethodWithCommaInReturnTypeWorks) {
|
||||
TypeParam mock;
|
||||
|
||||
const std::map<int, int> a_map;
|
||||
EXPECT_CALL(mock, ReturnTypeWithComma())
|
||||
@@ -493,9 +586,31 @@ class MockStackWithCallType : public StackInterfaceWithCallType<T> {
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStackWithCallType);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class LegacyMockStackWithCallType : public StackInterfaceWithCallType<T> {
|
||||
public:
|
||||
LegacyMockStackWithCallType() {}
|
||||
|
||||
MOCK_METHOD1_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Push, void(const T& elem));
|
||||
MOCK_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Pop, void());
|
||||
MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetSize, int());
|
||||
MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTop, const T&());
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockStackWithCallType);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TemplateMockTestWithCallType : public ::testing::Test {};
|
||||
using TemplateMockTestWithCallTypeTypes =
|
||||
::testing::Types<MockStackWithCallType<int>,
|
||||
LegacyMockStackWithCallType<int>>;
|
||||
TYPED_TEST_SUITE(TemplateMockTestWithCallType,
|
||||
TemplateMockTestWithCallTypeTypes);
|
||||
|
||||
// Tests that template mock with calltype works.
|
||||
TEST(MockMethodTemplateMockTestWithCallType, Works) {
|
||||
MockStackWithCallType<int> mock;
|
||||
TYPED_TEST(TemplateMockTestWithCallType, Works) {
|
||||
TypeParam mock;
|
||||
|
||||
EXPECT_CALL(mock, GetSize())
|
||||
.WillOnce(Return(0))
|
||||
@@ -522,6 +637,11 @@ TEST(MockMethodTemplateMockTestWithCallType, Works) {
|
||||
MOCK_METHOD(int, Overloaded, (int), (const)); \
|
||||
MOCK_METHOD(bool, Overloaded, (bool f, int n))
|
||||
|
||||
#define LEGACY_MY_MOCK_METHODS1_ \
|
||||
MOCK_METHOD0(Overloaded, void()); \
|
||||
MOCK_CONST_METHOD1(Overloaded, int(int n)); \
|
||||
MOCK_METHOD2(Overloaded, bool(bool f, int n))
|
||||
|
||||
class MockOverloadedOnArgNumber {
|
||||
public:
|
||||
MockOverloadedOnArgNumber() {}
|
||||
@@ -532,8 +652,25 @@ class MockOverloadedOnArgNumber {
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockOverloadedOnArgNumber);
|
||||
};
|
||||
|
||||
TEST(MockMethodOverloadedMockMethodTest, CanOverloadOnArgNumberInMacroBody) {
|
||||
MockOverloadedOnArgNumber mock;
|
||||
class LegacyMockOverloadedOnArgNumber {
|
||||
public:
|
||||
LegacyMockOverloadedOnArgNumber() {}
|
||||
|
||||
LEGACY_MY_MOCK_METHODS1_;
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockOverloadedOnArgNumber);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class OverloadedMockMethodTest : public ::testing::Test {};
|
||||
using OverloadedMockMethodTestTypes =
|
||||
::testing::Types<MockOverloadedOnArgNumber,
|
||||
LegacyMockOverloadedOnArgNumber>;
|
||||
TYPED_TEST_SUITE(OverloadedMockMethodTest, OverloadedMockMethodTestTypes);
|
||||
|
||||
TYPED_TEST(OverloadedMockMethodTest, CanOverloadOnArgNumberInMacroBody) {
|
||||
TypeParam mock;
|
||||
EXPECT_CALL(mock, Overloaded());
|
||||
EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2));
|
||||
EXPECT_CALL(mock, Overloaded(true, 1)).WillOnce(Return(true));
|
||||
@@ -658,11 +795,35 @@ struct MockMethodSizes4 {
|
||||
MOCK_METHOD(void, func, (int, int, int, int));
|
||||
};
|
||||
|
||||
struct LegacyMockMethodSizes0 {
|
||||
MOCK_METHOD0(func, void());
|
||||
};
|
||||
struct LegacyMockMethodSizes1 {
|
||||
MOCK_METHOD1(func, void(int));
|
||||
};
|
||||
struct LegacyMockMethodSizes2 {
|
||||
MOCK_METHOD2(func, void(int, int));
|
||||
};
|
||||
struct LegacyMockMethodSizes3 {
|
||||
MOCK_METHOD3(func, void(int, int, int));
|
||||
};
|
||||
struct LegacyMockMethodSizes4 {
|
||||
MOCK_METHOD4(func, void(int, int, int, int));
|
||||
};
|
||||
|
||||
|
||||
TEST(MockMethodMockFunctionTest, MockMethodSizeOverhead) {
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes1));
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes2));
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes3));
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes4));
|
||||
|
||||
EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes1));
|
||||
EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes2));
|
||||
EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes3));
|
||||
EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes4));
|
||||
|
||||
EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(MockMethodSizes0));
|
||||
}
|
||||
|
||||
void hasTwoParams(int, int);
|
||||
|
||||
@@ -1,659 +0,0 @@
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file tests the function mocker classes.
|
||||
|
||||
#include "gmock/gmock-generated-function-mockers.h"
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// MSDN says the header file to be included for STDMETHOD is BaseTyps.h but
|
||||
// we are getting compiler errors if we use basetyps.h, hence including
|
||||
// objbase.h for definition of STDMETHOD.
|
||||
# include <objbase.h>
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace testing {
|
||||
namespace gmock_generated_function_mockers_test {
|
||||
|
||||
using testing::_;
|
||||
using testing::A;
|
||||
using testing::An;
|
||||
using testing::AnyNumber;
|
||||
using testing::Const;
|
||||
using testing::DoDefault;
|
||||
using testing::Eq;
|
||||
using testing::Lt;
|
||||
using testing::MockFunction;
|
||||
using testing::Ref;
|
||||
using testing::Return;
|
||||
using testing::ReturnRef;
|
||||
using testing::TypedEq;
|
||||
|
||||
template<typename T>
|
||||
class TemplatedCopyable {
|
||||
public:
|
||||
TemplatedCopyable() {}
|
||||
|
||||
template <typename U>
|
||||
TemplatedCopyable(const U& other) {} // NOLINT
|
||||
};
|
||||
|
||||
class FooInterface {
|
||||
public:
|
||||
virtual ~FooInterface() {}
|
||||
|
||||
virtual void VoidReturning(int x) = 0;
|
||||
|
||||
virtual int Nullary() = 0;
|
||||
virtual bool Unary(int x) = 0;
|
||||
virtual long Binary(short x, int y) = 0; // NOLINT
|
||||
virtual int Decimal(bool b, char c, short d, int e, long f, // NOLINT
|
||||
float g, double h, unsigned i, char* j,
|
||||
const std::string& k) = 0;
|
||||
|
||||
virtual bool TakesNonConstReference(int& n) = 0; // NOLINT
|
||||
virtual std::string TakesConstReference(const int& n) = 0;
|
||||
virtual bool TakesConst(const int x) = 0;
|
||||
|
||||
virtual int OverloadedOnArgumentNumber() = 0;
|
||||
virtual int OverloadedOnArgumentNumber(int n) = 0;
|
||||
|
||||
virtual int OverloadedOnArgumentType(int n) = 0;
|
||||
virtual char OverloadedOnArgumentType(char c) = 0;
|
||||
|
||||
virtual int OverloadedOnConstness() = 0;
|
||||
virtual char OverloadedOnConstness() const = 0;
|
||||
|
||||
virtual int TypeWithHole(int (*func)()) = 0;
|
||||
virtual int TypeWithComma(const std::map<int, std::string>& a_map) = 0;
|
||||
virtual int TypeWithTemplatedCopyCtor(
|
||||
const TemplatedCopyable<int>& a_vector) = 0;
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
STDMETHOD_(int, CTNullary)() = 0;
|
||||
STDMETHOD_(bool, CTUnary)(int x) = 0;
|
||||
STDMETHOD_(int, CTDecimal)
|
||||
(bool b, char c, short d, int e, long f, // NOLINT
|
||||
float g, double h, unsigned i, char* j, const std::string& k) = 0;
|
||||
STDMETHOD_(char, CTConst)(int x) const = 0;
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
};
|
||||
|
||||
// Const qualifiers on arguments were once (incorrectly) considered
|
||||
// significant in determining whether two virtual functions had the same
|
||||
// signature. This was fixed in Visual Studio 2008. However, the compiler
|
||||
// still emits a warning that alerts about this change in behavior.
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4373)
|
||||
#endif
|
||||
class MockFoo : public FooInterface {
|
||||
public:
|
||||
MockFoo() {}
|
||||
|
||||
// Makes sure that a mock function parameter can be named.
|
||||
MOCK_METHOD1(VoidReturning, void(int n)); // NOLINT
|
||||
|
||||
MOCK_METHOD0(Nullary, int()); // NOLINT
|
||||
|
||||
// Makes sure that a mock function parameter can be unnamed.
|
||||
MOCK_METHOD1(Unary, bool(int)); // NOLINT
|
||||
MOCK_METHOD2(Binary, long(short, int)); // NOLINT
|
||||
MOCK_METHOD10(Decimal, int(bool, char, short, int, long, float, // NOLINT
|
||||
double, unsigned, char*, const std::string& str));
|
||||
|
||||
MOCK_METHOD1(TakesNonConstReference, bool(int&)); // NOLINT
|
||||
MOCK_METHOD1(TakesConstReference, std::string(const int&));
|
||||
MOCK_METHOD1(TakesConst, bool(const int)); // NOLINT
|
||||
|
||||
// Tests that the function return type can contain unprotected comma.
|
||||
MOCK_METHOD0(ReturnTypeWithComma, std::map<int, std::string>());
|
||||
MOCK_CONST_METHOD1(ReturnTypeWithComma,
|
||||
std::map<int, std::string>(int)); // NOLINT
|
||||
|
||||
MOCK_METHOD0(OverloadedOnArgumentNumber, int()); // NOLINT
|
||||
MOCK_METHOD1(OverloadedOnArgumentNumber, int(int)); // NOLINT
|
||||
|
||||
MOCK_METHOD1(OverloadedOnArgumentType, int(int)); // NOLINT
|
||||
MOCK_METHOD1(OverloadedOnArgumentType, char(char)); // NOLINT
|
||||
|
||||
MOCK_METHOD0(OverloadedOnConstness, int()); // NOLINT
|
||||
MOCK_CONST_METHOD0(OverloadedOnConstness, char()); // NOLINT
|
||||
|
||||
MOCK_METHOD1(TypeWithHole, int(int (*)())); // NOLINT
|
||||
MOCK_METHOD1(TypeWithComma,
|
||||
int(const std::map<int, std::string>&)); // NOLINT
|
||||
MOCK_METHOD1(TypeWithTemplatedCopyCtor,
|
||||
int(const TemplatedCopyable<int>&)); // NOLINT
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTNullary, int());
|
||||
MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTUnary, bool(int));
|
||||
MOCK_METHOD10_WITH_CALLTYPE(STDMETHODCALLTYPE, CTDecimal,
|
||||
int(bool b, char c, short d, int e, long f,
|
||||
float g, double h, unsigned i, char* j,
|
||||
const std::string& k));
|
||||
MOCK_CONST_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTConst, char(int));
|
||||
|
||||
// Tests that the function return type can contain unprotected comma.
|
||||
MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTReturnTypeWithComma,
|
||||
std::map<int, std::string>());
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
|
||||
};
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
class FunctionMockerTest : public testing::Test {
|
||||
protected:
|
||||
FunctionMockerTest() : foo_(&mock_foo_) {}
|
||||
|
||||
FooInterface* const foo_;
|
||||
MockFoo mock_foo_;
|
||||
};
|
||||
|
||||
// Tests mocking a void-returning function.
|
||||
TEST_F(FunctionMockerTest, MocksVoidFunction) {
|
||||
EXPECT_CALL(mock_foo_, VoidReturning(Lt(100)));
|
||||
foo_->VoidReturning(0);
|
||||
}
|
||||
|
||||
// Tests mocking a nullary function.
|
||||
TEST_F(FunctionMockerTest, MocksNullaryFunction) {
|
||||
EXPECT_CALL(mock_foo_, Nullary())
|
||||
.WillOnce(DoDefault())
|
||||
.WillOnce(Return(1));
|
||||
|
||||
EXPECT_EQ(0, foo_->Nullary());
|
||||
EXPECT_EQ(1, foo_->Nullary());
|
||||
}
|
||||
|
||||
// Tests mocking a unary function.
|
||||
TEST_F(FunctionMockerTest, MocksUnaryFunction) {
|
||||
EXPECT_CALL(mock_foo_, Unary(Eq(2)))
|
||||
.Times(2)
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_TRUE(foo_->Unary(2));
|
||||
EXPECT_FALSE(foo_->Unary(2));
|
||||
}
|
||||
|
||||
// Tests mocking a binary function.
|
||||
TEST_F(FunctionMockerTest, MocksBinaryFunction) {
|
||||
EXPECT_CALL(mock_foo_, Binary(2, _))
|
||||
.WillOnce(Return(3));
|
||||
|
||||
EXPECT_EQ(3, foo_->Binary(2, 1));
|
||||
}
|
||||
|
||||
// Tests mocking a decimal function.
|
||||
TEST_F(FunctionMockerTest, MocksDecimalFunction) {
|
||||
EXPECT_CALL(mock_foo_, Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U,
|
||||
nullptr, "hi"))
|
||||
.WillOnce(Return(5));
|
||||
|
||||
EXPECT_EQ(5, foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi"));
|
||||
}
|
||||
|
||||
// Tests mocking a function that takes a non-const reference.
|
||||
TEST_F(FunctionMockerTest, MocksFunctionWithNonConstReferenceArgument) {
|
||||
int a = 0;
|
||||
EXPECT_CALL(mock_foo_, TakesNonConstReference(Ref(a)))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_TRUE(foo_->TakesNonConstReference(a));
|
||||
}
|
||||
|
||||
// Tests mocking a function that takes a const reference.
|
||||
TEST_F(FunctionMockerTest, MocksFunctionWithConstReferenceArgument) {
|
||||
int a = 0;
|
||||
EXPECT_CALL(mock_foo_, TakesConstReference(Ref(a)))
|
||||
.WillOnce(Return("Hello"));
|
||||
|
||||
EXPECT_EQ("Hello", foo_->TakesConstReference(a));
|
||||
}
|
||||
|
||||
// Tests mocking a function that takes a const variable.
|
||||
TEST_F(FunctionMockerTest, MocksFunctionWithConstArgument) {
|
||||
EXPECT_CALL(mock_foo_, TakesConst(Lt(10)))
|
||||
.WillOnce(DoDefault());
|
||||
|
||||
EXPECT_FALSE(foo_->TakesConst(5));
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the number of arguments.
|
||||
TEST_F(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentNumber) {
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentNumber())
|
||||
.WillOnce(Return(1));
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentNumber(_))
|
||||
.WillOnce(Return(2));
|
||||
|
||||
EXPECT_EQ(2, foo_->OverloadedOnArgumentNumber(1));
|
||||
EXPECT_EQ(1, foo_->OverloadedOnArgumentNumber());
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the types of argument.
|
||||
TEST_F(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentType) {
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentType(An<int>()))
|
||||
.WillOnce(Return(1));
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentType(TypedEq<char>('a')))
|
||||
.WillOnce(Return('b'));
|
||||
|
||||
EXPECT_EQ(1, foo_->OverloadedOnArgumentType(0));
|
||||
EXPECT_EQ('b', foo_->OverloadedOnArgumentType('a'));
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the const-ness of this object.
|
||||
TEST_F(FunctionMockerTest, MocksFunctionsOverloadedOnConstnessOfThis) {
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnConstness());
|
||||
EXPECT_CALL(Const(mock_foo_), OverloadedOnConstness())
|
||||
.WillOnce(Return('a'));
|
||||
|
||||
EXPECT_EQ(0, foo_->OverloadedOnConstness());
|
||||
EXPECT_EQ('a', Const(*foo_).OverloadedOnConstness());
|
||||
}
|
||||
|
||||
TEST_F(FunctionMockerTest, MocksReturnTypeWithComma) {
|
||||
const std::map<int, std::string> a_map;
|
||||
EXPECT_CALL(mock_foo_, ReturnTypeWithComma())
|
||||
.WillOnce(Return(a_map));
|
||||
EXPECT_CALL(mock_foo_, ReturnTypeWithComma(42))
|
||||
.WillOnce(Return(a_map));
|
||||
|
||||
EXPECT_EQ(a_map, mock_foo_.ReturnTypeWithComma());
|
||||
EXPECT_EQ(a_map, mock_foo_.ReturnTypeWithComma(42));
|
||||
}
|
||||
|
||||
TEST_F(FunctionMockerTest, MocksTypeWithTemplatedCopyCtor) {
|
||||
EXPECT_CALL(mock_foo_, TypeWithTemplatedCopyCtor(_)).WillOnce(Return(true));
|
||||
EXPECT_TRUE(foo_->TypeWithTemplatedCopyCtor(TemplatedCopyable<int>()));
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// Tests mocking a nullary function with calltype.
|
||||
TEST_F(FunctionMockerTest, MocksNullaryFunctionWithCallType) {
|
||||
EXPECT_CALL(mock_foo_, CTNullary())
|
||||
.WillOnce(Return(-1))
|
||||
.WillOnce(Return(0));
|
||||
|
||||
EXPECT_EQ(-1, foo_->CTNullary());
|
||||
EXPECT_EQ(0, foo_->CTNullary());
|
||||
}
|
||||
|
||||
// Tests mocking a unary function with calltype.
|
||||
TEST_F(FunctionMockerTest, MocksUnaryFunctionWithCallType) {
|
||||
EXPECT_CALL(mock_foo_, CTUnary(Eq(2)))
|
||||
.Times(2)
|
||||
.WillOnce(Return(true))
|
||||
.WillOnce(Return(false));
|
||||
|
||||
EXPECT_TRUE(foo_->CTUnary(2));
|
||||
EXPECT_FALSE(foo_->CTUnary(2));
|
||||
}
|
||||
|
||||
// Tests mocking a decimal function with calltype.
|
||||
TEST_F(FunctionMockerTest, MocksDecimalFunctionWithCallType) {
|
||||
EXPECT_CALL(mock_foo_, CTDecimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U,
|
||||
nullptr, "hi"))
|
||||
.WillOnce(Return(10));
|
||||
|
||||
EXPECT_EQ(10, foo_->CTDecimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi"));
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the const-ness of this object.
|
||||
TEST_F(FunctionMockerTest, MocksFunctionsConstFunctionWithCallType) {
|
||||
EXPECT_CALL(Const(mock_foo_), CTConst(_))
|
||||
.WillOnce(Return('a'));
|
||||
|
||||
EXPECT_EQ('a', Const(*foo_).CTConst(0));
|
||||
}
|
||||
|
||||
TEST_F(FunctionMockerTest, MocksReturnTypeWithCommaAndCallType) {
|
||||
const std::map<int, std::string> a_map;
|
||||
EXPECT_CALL(mock_foo_, CTReturnTypeWithComma())
|
||||
.WillOnce(Return(a_map));
|
||||
|
||||
EXPECT_EQ(a_map, mock_foo_.CTReturnTypeWithComma());
|
||||
}
|
||||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
class MockB {
|
||||
public:
|
||||
MockB() {}
|
||||
|
||||
MOCK_METHOD0(DoB, void());
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockB);
|
||||
};
|
||||
|
||||
// Tests that functions with no EXPECT_CALL() ruls can be called any
|
||||
// number of times.
|
||||
TEST(ExpectCallTest, UnmentionedFunctionCanBeCalledAnyNumberOfTimes) {
|
||||
{
|
||||
MockB b;
|
||||
}
|
||||
|
||||
{
|
||||
MockB b;
|
||||
b.DoB();
|
||||
}
|
||||
|
||||
{
|
||||
MockB b;
|
||||
b.DoB();
|
||||
b.DoB();
|
||||
}
|
||||
}
|
||||
|
||||
// Tests mocking template interfaces.
|
||||
|
||||
template <typename T>
|
||||
class StackInterface {
|
||||
public:
|
||||
virtual ~StackInterface() {}
|
||||
|
||||
// Template parameter appears in function parameter.
|
||||
virtual void Push(const T& value) = 0;
|
||||
virtual void Pop() = 0;
|
||||
virtual int GetSize() const = 0;
|
||||
// Template parameter appears in function return type.
|
||||
virtual const T& GetTop() const = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class MockStack : public StackInterface<T> {
|
||||
public:
|
||||
MockStack() {}
|
||||
|
||||
MOCK_METHOD1_T(Push, void(const T& elem));
|
||||
MOCK_METHOD0_T(Pop, void());
|
||||
MOCK_CONST_METHOD0_T(GetSize, int()); // NOLINT
|
||||
MOCK_CONST_METHOD0_T(GetTop, const T&());
|
||||
|
||||
// Tests that the function return type can contain unprotected comma.
|
||||
MOCK_METHOD0_T(ReturnTypeWithComma, std::map<int, int>());
|
||||
MOCK_CONST_METHOD1_T(ReturnTypeWithComma, std::map<int, int>(int)); // NOLINT
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStack);
|
||||
};
|
||||
|
||||
// Tests that template mock works.
|
||||
TEST(TemplateMockTest, Works) {
|
||||
MockStack<int> mock;
|
||||
|
||||
EXPECT_CALL(mock, GetSize())
|
||||
.WillOnce(Return(0))
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(0));
|
||||
EXPECT_CALL(mock, Push(_));
|
||||
int n = 5;
|
||||
EXPECT_CALL(mock, GetTop())
|
||||
.WillOnce(ReturnRef(n));
|
||||
EXPECT_CALL(mock, Pop())
|
||||
.Times(AnyNumber());
|
||||
|
||||
EXPECT_EQ(0, mock.GetSize());
|
||||
mock.Push(5);
|
||||
EXPECT_EQ(1, mock.GetSize());
|
||||
EXPECT_EQ(5, mock.GetTop());
|
||||
mock.Pop();
|
||||
EXPECT_EQ(0, mock.GetSize());
|
||||
}
|
||||
|
||||
TEST(TemplateMockTest, MethodWithCommaInReturnTypeWorks) {
|
||||
MockStack<int> mock;
|
||||
|
||||
const std::map<int, int> a_map;
|
||||
EXPECT_CALL(mock, ReturnTypeWithComma())
|
||||
.WillOnce(Return(a_map));
|
||||
EXPECT_CALL(mock, ReturnTypeWithComma(1))
|
||||
.WillOnce(Return(a_map));
|
||||
|
||||
EXPECT_EQ(a_map, mock.ReturnTypeWithComma());
|
||||
EXPECT_EQ(a_map, mock.ReturnTypeWithComma(1));
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// Tests mocking template interfaces with calltype.
|
||||
|
||||
template <typename T>
|
||||
class StackInterfaceWithCallType {
|
||||
public:
|
||||
virtual ~StackInterfaceWithCallType() {}
|
||||
|
||||
// Template parameter appears in function parameter.
|
||||
STDMETHOD_(void, Push)(const T& value) = 0;
|
||||
STDMETHOD_(void, Pop)() = 0;
|
||||
STDMETHOD_(int, GetSize)() const = 0;
|
||||
// Template parameter appears in function return type.
|
||||
STDMETHOD_(const T&, GetTop)() const = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class MockStackWithCallType : public StackInterfaceWithCallType<T> {
|
||||
public:
|
||||
MockStackWithCallType() {}
|
||||
|
||||
MOCK_METHOD1_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Push, void(const T& elem));
|
||||
MOCK_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Pop, void());
|
||||
MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetSize, int());
|
||||
MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTop, const T&());
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStackWithCallType);
|
||||
};
|
||||
|
||||
// Tests that template mock with calltype works.
|
||||
TEST(TemplateMockTestWithCallType, Works) {
|
||||
MockStackWithCallType<int> mock;
|
||||
|
||||
EXPECT_CALL(mock, GetSize())
|
||||
.WillOnce(Return(0))
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(0));
|
||||
EXPECT_CALL(mock, Push(_));
|
||||
int n = 5;
|
||||
EXPECT_CALL(mock, GetTop())
|
||||
.WillOnce(ReturnRef(n));
|
||||
EXPECT_CALL(mock, Pop())
|
||||
.Times(AnyNumber());
|
||||
|
||||
EXPECT_EQ(0, mock.GetSize());
|
||||
mock.Push(5);
|
||||
EXPECT_EQ(1, mock.GetSize());
|
||||
EXPECT_EQ(5, mock.GetTop());
|
||||
mock.Pop();
|
||||
EXPECT_EQ(0, mock.GetSize());
|
||||
}
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
#define MY_MOCK_METHODS1_ \
|
||||
MOCK_METHOD0(Overloaded, void()); \
|
||||
MOCK_CONST_METHOD1(Overloaded, int(int n)); \
|
||||
MOCK_METHOD2(Overloaded, bool(bool f, int n))
|
||||
|
||||
class MockOverloadedOnArgNumber {
|
||||
public:
|
||||
MockOverloadedOnArgNumber() {}
|
||||
|
||||
MY_MOCK_METHODS1_;
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockOverloadedOnArgNumber);
|
||||
};
|
||||
|
||||
TEST(OverloadedMockMethodTest, CanOverloadOnArgNumberInMacroBody) {
|
||||
MockOverloadedOnArgNumber mock;
|
||||
EXPECT_CALL(mock, Overloaded());
|
||||
EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2));
|
||||
EXPECT_CALL(mock, Overloaded(true, 1)).WillOnce(Return(true));
|
||||
|
||||
mock.Overloaded();
|
||||
EXPECT_EQ(2, mock.Overloaded(1));
|
||||
EXPECT_TRUE(mock.Overloaded(true, 1));
|
||||
}
|
||||
|
||||
#define MY_MOCK_METHODS2_ \
|
||||
MOCK_CONST_METHOD1(Overloaded, int(int n)); \
|
||||
MOCK_METHOD1(Overloaded, int(int n))
|
||||
|
||||
class MockOverloadedOnConstness {
|
||||
public:
|
||||
MockOverloadedOnConstness() {}
|
||||
|
||||
MY_MOCK_METHODS2_;
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockOverloadedOnConstness);
|
||||
};
|
||||
|
||||
TEST(OverloadedMockMethodTest, CanOverloadOnConstnessInMacroBody) {
|
||||
MockOverloadedOnConstness mock;
|
||||
const MockOverloadedOnConstness* const_mock = &mock;
|
||||
EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2));
|
||||
EXPECT_CALL(*const_mock, Overloaded(1)).WillOnce(Return(3));
|
||||
|
||||
EXPECT_EQ(2, mock.Overloaded(1));
|
||||
EXPECT_EQ(3, const_mock->Overloaded(1));
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, WorksForVoidNullary) {
|
||||
MockFunction<void()> foo;
|
||||
EXPECT_CALL(foo, Call());
|
||||
foo.Call();
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, WorksForNonVoidNullary) {
|
||||
MockFunction<int()> foo;
|
||||
EXPECT_CALL(foo, Call())
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(2));
|
||||
EXPECT_EQ(1, foo.Call());
|
||||
EXPECT_EQ(2, foo.Call());
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, WorksForVoidUnary) {
|
||||
MockFunction<void(int)> foo;
|
||||
EXPECT_CALL(foo, Call(1));
|
||||
foo.Call(1);
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, WorksForNonVoidBinary) {
|
||||
MockFunction<int(bool, int)> foo;
|
||||
EXPECT_CALL(foo, Call(false, 42))
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(2));
|
||||
EXPECT_CALL(foo, Call(true, Ge(100)))
|
||||
.WillOnce(Return(3));
|
||||
EXPECT_EQ(1, foo.Call(false, 42));
|
||||
EXPECT_EQ(2, foo.Call(false, 42));
|
||||
EXPECT_EQ(3, foo.Call(true, 120));
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, WorksFor10Arguments) {
|
||||
MockFunction<int(bool a0, char a1, int a2, int a3, int a4,
|
||||
int a5, int a6, char a7, int a8, bool a9)> foo;
|
||||
EXPECT_CALL(foo, Call(_, 'a', _, _, _, _, _, _, _, _))
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(2));
|
||||
EXPECT_EQ(1, foo.Call(false, 'a', 0, 0, 0, 0, 0, 'b', 0, true));
|
||||
EXPECT_EQ(2, foo.Call(true, 'a', 0, 0, 0, 0, 0, 'b', 1, false));
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, AsStdFunction) {
|
||||
MockFunction<int(int)> foo;
|
||||
auto call = [](const std::function<int(int)> &f, int i) {
|
||||
return f(i);
|
||||
};
|
||||
EXPECT_CALL(foo, Call(1)).WillOnce(Return(-1));
|
||||
EXPECT_CALL(foo, Call(2)).WillOnce(Return(-2));
|
||||
EXPECT_EQ(-1, call(foo.AsStdFunction(), 1));
|
||||
EXPECT_EQ(-2, call(foo.AsStdFunction(), 2));
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, AsStdFunctionReturnsReference) {
|
||||
MockFunction<int&()> foo;
|
||||
int value = 1;
|
||||
EXPECT_CALL(foo, Call()).WillOnce(ReturnRef(value));
|
||||
int& ref = foo.AsStdFunction()();
|
||||
EXPECT_EQ(1, ref);
|
||||
value = 2;
|
||||
EXPECT_EQ(2, ref);
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, AsStdFunctionWithReferenceParameter) {
|
||||
MockFunction<int(int &)> foo;
|
||||
auto call = [](const std::function<int(int& )> &f, int &i) {
|
||||
return f(i);
|
||||
};
|
||||
int i = 42;
|
||||
EXPECT_CALL(foo, Call(i)).WillOnce(Return(-1));
|
||||
EXPECT_EQ(-1, call(foo.AsStdFunction(), i));
|
||||
}
|
||||
|
||||
|
||||
struct MockMethodSizes0 {
|
||||
MOCK_METHOD0(func, void());
|
||||
};
|
||||
struct MockMethodSizes1 {
|
||||
MOCK_METHOD1(func, void(int));
|
||||
};
|
||||
struct MockMethodSizes2 {
|
||||
MOCK_METHOD2(func, void(int, int));
|
||||
};
|
||||
struct MockMethodSizes3 {
|
||||
MOCK_METHOD3(func, void(int, int, int));
|
||||
};
|
||||
struct MockMethodSizes4 {
|
||||
MOCK_METHOD4(func, void(int, int, int, int));
|
||||
};
|
||||
|
||||
TEST(MockFunctionTest, MockMethodSizeOverhead) {
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes1));
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes2));
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes3));
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes4));
|
||||
}
|
||||
|
||||
} // namespace gmock_generated_function_mockers_test
|
||||
} // namespace testing
|
||||
@@ -39,7 +39,7 @@
|
||||
# pragma warning(disable:4100)
|
||||
#endif
|
||||
|
||||
#include "gmock/gmock-generated-matchers.h"
|
||||
#include "gmock/gmock-matchers.h"
|
||||
|
||||
#include <array>
|
||||
#include <iterator>
|
||||
@@ -764,9 +764,16 @@ MATCHER_P2(ReferencesAnyOf, variable1, variable2, "") {
|
||||
|
||||
TEST(MatcherPnMacroTest, WorksWhenExplicitlyInstantiatedWithReferences) {
|
||||
UncopyableFoo foo1('1'), foo2('2'), foo3('3');
|
||||
const Matcher<const UncopyableFoo&> m =
|
||||
const Matcher<const UncopyableFoo&> const_m =
|
||||
ReferencesAnyOf<const UncopyableFoo&, const UncopyableFoo&>(foo1, foo2);
|
||||
|
||||
EXPECT_TRUE(const_m.Matches(foo1));
|
||||
EXPECT_TRUE(const_m.Matches(foo2));
|
||||
EXPECT_FALSE(const_m.Matches(foo3));
|
||||
|
||||
const Matcher<UncopyableFoo&> m =
|
||||
ReferencesAnyOf<UncopyableFoo&, UncopyableFoo&>(foo1, foo2);
|
||||
|
||||
EXPECT_TRUE(m.Matches(foo1));
|
||||
EXPECT_TRUE(m.Matches(foo2));
|
||||
EXPECT_FALSE(m.Matches(foo3));
|
||||
|
||||
@@ -351,43 +351,43 @@ TEST(StringMatcherTest, CanBeImplicitlyConstructedFromString) {
|
||||
EXPECT_FALSE(m2.Matches("hello"));
|
||||
}
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
// Tests that a C-string literal can be implicitly converted to a
|
||||
// Matcher<absl::string_view> or Matcher<const absl::string_view&>.
|
||||
// Matcher<StringView> or Matcher<const StringView&>.
|
||||
TEST(StringViewMatcherTest, CanBeImplicitlyConstructedFromCStringLiteral) {
|
||||
Matcher<absl::string_view> m1 = "cats";
|
||||
Matcher<internal::StringView> m1 = "cats";
|
||||
EXPECT_TRUE(m1.Matches("cats"));
|
||||
EXPECT_FALSE(m1.Matches("dogs"));
|
||||
|
||||
Matcher<const absl::string_view&> m2 = "cats";
|
||||
Matcher<const internal::StringView&> m2 = "cats";
|
||||
EXPECT_TRUE(m2.Matches("cats"));
|
||||
EXPECT_FALSE(m2.Matches("dogs"));
|
||||
}
|
||||
|
||||
// Tests that a std::string object can be implicitly converted to a
|
||||
// Matcher<absl::string_view> or Matcher<const absl::string_view&>.
|
||||
// Matcher<StringView> or Matcher<const StringView&>.
|
||||
TEST(StringViewMatcherTest, CanBeImplicitlyConstructedFromString) {
|
||||
Matcher<absl::string_view> m1 = std::string("cats");
|
||||
Matcher<internal::StringView> m1 = std::string("cats");
|
||||
EXPECT_TRUE(m1.Matches("cats"));
|
||||
EXPECT_FALSE(m1.Matches("dogs"));
|
||||
|
||||
Matcher<const absl::string_view&> m2 = std::string("cats");
|
||||
Matcher<const internal::StringView&> m2 = std::string("cats");
|
||||
EXPECT_TRUE(m2.Matches("cats"));
|
||||
EXPECT_FALSE(m2.Matches("dogs"));
|
||||
}
|
||||
|
||||
// Tests that a absl::string_view object can be implicitly converted to a
|
||||
// Matcher<absl::string_view> or Matcher<const absl::string_view&>.
|
||||
// Tests that a StringView object can be implicitly converted to a
|
||||
// Matcher<StringView> or Matcher<const StringView&>.
|
||||
TEST(StringViewMatcherTest, CanBeImplicitlyConstructedFromStringView) {
|
||||
Matcher<absl::string_view> m1 = absl::string_view("cats");
|
||||
Matcher<internal::StringView> m1 = internal::StringView("cats");
|
||||
EXPECT_TRUE(m1.Matches("cats"));
|
||||
EXPECT_FALSE(m1.Matches("dogs"));
|
||||
|
||||
Matcher<const absl::string_view&> m2 = absl::string_view("cats");
|
||||
Matcher<const internal::StringView&> m2 = internal::StringView("cats");
|
||||
EXPECT_TRUE(m2.Matches("cats"));
|
||||
EXPECT_FALSE(m2.Matches("dogs"));
|
||||
}
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Tests that a std::reference_wrapper<std::string> object can be implicitly
|
||||
// converted to a Matcher<std::string> or Matcher<const std::string&> via Eq().
|
||||
@@ -1235,17 +1235,17 @@ TEST(StrEqTest, MatchesEqualString) {
|
||||
EXPECT_TRUE(m2.Matches("Hello"));
|
||||
EXPECT_FALSE(m2.Matches("Hi"));
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
Matcher<const absl::string_view&> m3 = StrEq("Hello");
|
||||
EXPECT_TRUE(m3.Matches(absl::string_view("Hello")));
|
||||
EXPECT_FALSE(m3.Matches(absl::string_view("hello")));
|
||||
EXPECT_FALSE(m3.Matches(absl::string_view()));
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
Matcher<const internal::StringView&> m3 = StrEq("Hello");
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("Hello")));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView("hello")));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView()));
|
||||
|
||||
Matcher<const absl::string_view&> m_empty = StrEq("");
|
||||
EXPECT_TRUE(m_empty.Matches(absl::string_view("")));
|
||||
EXPECT_TRUE(m_empty.Matches(absl::string_view()));
|
||||
EXPECT_FALSE(m_empty.Matches(absl::string_view("hello")));
|
||||
#endif // GTEST_HAS_ABSL
|
||||
Matcher<const internal::StringView&> m_empty = StrEq("");
|
||||
EXPECT_TRUE(m_empty.Matches(internal::StringView("")));
|
||||
EXPECT_TRUE(m_empty.Matches(internal::StringView()));
|
||||
EXPECT_FALSE(m_empty.Matches(internal::StringView("hello")));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(StrEqTest, CanDescribeSelf) {
|
||||
@@ -1272,12 +1272,12 @@ TEST(StrNeTest, MatchesUnequalString) {
|
||||
EXPECT_TRUE(m2.Matches("hello"));
|
||||
EXPECT_FALSE(m2.Matches("Hello"));
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
Matcher<const absl::string_view> m3 = StrNe("Hello");
|
||||
EXPECT_TRUE(m3.Matches(absl::string_view("")));
|
||||
EXPECT_TRUE(m3.Matches(absl::string_view()));
|
||||
EXPECT_FALSE(m3.Matches(absl::string_view("Hello")));
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
Matcher<const internal::StringView> m3 = StrNe("Hello");
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("")));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView()));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView("Hello")));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(StrNeTest, CanDescribeSelf) {
|
||||
@@ -1296,13 +1296,13 @@ TEST(StrCaseEqTest, MatchesEqualStringIgnoringCase) {
|
||||
EXPECT_TRUE(m2.Matches("hello"));
|
||||
EXPECT_FALSE(m2.Matches("Hi"));
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
Matcher<const absl::string_view&> m3 = StrCaseEq(std::string("Hello"));
|
||||
EXPECT_TRUE(m3.Matches(absl::string_view("Hello")));
|
||||
EXPECT_TRUE(m3.Matches(absl::string_view("hello")));
|
||||
EXPECT_FALSE(m3.Matches(absl::string_view("Hi")));
|
||||
EXPECT_FALSE(m3.Matches(absl::string_view()));
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
Matcher<const internal::StringView&> m3 = StrCaseEq(std::string("Hello"));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("Hello")));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("hello")));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView("Hi")));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView()));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(StrCaseEqTest, MatchesEqualStringWith0IgnoringCase) {
|
||||
@@ -1346,13 +1346,13 @@ TEST(StrCaseNeTest, MatchesUnequalStringIgnoringCase) {
|
||||
EXPECT_TRUE(m2.Matches(""));
|
||||
EXPECT_FALSE(m2.Matches("Hello"));
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
Matcher<const absl::string_view> m3 = StrCaseNe("Hello");
|
||||
EXPECT_TRUE(m3.Matches(absl::string_view("Hi")));
|
||||
EXPECT_TRUE(m3.Matches(absl::string_view()));
|
||||
EXPECT_FALSE(m3.Matches(absl::string_view("Hello")));
|
||||
EXPECT_FALSE(m3.Matches(absl::string_view("hello")));
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
Matcher<const internal::StringView> m3 = StrCaseNe("Hello");
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("Hi")));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView()));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView("Hello")));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView("hello")));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(StrCaseNeTest, CanDescribeSelf) {
|
||||
@@ -1393,25 +1393,25 @@ TEST(HasSubstrTest, WorksForCStrings) {
|
||||
EXPECT_FALSE(m_empty.Matches(nullptr));
|
||||
}
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
// Tests that HasSubstr() works for matching absl::string_view-typed values.
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
// Tests that HasSubstr() works for matching StringView-typed values.
|
||||
TEST(HasSubstrTest, WorksForStringViewClasses) {
|
||||
const Matcher<absl::string_view> m1 = HasSubstr("foo");
|
||||
EXPECT_TRUE(m1.Matches(absl::string_view("I love food.")));
|
||||
EXPECT_FALSE(m1.Matches(absl::string_view("tofo")));
|
||||
EXPECT_FALSE(m1.Matches(absl::string_view()));
|
||||
const Matcher<internal::StringView> m1 = HasSubstr("foo");
|
||||
EXPECT_TRUE(m1.Matches(internal::StringView("I love food.")));
|
||||
EXPECT_FALSE(m1.Matches(internal::StringView("tofo")));
|
||||
EXPECT_FALSE(m1.Matches(internal::StringView()));
|
||||
|
||||
const Matcher<const absl::string_view&> m2 = HasSubstr("foo");
|
||||
EXPECT_TRUE(m2.Matches(absl::string_view("I love food.")));
|
||||
EXPECT_FALSE(m2.Matches(absl::string_view("tofo")));
|
||||
EXPECT_FALSE(m2.Matches(absl::string_view()));
|
||||
const Matcher<const internal::StringView&> m2 = HasSubstr("foo");
|
||||
EXPECT_TRUE(m2.Matches(internal::StringView("I love food.")));
|
||||
EXPECT_FALSE(m2.Matches(internal::StringView("tofo")));
|
||||
EXPECT_FALSE(m2.Matches(internal::StringView()));
|
||||
|
||||
const Matcher<const absl::string_view&> m3 = HasSubstr("");
|
||||
EXPECT_TRUE(m3.Matches(absl::string_view("foo")));
|
||||
EXPECT_TRUE(m3.Matches(absl::string_view("")));
|
||||
EXPECT_TRUE(m3.Matches(absl::string_view()));
|
||||
const Matcher<const internal::StringView&> m3 = HasSubstr("");
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("foo")));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("")));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView()));
|
||||
}
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Tests that HasSubstr(s) describes itself properly.
|
||||
TEST(HasSubstrTest, CanDescribeSelf) {
|
||||
@@ -1648,12 +1648,12 @@ TEST(StartsWithTest, MatchesStringWithGivenPrefix) {
|
||||
EXPECT_FALSE(m2.Matches("H"));
|
||||
EXPECT_FALSE(m2.Matches(" Hi"));
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
const Matcher<absl::string_view> m_empty = StartsWith("");
|
||||
EXPECT_TRUE(m_empty.Matches(absl::string_view()));
|
||||
EXPECT_TRUE(m_empty.Matches(absl::string_view("")));
|
||||
EXPECT_TRUE(m_empty.Matches(absl::string_view("not empty")));
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
const Matcher<internal::StringView> m_empty = StartsWith("");
|
||||
EXPECT_TRUE(m_empty.Matches(internal::StringView()));
|
||||
EXPECT_TRUE(m_empty.Matches(internal::StringView("")));
|
||||
EXPECT_TRUE(m_empty.Matches(internal::StringView("not empty")));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(StartsWithTest, CanDescribeSelf) {
|
||||
@@ -1676,13 +1676,13 @@ TEST(EndsWithTest, MatchesStringWithGivenSuffix) {
|
||||
EXPECT_FALSE(m2.Matches("i"));
|
||||
EXPECT_FALSE(m2.Matches("Hi "));
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
const Matcher<const absl::string_view&> m4 = EndsWith("");
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
const Matcher<const internal::StringView&> m4 = EndsWith("");
|
||||
EXPECT_TRUE(m4.Matches("Hi"));
|
||||
EXPECT_TRUE(m4.Matches(""));
|
||||
EXPECT_TRUE(m4.Matches(absl::string_view()));
|
||||
EXPECT_TRUE(m4.Matches(absl::string_view("")));
|
||||
#endif // GTEST_HAS_ABSL
|
||||
EXPECT_TRUE(m4.Matches(internal::StringView()));
|
||||
EXPECT_TRUE(m4.Matches(internal::StringView("")));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(EndsWithTest, CanDescribeSelf) {
|
||||
@@ -1703,16 +1703,16 @@ TEST(MatchesRegexTest, MatchesStringMatchingGivenRegex) {
|
||||
EXPECT_FALSE(m2.Matches("az1"));
|
||||
EXPECT_FALSE(m2.Matches("1az"));
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
const Matcher<const absl::string_view&> m3 = MatchesRegex("a.*z");
|
||||
EXPECT_TRUE(m3.Matches(absl::string_view("az")));
|
||||
EXPECT_TRUE(m3.Matches(absl::string_view("abcz")));
|
||||
EXPECT_FALSE(m3.Matches(absl::string_view("1az")));
|
||||
EXPECT_FALSE(m3.Matches(absl::string_view()));
|
||||
const Matcher<const absl::string_view&> m4 = MatchesRegex("");
|
||||
EXPECT_TRUE(m4.Matches(absl::string_view("")));
|
||||
EXPECT_TRUE(m4.Matches(absl::string_view()));
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
const Matcher<const internal::StringView&> m3 = MatchesRegex("a.*z");
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("az")));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("abcz")));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView("1az")));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView()));
|
||||
const Matcher<const internal::StringView&> m4 = MatchesRegex("");
|
||||
EXPECT_TRUE(m4.Matches(internal::StringView("")));
|
||||
EXPECT_TRUE(m4.Matches(internal::StringView()));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(MatchesRegexTest, CanDescribeSelf) {
|
||||
@@ -1722,10 +1722,10 @@ TEST(MatchesRegexTest, CanDescribeSelf) {
|
||||
Matcher<const char*> m2 = MatchesRegex(new RE("a.*"));
|
||||
EXPECT_EQ("matches regular expression \"a.*\"", Describe(m2));
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
Matcher<const absl::string_view> m3 = MatchesRegex(new RE("0.*"));
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
Matcher<const internal::StringView> m3 = MatchesRegex(new RE("0.*"));
|
||||
EXPECT_EQ("matches regular expression \"0.*\"", Describe(m3));
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
// Tests ContainsRegex().
|
||||
@@ -1741,16 +1741,17 @@ TEST(ContainsRegexTest, MatchesStringContainingGivenRegex) {
|
||||
EXPECT_TRUE(m2.Matches("az1"));
|
||||
EXPECT_FALSE(m2.Matches("1a"));
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
const Matcher<const absl::string_view&> m3 = ContainsRegex(new RE("a.*z"));
|
||||
EXPECT_TRUE(m3.Matches(absl::string_view("azbz")));
|
||||
EXPECT_TRUE(m3.Matches(absl::string_view("az1")));
|
||||
EXPECT_FALSE(m3.Matches(absl::string_view("1a")));
|
||||
EXPECT_FALSE(m3.Matches(absl::string_view()));
|
||||
const Matcher<const absl::string_view&> m4 = ContainsRegex("");
|
||||
EXPECT_TRUE(m4.Matches(absl::string_view("")));
|
||||
EXPECT_TRUE(m4.Matches(absl::string_view()));
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
const Matcher<const internal::StringView&> m3 =
|
||||
ContainsRegex(new RE("a.*z"));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("azbz")));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("az1")));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView("1a")));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView()));
|
||||
const Matcher<const internal::StringView&> m4 = ContainsRegex("");
|
||||
EXPECT_TRUE(m4.Matches(internal::StringView("")));
|
||||
EXPECT_TRUE(m4.Matches(internal::StringView()));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(ContainsRegexTest, CanDescribeSelf) {
|
||||
@@ -1760,10 +1761,10 @@ TEST(ContainsRegexTest, CanDescribeSelf) {
|
||||
Matcher<const char*> m2 = ContainsRegex(new RE("a.*"));
|
||||
EXPECT_EQ("contains regular expression \"a.*\"", Describe(m2));
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
Matcher<const absl::string_view> m3 = ContainsRegex(new RE("0.*"));
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
Matcher<const internal::StringView> m3 = ContainsRegex(new RE("0.*"));
|
||||
EXPECT_EQ("contains regular expression \"0.*\"", Describe(m3));
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
// Tests for wide strings.
|
||||
@@ -2875,6 +2876,33 @@ TEST(ExplainMatchResultTest, WorksWithMonomorphicMatcher) {
|
||||
EXPECT_EQ("", listener2.str());
|
||||
}
|
||||
|
||||
MATCHER(ConstructNoArg, "") { return true; }
|
||||
MATCHER_P(Construct1Arg, arg1, "") { return true; }
|
||||
MATCHER_P2(Construct2Args, arg1, arg2, "") { return true; }
|
||||
|
||||
TEST(MatcherConstruct, ExplicitVsImplicit) {
|
||||
{
|
||||
// No arg constructor can be constructed with empty brace.
|
||||
ConstructNoArgMatcher m = {};
|
||||
(void)m;
|
||||
// And with no args
|
||||
ConstructNoArgMatcher m2;
|
||||
(void)m2;
|
||||
}
|
||||
{
|
||||
// The one arg constructor has an explicit constructor.
|
||||
// This is to prevent the implicit conversion.
|
||||
using M = Construct1ArgMatcherP<int>;
|
||||
EXPECT_TRUE((std::is_constructible<M, int>::value));
|
||||
EXPECT_FALSE((std::is_convertible<int, M>::value));
|
||||
}
|
||||
{
|
||||
// Multiple arg matchers can be constructed with an implicit construction.
|
||||
Construct2ArgsMatcherP2<int, double> m = {1, 2.2};
|
||||
(void)m;
|
||||
}
|
||||
}
|
||||
|
||||
MATCHER_P(Really, inner_matcher, "") {
|
||||
return ExplainMatchResult(inner_matcher, arg, result_listener);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "test/gmock-actions_test.cc"
|
||||
#include "test/gmock-cardinalities_test.cc"
|
||||
#include "test/gmock-generated-actions_test.cc"
|
||||
#include "test/gmock-generated-function-mockers_test.cc"
|
||||
#include "test/gmock-generated-matchers_test.cc"
|
||||
#include "test/gmock-internal-utils_test.cc"
|
||||
#include "test/gmock-matchers_test.cc"
|
||||
|
||||
@@ -638,6 +638,7 @@ Fatal assertion | Nonfatal assertion
|
||||
------------------------------------------------ | ------------------------------------------------ | --------
|
||||
`ASSERT_DEATH(statement, matcher);` | `EXPECT_DEATH(statement, matcher);` | `statement` crashes with the given error
|
||||
`ASSERT_DEATH_IF_SUPPORTED(statement, matcher);` | `EXPECT_DEATH_IF_SUPPORTED(statement, matcher);` | if death tests are supported, verifies that `statement` crashes with the given error; otherwise verifies nothing
|
||||
`ASSERT_DEBUG_DEATH(statement, matcher);` | `EXPECT_DEBUG_DEATH(statement, matcher);` | `statement` crashes with the given error **in debug mode**. When not in debug (i.e. `NDEBUG` is defined), this just executes `statement`
|
||||
`ASSERT_EXIT(statement, predicate, matcher);` | `EXPECT_EXIT(statement, predicate, matcher);` | `statement` exits with the given error, and its exit code matches `predicate`
|
||||
|
||||
where `statement` is a statement that is expected to cause the process to die,
|
||||
|
||||
@@ -384,18 +384,18 @@ class GTEST_API_ Matcher<std::string>
|
||||
Matcher(const char* s); // NOLINT
|
||||
};
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
// The following two specializations allow the user to write str
|
||||
// instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view
|
||||
// matcher is expected.
|
||||
template <>
|
||||
class GTEST_API_ Matcher<const absl::string_view&>
|
||||
: public internal::MatcherBase<const absl::string_view&> {
|
||||
class GTEST_API_ Matcher<const internal::StringView&>
|
||||
: public internal::MatcherBase<const internal::StringView&> {
|
||||
public:
|
||||
Matcher() {}
|
||||
|
||||
explicit Matcher(const MatcherInterface<const absl::string_view&>* impl)
|
||||
: internal::MatcherBase<const absl::string_view&>(impl) {}
|
||||
explicit Matcher(const MatcherInterface<const internal::StringView&>* impl)
|
||||
: internal::MatcherBase<const internal::StringView&>(impl) {}
|
||||
|
||||
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||
// str is a std::string object.
|
||||
@@ -404,20 +404,20 @@ class GTEST_API_ Matcher<const absl::string_view&>
|
||||
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
||||
Matcher(const char* s); // NOLINT
|
||||
|
||||
// Allows the user to pass absl::string_views directly.
|
||||
Matcher(absl::string_view s); // NOLINT
|
||||
// Allows the user to pass absl::string_views or std::string_views directly.
|
||||
Matcher(internal::StringView s); // NOLINT
|
||||
};
|
||||
|
||||
template <>
|
||||
class GTEST_API_ Matcher<absl::string_view>
|
||||
: public internal::MatcherBase<absl::string_view> {
|
||||
class GTEST_API_ Matcher<internal::StringView>
|
||||
: public internal::MatcherBase<internal::StringView> {
|
||||
public:
|
||||
Matcher() {}
|
||||
|
||||
explicit Matcher(const MatcherInterface<const absl::string_view&>* impl)
|
||||
: internal::MatcherBase<absl::string_view>(impl) {}
|
||||
explicit Matcher(const MatcherInterface<absl::string_view>* impl)
|
||||
: internal::MatcherBase<absl::string_view>(impl) {}
|
||||
explicit Matcher(const MatcherInterface<const internal::StringView&>* impl)
|
||||
: internal::MatcherBase<internal::StringView>(impl) {}
|
||||
explicit Matcher(const MatcherInterface<internal::StringView>* impl)
|
||||
: internal::MatcherBase<internal::StringView>(impl) {}
|
||||
|
||||
// Allows the user to write str instead of Eq(str) sometimes, where
|
||||
// str is a std::string object.
|
||||
@@ -426,10 +426,10 @@ class GTEST_API_ Matcher<absl::string_view>
|
||||
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
||||
Matcher(const char* s); // NOLINT
|
||||
|
||||
// Allows the user to pass absl::string_views directly.
|
||||
Matcher(absl::string_view s); // NOLINT
|
||||
// Allows the user to pass absl::string_views or std::string_views directly.
|
||||
Matcher(internal::StringView s); // NOLINT
|
||||
};
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Prints a matcher in a human-readable format.
|
||||
template <typename T>
|
||||
@@ -620,12 +620,12 @@ class MatchesRegexMatcher {
|
||||
MatchesRegexMatcher(const RE* regex, bool full_match)
|
||||
: regex_(regex), full_match_(full_match) {}
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
bool MatchAndExplain(const absl::string_view& s,
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
bool MatchAndExplain(const internal::StringView& s,
|
||||
MatchResultListener* listener) const {
|
||||
return MatchAndExplain(std::string(s), listener);
|
||||
}
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Accepts pointer types, particularly:
|
||||
// const char*
|
||||
|
||||
@@ -135,9 +135,9 @@ enum TypeKind {
|
||||
kProtobuf, // a protobuf type
|
||||
kConvertibleToInteger, // a type implicitly convertible to BiggestInt
|
||||
// (e.g. a named or unnamed enum type)
|
||||
#if GTEST_HAS_ABSL
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
kConvertibleToStringView, // a type implicitly convertible to
|
||||
// absl::string_view
|
||||
// absl::string_view or std::string_view
|
||||
#endif
|
||||
kOtherType // anything else
|
||||
};
|
||||
@@ -191,12 +191,13 @@ class TypeWithoutFormatter<T, kConvertibleToInteger> {
|
||||
}
|
||||
};
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
template <typename T>
|
||||
class TypeWithoutFormatter<T, kConvertibleToStringView> {
|
||||
public:
|
||||
// Since T has neither operator<< nor PrintTo() but can be implicitly
|
||||
// converted to absl::string_view, we print it as a absl::string_view.
|
||||
// converted to absl::string_view, we print it as a absl::string_view
|
||||
// (or std::string_view).
|
||||
//
|
||||
// Note: the implementation is further below, as it depends on
|
||||
// internal::PrintTo symbol which is defined later in the file.
|
||||
@@ -237,9 +238,9 @@ template <typename Char, typename CharTraits, typename T>
|
||||
const T&, internal::BiggestInt>::value
|
||||
? kConvertibleToInteger
|
||||
:
|
||||
#if GTEST_HAS_ABSL
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
std::is_convertible<
|
||||
const T&, absl::string_view>::value
|
||||
const T&, internal::StringView>::value
|
||||
? kConvertibleToStringView
|
||||
:
|
||||
#endif
|
||||
@@ -601,12 +602,12 @@ inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
|
||||
}
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
// Overload for absl::string_view.
|
||||
inline void PrintTo(absl::string_view sp, ::std::ostream* os) {
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
// Overload for internal::StringView.
|
||||
inline void PrintTo(internal::StringView sp, ::std::ostream* os) {
|
||||
PrintTo(::std::string(sp), os);
|
||||
}
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; }
|
||||
|
||||
@@ -899,12 +900,12 @@ Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
|
||||
|
||||
} // namespace internal
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
namespace internal2 {
|
||||
template <typename T>
|
||||
void TypeWithoutFormatter<T, kConvertibleToStringView>::PrintValue(
|
||||
const T& value, ::std::ostream* os) {
|
||||
internal::PrintTo(absl::string_view(value), os);
|
||||
internal::PrintTo(internal::StringView(value), os);
|
||||
}
|
||||
} // namespace internal2
|
||||
#endif
|
||||
|
||||
@@ -279,7 +279,11 @@ class GTEST_API_ AssertionResult {
|
||||
// Used in EXPECT_TRUE/FALSE(assertion_result).
|
||||
AssertionResult(const AssertionResult& other);
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1910
|
||||
// C4800 is a level 3 warning in Visual Studio 2015 and earlier.
|
||||
// This warning is not emitted in Visual Studio 2017.
|
||||
// This warning is off by default starting in Visual Studio 2019 but can be
|
||||
// enabled with command-line options.
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920)
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */)
|
||||
#endif
|
||||
|
||||
@@ -299,7 +303,7 @@ class GTEST_API_ AssertionResult {
|
||||
= nullptr)
|
||||
: success_(success) {}
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1910
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920)
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
||||
#endif
|
||||
|
||||
@@ -2364,9 +2368,11 @@ constexpr bool StaticAssertTypeEq() noexcept {
|
||||
// }
|
||||
//
|
||||
// GOOGLETEST_CM0011 DO NOT DELETE
|
||||
#if !GTEST_DONT_DEFINE_TEST
|
||||
#define TEST_F(test_fixture, test_name)\
|
||||
GTEST_TEST_(test_fixture, test_name, test_fixture, \
|
||||
::testing::internal::GetTypeId<test_fixture>())
|
||||
#endif // !GTEST_DONT_DEFINE_TEST
|
||||
|
||||
// Returns a path to temporary directory.
|
||||
// Tries to determine an appropriate directory for the platform.
|
||||
|
||||
@@ -199,6 +199,9 @@
|
||||
// suppressed (constant conditional).
|
||||
// GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127
|
||||
// is suppressed.
|
||||
// GTEST_INTERNAL_HAS_STRING_VIEW - for enabling Matcher<std::string_view> or
|
||||
// Matcher<absl::string_view>
|
||||
// specializations.
|
||||
//
|
||||
// Synchronization:
|
||||
// Mutex, MutexLock, ThreadLocal, GetThreadCount()
|
||||
@@ -2220,4 +2223,32 @@ const char* StringFromGTestEnv(const char* flag, const char* default_val);
|
||||
|
||||
#endif // !defined(GTEST_INTERNAL_DEPRECATED)
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
// Always use absl::string_view for Matcher<> specializations if googletest
|
||||
// is built with absl support.
|
||||
# define GTEST_INTERNAL_HAS_STRING_VIEW 1
|
||||
#include "absl/strings/string_view.h"
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
using StringView = ::absl::string_view;
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
#else
|
||||
# ifdef __has_include
|
||||
# if __has_include(<string_view>) && __cplusplus >= 201703L
|
||||
// Otherwise for C++17 and higher use std::string_view for Matcher<>
|
||||
// specializations.
|
||||
# define GTEST_INTERNAL_HAS_STRING_VIEW 1
|
||||
#include <string_view>
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
using StringView = ::std::string_view;
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
// The case where absl is configured NOT to alias std::string_view is not
|
||||
// supported.
|
||||
# endif // __has_include(<string_view>) && __cplusplus >= 201703L
|
||||
# endif // __has_include
|
||||
#endif // GTEST_HAS_ABSL
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
|
||||
|
||||
@@ -66,11 +66,11 @@ class OnTheFlyPrimeTable : public PrimeTable {
|
||||
}
|
||||
|
||||
int GetNextPrime(int p) const override {
|
||||
for (int n = p + 1; n > 0; n++) {
|
||||
if (p < 0) return -1;
|
||||
|
||||
for (int n = p + 1;; n++) {
|
||||
if (IsPrime(n)) return n;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -58,40 +58,40 @@ Matcher<std::string>::Matcher(const std::string& s) { *this = Eq(s); }
|
||||
// s.
|
||||
Matcher<std::string>::Matcher(const char* s) { *this = Eq(std::string(s)); }
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
// Constructs a matcher that matches a const absl::string_view& whose value is
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
// Constructs a matcher that matches a const StringView& whose value is
|
||||
// equal to s.
|
||||
Matcher<const absl::string_view&>::Matcher(const std::string& s) {
|
||||
Matcher<const internal::StringView&>::Matcher(const std::string& s) {
|
||||
*this = Eq(s);
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a const absl::string_view& whose value is
|
||||
// Constructs a matcher that matches a const StringView& whose value is
|
||||
// equal to s.
|
||||
Matcher<const absl::string_view&>::Matcher(const char* s) {
|
||||
Matcher<const internal::StringView&>::Matcher(const char* s) {
|
||||
*this = Eq(std::string(s));
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a const absl::string_view& whose value is
|
||||
// Constructs a matcher that matches a const StringView& whose value is
|
||||
// equal to s.
|
||||
Matcher<const absl::string_view&>::Matcher(absl::string_view s) {
|
||||
Matcher<const internal::StringView&>::Matcher(internal::StringView s) {
|
||||
*this = Eq(std::string(s));
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a absl::string_view whose value is equal to
|
||||
// Constructs a matcher that matches a StringView whose value is equal to
|
||||
// s.
|
||||
Matcher<absl::string_view>::Matcher(const std::string& s) { *this = Eq(s); }
|
||||
Matcher<internal::StringView>::Matcher(const std::string& s) { *this = Eq(s); }
|
||||
|
||||
// Constructs a matcher that matches a absl::string_view whose value is equal to
|
||||
// Constructs a matcher that matches a StringView whose value is equal to
|
||||
// s.
|
||||
Matcher<absl::string_view>::Matcher(const char* s) {
|
||||
Matcher<internal::StringView>::Matcher(const char* s) {
|
||||
*this = Eq(std::string(s));
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a absl::string_view whose value is equal to
|
||||
// Constructs a matcher that matches a StringView whose value is equal to
|
||||
// s.
|
||||
Matcher<absl::string_view>::Matcher(absl::string_view s) {
|
||||
Matcher<internal::StringView>::Matcher(internal::StringView s) {
|
||||
*this = Eq(std::string(s));
|
||||
}
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
} // namespace testing
|
||||
|
||||
@@ -56,6 +56,7 @@ cc_test(
|
||||
"gtest-listener_test.cc",
|
||||
"gtest-unittest-api_test.cc",
|
||||
"googletest-param-test-test.cc",
|
||||
"googletest-param-test2-test.cc",
|
||||
"googletest-catch-exceptions-test_.cc",
|
||||
"googletest-color-test_.cc",
|
||||
"googletest-env-var-test_.cc",
|
||||
|
||||
@@ -760,22 +760,22 @@ TEST(PrintTypeWithGenericStreamingTest, TypeImplicitlyConvertible) {
|
||||
EXPECT_EQ("AllowsGenericStreamingAndImplicitConversionTemplate", Print(a));
|
||||
}
|
||||
|
||||
#if GTEST_HAS_ABSL
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Tests printing ::absl::string_view.
|
||||
// Tests printing internal::StringView.
|
||||
|
||||
TEST(PrintStringViewTest, SimpleStringView) {
|
||||
const ::absl::string_view sp = "Hello";
|
||||
const internal::StringView sp = "Hello";
|
||||
EXPECT_EQ("\"Hello\"", Print(sp));
|
||||
}
|
||||
|
||||
TEST(PrintStringViewTest, UnprintableCharacters) {
|
||||
const char str[] = "NUL (\0) and \r\t";
|
||||
const ::absl::string_view sp(str, sizeof(str) - 1);
|
||||
const internal::StringView sp(str, sizeof(str) - 1);
|
||||
EXPECT_EQ("\"NUL (\\0) and \\r\\t\"", Print(sp));
|
||||
}
|
||||
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Tests printing STL containers.
|
||||
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
// Copyright 2008, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// Tests for Google Test itself. This verifies that the basic constructs of
|
||||
// Google Test work.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "googletest-param-test-test.h"
|
||||
|
||||
using ::testing::Values;
|
||||
using ::testing::internal::ParamGenerator;
|
||||
|
||||
// Tests that generators defined in a different translation unit
|
||||
// are functional. The test using extern_gen_2 is defined
|
||||
// in googletest-param-test-test.cc.
|
||||
ParamGenerator<int> extern_gen_2 = Values(33);
|
||||
|
||||
// Tests that a parameterized test case can be defined in one translation unit
|
||||
// and instantiated in another. The test is defined in
|
||||
// googletest-param-test-test.cc and ExternalInstantiationTest fixture class is
|
||||
// defined in gtest-param-test_test.h.
|
||||
INSTANTIATE_TEST_SUITE_P(MultiplesOf33,
|
||||
ExternalInstantiationTest,
|
||||
Values(33, 66));
|
||||
|
||||
// Tests that a parameterized test case can be instantiated
|
||||
// in multiple translation units. Another instantiation is defined
|
||||
// in googletest-param-test-test.cc and
|
||||
// InstantiationInMultipleTranslationUnitsTest fixture is defined in
|
||||
// gtest-param-test_test.h
|
||||
INSTANTIATE_TEST_SUITE_P(Sequence2,
|
||||
InstantiationInMultipleTranslationUnitsTest,
|
||||
Values(42*3, 42*4, 42*5));
|
||||
|
||||
Reference in New Issue
Block a user