Unverified Commit 21e51855 authored by Gennadiy Civil's avatar Gennadiy Civil Committed by GitHub
Browse files

Merge branch 'master' into josh/fix_scoped_class2

parents 3e2cb754 490554aa
$$ -*- mode: c++; -*- $$ -*- mode: c++; -*-
$$ This is a Pump source file (http://go/pump). Please use Pump to convert $$ This is a Pump source file. Please use Pump to convert
$$ it to callback-actions.h. $$ it to callback-actions.h.
$$ $$
$var max_callback_arity = 5 $var max_callback_arity = 5
$$}} This meta comment fixes auto-indentation in editors. $$}} This meta comment fixes auto-indentation in editors.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_ #ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_ #define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
......
...@@ -27,13 +27,10 @@ ...@@ -27,13 +27,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// ============================================================ // Injection point for custom user configurations. See README for details
// An installation-specific extension point for gmock-matchers.h.
// ============================================================
// //
// Adds google3 callback support to CallableTraits. // GOOGLETEST_CM0002 DO NOT DELETE
//
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_CALLBACK_MATCHERS_H_
#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_CALLBACK_MATCHERS_H_
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_CALLBACK_MATCHERS_H_ #ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_MATCHERS_H_
#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_MATCHERS_H_
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_MATCHERS_H_
...@@ -27,19 +27,12 @@ ...@@ -27,19 +27,12 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// Injection point for custom user configurations. // Injection point for custom user configurations. See README for details
// The following macros can be defined:
//
// Flag related macros:
// GMOCK_DECLARE_bool_(name)
// GMOCK_DECLARE_int32_(name)
// GMOCK_DECLARE_string_(name)
// GMOCK_DEFINE_bool_(name, default_val, doc)
// GMOCK_DEFINE_int32_(name, default_val, doc)
// GMOCK_DEFINE_string_(name, default_val, doc)
// //
// ** Custom implementation starts here ** // ** Custom implementation starts here **
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_ #ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_
#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_ #define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_
......
...@@ -30,14 +30,15 @@ ...@@ -30,14 +30,15 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Mock - a framework for writing C++ mock classes. // Google Mock - a framework for writing C++ mock classes.
// //
// This file contains template meta-programming utility classes needed // This file contains template meta-programming utility classes needed
// for implementing Google Mock. // for implementing Google Mock.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_ #ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_ #define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
...@@ -90,42 +91,48 @@ struct MatcherTuple< ::testing::tuple<A1, A2, A3> > { ...@@ -90,42 +91,48 @@ struct MatcherTuple< ::testing::tuple<A1, A2, A3> > {
template <typename A1, typename A2, typename A3, typename A4> template <typename A1, typename A2, typename A3, typename A4>
struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4> > { struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4> > {
typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4> >
Matcher<A4> > type; type;
}; };
template <typename A1, typename A2, typename A3, typename A4, typename A5> template <typename A1, typename A2, typename A3, typename A4, typename A5>
struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5> > { struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5> > {
typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>, typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
Matcher<A5> > type; Matcher<A5> >
type;
}; };
template <typename A1, typename A2, typename A3, typename A4, typename A5, template <typename A1, typename A2, typename A3, typename A4, typename A5,
typename A6> typename A6>
struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6> > { struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6> > {
typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>, typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
Matcher<A5>, Matcher<A6> > type; Matcher<A5>, Matcher<A6> >
type;
}; };
template <typename A1, typename A2, typename A3, typename A4, typename A5, template <typename A1, typename A2, typename A3, typename A4, typename A5,
typename A6, typename A7> typename A6, typename A7>
struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7> > { struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7> > {
typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>, typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
Matcher<A5>, Matcher<A6>, Matcher<A7> > type; Matcher<A5>, Matcher<A6>, Matcher<A7> >
type;
}; };
template <typename A1, typename A2, typename A3, typename A4, typename A5, template <typename A1, typename A2, typename A3, typename A4, typename A5,
typename A6, typename A7, typename A8> typename A6, typename A7, typename A8>
struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8> > { struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8> > {
typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>, typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8> > type; Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8> >
type;
}; };
template <typename A1, typename A2, typename A3, typename A4, typename A5, template <typename A1, typename A2, typename A3, typename A4, typename A5,
typename A6, typename A7, typename A8, typename A9> typename A6, typename A7, typename A8, typename A9>
struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> > { struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> > {
typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>, typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>, Matcher<A9> > type; Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>,
Matcher<A9> >
type;
}; };
template <typename A1, typename A2, typename A3, typename A4, typename A5, template <typename A1, typename A2, typename A3, typename A4, typename A5,
...@@ -133,8 +140,9 @@ template <typename A1, typename A2, typename A3, typename A4, typename A5, ...@@ -133,8 +140,9 @@ template <typename A1, typename A2, typename A3, typename A4, typename A5,
struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9, struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
A10> > { A10> > {
typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>, typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>, Matcher<A9>, Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>,
Matcher<A10> > type; Matcher<A9>, Matcher<A10> >
type;
}; };
// Template struct Function<F>, where F must be a function type, contains // Template struct Function<F>, where F must be a function type, contains
......
...@@ -31,14 +31,15 @@ $var n = 10 $$ The maximum arity we support. ...@@ -31,14 +31,15 @@ $var n = 10 $$ The maximum arity we support.
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Mock - a framework for writing C++ mock classes. // Google Mock - a framework for writing C++ mock classes.
// //
// This file contains template meta-programming utility classes needed // This file contains template meta-programming utility classes needed
// for implementing Google Mock. // for implementing Google Mock.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_ #ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_ #define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
......
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Mock - a framework for writing C++ mock classes. // Google Mock - a framework for writing C++ mock classes.
// //
...@@ -35,13 +34,14 @@ ...@@ -35,13 +34,14 @@
// Mock. They are subject to change without notice, so please DO NOT // Mock. They are subject to change without notice, so please DO NOT
// USE THEM IN USER CODE. // USE THEM IN USER CODE.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_ #ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_ #define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
#include <stdio.h> #include <stdio.h>
#include <ostream> // NOLINT #include <ostream> // NOLINT
#include <string> #include <string>
#include "gmock/internal/gmock-generated-internal-utils.h" #include "gmock/internal/gmock-generated-internal-utils.h"
#include "gmock/internal/gmock-port.h" #include "gmock/internal/gmock-port.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
...@@ -49,11 +49,23 @@ ...@@ -49,11 +49,23 @@
namespace testing { namespace testing {
namespace internal { namespace internal {
// Silence MSVC C4100 (unreferenced formal parameter) and
// C4805('==': unsafe mix of type 'const int' and type 'const bool')
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4100)
# pragma warning(disable:4805)
#endif
// Joins a vector of strings as if they are fields of a tuple; returns
// the joined string.
GTEST_API_ std::string JoinAsTuple(const Strings& fields);
// Converts an identifier name to a space-separated list of lower-case // Converts an identifier name to a space-separated list of lower-case
// words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is // words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
// treated as one word. For example, both "FooBar123" and // treated as one word. For example, both "FooBar123" and
// "foo_bar_123" are converted to "foo bar 123". // "foo_bar_123" are converted to "foo bar 123".
GTEST_API_ string ConvertIdentifierNameToWords(const char* id_name); GTEST_API_ std::string ConvertIdentifierNameToWords(const char* id_name);
// PointeeOf<Pointer>::type is the type of a value pointed to by a // PointeeOf<Pointer>::type is the type of a value pointed to by a
// Pointer, which can be either a smart pointer or a raw pointer. The // Pointer, which can be either a smart pointer or a raw pointer. The
...@@ -114,9 +126,11 @@ struct LinkedPtrLessThan { ...@@ -114,9 +126,11 @@ struct LinkedPtrLessThan {
// To gcc, // To gcc,
// wchar_t == signed wchar_t != unsigned wchar_t == unsigned int // wchar_t == signed wchar_t != unsigned wchar_t == unsigned int
#ifdef __GNUC__ #ifdef __GNUC__
#if !defined(__WCHAR_UNSIGNED__)
// signed/unsigned wchar_t are valid types. // signed/unsigned wchar_t are valid types.
# define GMOCK_HAS_SIGNED_WCHAR_T_ 1 # define GMOCK_HAS_SIGNED_WCHAR_T_ 1
#endif #endif
#endif
// In what follows, we use the term "kind" to indicate whether a type // In what follows, we use the term "kind" to indicate whether a type
// is bool, an integer type (excluding bool), a floating-point type, // is bool, an integer type (excluding bool), a floating-point type,
...@@ -331,7 +345,22 @@ GTEST_API_ bool LogIsVisible(LogSeverity severity); ...@@ -331,7 +345,22 @@ GTEST_API_ bool LogIsVisible(LogSeverity severity);
GTEST_API_ void Log(LogSeverity severity, const std::string& message, GTEST_API_ void Log(LogSeverity severity, const std::string& message,
int stack_frames_to_skip); int stack_frames_to_skip);
// TODO(wan@google.com): group all type utilities together. // A marker class that is used to resolve parameterless expectations to the
// correct overload. This must not be instantiable, to prevent client code from
// accidentally resolving to the overload; for example:
//
// ON_CALL(mock, Method({}, nullptr))...
//
class WithoutMatchers {
private:
WithoutMatchers() {}
friend GTEST_API_ WithoutMatchers GetWithoutMatchers();
};
// Internal use only: access the singleton instance of WithoutMatchers.
GTEST_API_ WithoutMatchers GetWithoutMatchers();
// FIXME: group all type utilities together.
// Type traits. // Type traits.
...@@ -503,8 +532,44 @@ struct RemoveConstFromKey<std::pair<const K, V> > { ...@@ -503,8 +532,44 @@ struct RemoveConstFromKey<std::pair<const K, V> > {
template <bool kValue> template <bool kValue>
struct BooleanConstant {}; struct BooleanConstant {};
// Emit an assertion failure due to incorrect DoDefault() usage. Out-of-lined to
// reduce code size.
GTEST_API_ void IllegalDoDefault(const char* file, int line);
#if GTEST_LANG_CXX11
// Helper types for Apply() below.
template <size_t... Is> struct int_pack { typedef int_pack type; };
template <class Pack, size_t I> struct append;
template <size_t... Is, size_t I>
struct append<int_pack<Is...>, I> : int_pack<Is..., I> {};
template <size_t C>
struct make_int_pack : append<typename make_int_pack<C - 1>::type, C - 1> {};
template <> struct make_int_pack<0> : int_pack<> {};
template <typename F, typename Tuple, size_t... Idx>
auto ApplyImpl(F&& f, Tuple&& args, int_pack<Idx...>) -> decltype(
std::forward<F>(f)(std::get<Idx>(std::forward<Tuple>(args))...)) {
return std::forward<F>(f)(std::get<Idx>(std::forward<Tuple>(args))...);
}
// Apply the function to a tuple of arguments.
template <typename F, typename Tuple>
auto Apply(F&& f, Tuple&& args)
-> decltype(ApplyImpl(std::forward<F>(f), std::forward<Tuple>(args),
make_int_pack<std::tuple_size<Tuple>::value>())) {
return ApplyImpl(std::forward<F>(f), std::forward<Tuple>(args),
make_int_pack<std::tuple_size<Tuple>::value>());
}
#endif
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_ #endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: vadimb@google.com (Vadim Berman)
// //
// Low-level types and utilities for porting Google Mock to various // Low-level types and utilities for porting Google Mock to various
// platforms. All macros ending with _ and symbols defined in an // platforms. All macros ending with _ and symbols defined in an
...@@ -36,6 +35,8 @@ ...@@ -36,6 +35,8 @@
// end with _ are part of Google Mock's public API and can be used by // end with _ are part of Google Mock's public API and can be used by
// code outside Google Mock. // code outside Google Mock.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_ #ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_ #define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
...@@ -50,15 +51,11 @@ ...@@ -50,15 +51,11 @@
// portability utilities to Google Test's gtest-port.h instead of // portability utilities to Google Test's gtest-port.h instead of
// here, as Google Mock depends on Google Test. Only add a utility // here, as Google Mock depends on Google Test. Only add a utility
// here if it's truly specific to Google Mock. // here if it's truly specific to Google Mock.
#include "gtest/internal/gtest-linked_ptr.h" #include "gtest/internal/gtest-linked_ptr.h"
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#include "gmock/internal/custom/gmock-port.h" #include "gmock/internal/custom/gmock-port.h"
// To avoid conditional compilation everywhere, we make it
// gmock-port.h's responsibility to #include the header implementing
// tr1/tuple. gmock-port.h does this via gtest-port.h, which is
// guaranteed to pull in the tuple header.
// For MS Visual C++, check the compiler version. At least VS 2003 is // For MS Visual C++, check the compiler version. At least VS 2003 is
// required to compile Google Mock. // required to compile Google Mock.
#if defined(_MSC_VER) && _MSC_VER < 1310 #if defined(_MSC_VER) && _MSC_VER < 1310
...@@ -72,18 +69,18 @@ ...@@ -72,18 +69,18 @@
#if !defined(GMOCK_DECLARE_bool_) #if !defined(GMOCK_DECLARE_bool_)
// Macros for declaring flags. // Macros for declaring flags.
#define GMOCK_DECLARE_bool_(name) extern GTEST_API_ bool GMOCK_FLAG(name) # define GMOCK_DECLARE_bool_(name) extern GTEST_API_ bool GMOCK_FLAG(name)
#define GMOCK_DECLARE_int32_(name) \ # define GMOCK_DECLARE_int32_(name) \
extern GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) extern GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name)
#define GMOCK_DECLARE_string_(name) \ # define GMOCK_DECLARE_string_(name) \
extern GTEST_API_ ::std::string GMOCK_FLAG(name) extern GTEST_API_ ::std::string GMOCK_FLAG(name)
// Macros for defining flags. // Macros for defining flags.
#define GMOCK_DEFINE_bool_(name, default_val, doc) \ # define GMOCK_DEFINE_bool_(name, default_val, doc) \
GTEST_API_ bool GMOCK_FLAG(name) = (default_val) GTEST_API_ bool GMOCK_FLAG(name) = (default_val)
#define GMOCK_DEFINE_int32_(name, default_val, doc) \ # define GMOCK_DEFINE_int32_(name, default_val, doc) \
GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) = (default_val) GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) = (default_val)
#define GMOCK_DEFINE_string_(name, default_val, doc) \ # define GMOCK_DEFINE_string_(name, default_val, doc) \
GTEST_API_ ::std::string GMOCK_FLAG(name) = (default_val) GTEST_API_ ::std::string GMOCK_FLAG(name) = (default_val)
#endif // !defined(GMOCK_DECLARE_bool_) #endif // !defined(GMOCK_DECLARE_bool_)
......
The Google Mock class generator is an application that is part of cppclean. The Google Mock class generator is an application that is part of cppclean.
For more information about cppclean, see the README.cppclean file or For more information about cppclean, visit http://code.google.com/p/cppclean/
visit http://code.google.com/p/cppclean/
cppclean requires Python 2.3.5 or later. If you don't have Python installed The mock generator requires Python 2.3.5 or later. If you don't have Python
on your system, you will also need to install it. You can download Python installed on your system, you will also need to install it. You can download
from: http://www.python.org/download/releases/ Python from: http://www.python.org/download/releases/
To use the Google Mock class generator, you need to call it To use the Google Mock class generator, you need to call it
on the command line passing the header file and class for which you want on the command line passing the header file and class for which you want
......
...@@ -338,7 +338,7 @@ class Class(_GenericDeclaration): ...@@ -338,7 +338,7 @@ class Class(_GenericDeclaration):
# TODO(nnorwitz): handle namespaces, etc. # TODO(nnorwitz): handle namespaces, etc.
if self.bases: if self.bases:
for token_list in self.bases: for token_list in self.bases:
# TODO(nnorwitz): bases are tokens, do name comparision. # TODO(nnorwitz): bases are tokens, do name comparison.
for token in token_list: for token in token_list:
if token.name == node.name: if token.name == node.name:
return True return True
...@@ -381,7 +381,7 @@ class Function(_GenericDeclaration): ...@@ -381,7 +381,7 @@ class Function(_GenericDeclaration):
def Requires(self, node): def Requires(self, node):
if self.parameters: if self.parameters:
# TODO(nnorwitz): parameters are tokens, do name comparision. # TODO(nnorwitz): parameters are tokens, do name comparison.
for p in self.parameters: for p in self.parameters:
if p.name == node.name: if p.name == node.name:
return True return True
...@@ -858,7 +858,7 @@ class AstBuilder(object): ...@@ -858,7 +858,7 @@ class AstBuilder(object):
last_token = self._GetNextToken() last_token = self._GetNextToken()
return tokens, last_token return tokens, last_token
# TODO(nnorwitz): remove _IgnoreUpTo() it shouldn't be necesary. # TODO(nnorwitz): remove _IgnoreUpTo() it shouldn't be necessary.
def _IgnoreUpTo(self, token_type, token): def _IgnoreUpTo(self, token_type, token):
unused_tokens = self._GetTokensUpTo(token_type, token) unused_tokens = self._GetTokensUpTo(token_type, token)
......
...@@ -242,7 +242,7 @@ class AbstractRpcServer(object): ...@@ -242,7 +242,7 @@ class AbstractRpcServer(object):
The authentication process works as follows: The authentication process works as follows:
1) We get a username and password from the user 1) We get a username and password from the user
2) We use ClientLogin to obtain an AUTH token for the user 2) We use ClientLogin to obtain an AUTH token for the user
(see http://code.google.com/apis/accounts/AuthForInstalledApps.html). (see https://developers.google.com/identity/protocols/AuthForInstalledApps).
3) We pass the auth token to /_ah/login on the server to obtain an 3) We pass the auth token to /_ah/login on the server to obtain an
authentication cookie. If login was successful, it tries to redirect authentication cookie. If login was successful, it tries to redirect
us to the URL we provided. us to the URL we provided.
...@@ -506,7 +506,7 @@ def EncodeMultipartFormData(fields, files): ...@@ -506,7 +506,7 @@ def EncodeMultipartFormData(fields, files):
(content_type, body) ready for httplib.HTTP instance. (content_type, body) ready for httplib.HTTP instance.
Source: Source:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306 https://web.archive.org/web/20160116052001/code.activestate.com/recipes/146306
""" """
BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-' BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-'
CRLF = '\r\n' CRLF = '\r\n'
...@@ -807,7 +807,7 @@ class SubversionVCS(VersionControlSystem): ...@@ -807,7 +807,7 @@ class SubversionVCS(VersionControlSystem):
# svn cat translates keywords but svn diff doesn't. As a result of this # svn cat translates keywords but svn diff doesn't. As a result of this
# behavior patching.PatchChunks() fails with a chunk mismatch error. # behavior patching.PatchChunks() fails with a chunk mismatch error.
# This part was originally written by the Review Board development team # This part was originally written by the Review Board development team
# who had the same problem (http://reviews.review-board.org/r/276/). # who had the same problem (https://reviews.reviewboard.org/r/276/).
# Mapping of keywords to known aliases # Mapping of keywords to known aliases
svn_keywords = { svn_keywords = {
# Standard keywords # Standard keywords
...@@ -860,7 +860,7 @@ class SubversionVCS(VersionControlSystem): ...@@ -860,7 +860,7 @@ class SubversionVCS(VersionControlSystem):
status_lines = status.splitlines() status_lines = status.splitlines()
# If file is in a cl, the output will begin with # If file is in a cl, the output will begin with
# "\n--- Changelist 'cl_name':\n". See # "\n--- Changelist 'cl_name':\n". See
# http://svn.collab.net/repos/svn/trunk/notes/changelist-design.txt # https://web.archive.org/web/20090918234815/svn.collab.net/repos/svn/trunk/notes/changelist-design.txt
if (len(status_lines) == 3 and if (len(status_lines) == 3 and
not status_lines[0] and not status_lines[0] and
status_lines[1].startswith("--- Changelist")): status_lines[1].startswith("--- Changelist")):
......
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// //
// Google C++ Mocking Framework (Google Mock) // Google C++ Mocking Framework (Google Mock)
// //
......
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Mock - a framework for writing C++ mock classes. // Google Mock - a framework for writing C++ mock classes.
// //
......
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Mock - a framework for writing C++ mock classes. // Google Mock - a framework for writing C++ mock classes.
// //
...@@ -47,12 +46,31 @@ ...@@ -47,12 +46,31 @@
namespace testing { namespace testing {
namespace internal { namespace internal {
// Joins a vector of strings as if they are fields of a tuple; returns
// the joined string.
GTEST_API_ std::string JoinAsTuple(const Strings& fields) {
switch (fields.size()) {
case 0:
return "";
case 1:
return fields[0];
default:
std::string result = "(" + fields[0];
for (size_t i = 1; i < fields.size(); i++) {
result += ", ";
result += fields[i];
}
result += ")";
return result;
}
}
// Converts an identifier name to a space-separated list of lower-case // Converts an identifier name to a space-separated list of lower-case
// words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is // words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
// treated as one word. For example, both "FooBar123" and // treated as one word. For example, both "FooBar123" and
// "foo_bar_123" are converted to "foo bar 123". // "foo_bar_123" are converted to "foo bar 123".
GTEST_API_ string ConvertIdentifierNameToWords(const char* id_name) { GTEST_API_ std::string ConvertIdentifierNameToWords(const char* id_name) {
string result; std::string result;
char prev_char = '\0'; char prev_char = '\0';
for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) { for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) {
// We don't care about the current locale as the input is // We don't care about the current locale as the input is
...@@ -169,5 +187,17 @@ GTEST_API_ void Log(LogSeverity severity, const std::string& message, ...@@ -169,5 +187,17 @@ GTEST_API_ void Log(LogSeverity severity, const std::string& message,
std::cout << ::std::flush; std::cout << ::std::flush;
} }
GTEST_API_ WithoutMatchers GetWithoutMatchers() { return WithoutMatchers(); }
GTEST_API_ void IllegalDoDefault(const char* file, int line) {
internal::Assert(
false, file, line,
"You are using DoDefault() inside a composite action like "
"DoAll() or WithArgs(). This is not supported for technical "
"reasons. Please instead spell out the default action, or "
"assign the default action to an Action variable and use "
"the variable in various places.");
}
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Mock - a framework for writing C++ mock classes. // Google Mock - a framework for writing C++ mock classes.
// //
...@@ -38,98 +37,133 @@ ...@@ -38,98 +37,133 @@
#include "gmock/gmock-generated-matchers.h" #include "gmock/gmock-generated-matchers.h"
#include <string.h> #include <string.h>
#include <iostream>
#include <sstream> #include <sstream>
#include <string> #include <string>
namespace testing { namespace testing {
// Constructs a matcher that matches a const string& whose value is // Constructs a matcher that matches a const std::string& whose value is
// equal to s. // equal to s.
Matcher<const internal::string&>::Matcher(const internal::string& s) { Matcher<const std::string&>::Matcher(const std::string& s) { *this = Eq(s); }
*this = Eq(s);
#if GTEST_HAS_GLOBAL_STRING
// Constructs a matcher that matches a const std::string& whose value is
// equal to s.
Matcher<const std::string&>::Matcher(const ::string& s) {
*this = Eq(static_cast<std::string>(s));
} }
#endif // GTEST_HAS_GLOBAL_STRING
// Constructs a matcher that matches a const string& whose value is // Constructs a matcher that matches a const std::string& whose value is
// equal to s. // equal to s.
Matcher<const internal::string&>::Matcher(const char* s) { Matcher<const std::string&>::Matcher(const char* s) {
*this = Eq(internal::string(s)); *this = Eq(std::string(s));
} }
// Constructs a matcher that matches a string whose value is equal to s. // Constructs a matcher that matches a std::string whose value is equal to
Matcher<internal::string>::Matcher(const internal::string& s) { *this = Eq(s); } // s.
Matcher<std::string>::Matcher(const std::string& s) { *this = Eq(s); }
// Constructs a matcher that matches a string whose value is equal to s. #if GTEST_HAS_GLOBAL_STRING
Matcher<internal::string>::Matcher(const char* s) { // Constructs a matcher that matches a std::string whose value is equal to
*this = Eq(internal::string(s)); // s.
Matcher<std::string>::Matcher(const ::string& s) {
*this = Eq(static_cast<std::string>(s));
} }
#endif // GTEST_HAS_GLOBAL_STRING
// Constructs a matcher that matches a std::string whose value is equal to
// s.
Matcher<std::string>::Matcher(const char* s) { *this = Eq(std::string(s)); }
#if GTEST_HAS_STRING_PIECE_ #if GTEST_HAS_GLOBAL_STRING
// Constructs a matcher that matches a const StringPiece& whose value is // Constructs a matcher that matches a const ::string& whose value is
// equal to s. // equal to s.
Matcher<const StringPiece&>::Matcher(const internal::string& s) { Matcher<const ::string&>::Matcher(const std::string& s) {
*this = Eq(s); *this = Eq(static_cast<::string>(s));
} }
// Constructs a matcher that matches a const StringPiece& whose value is // Constructs a matcher that matches a const ::string& whose value is
// equal to s. // equal to s.
Matcher<const StringPiece&>::Matcher(const char* s) { Matcher<const ::string&>::Matcher(const ::string& s) { *this = Eq(s); }
*this = Eq(internal::string(s));
}
// Constructs a matcher that matches a const StringPiece& whose value is // Constructs a matcher that matches a const ::string& whose value is
// equal to s. // equal to s.
Matcher<const StringPiece&>::Matcher(StringPiece s) { Matcher<const ::string&>::Matcher(const char* s) { *this = Eq(::string(s)); }
*this = Eq(s.ToString());
// Constructs a matcher that matches a ::string whose value is equal to s.
Matcher<::string>::Matcher(const std::string& s) {
*this = Eq(static_cast<::string>(s));
} }
// Constructs a matcher that matches a StringPiece whose value is equal to s. // Constructs a matcher that matches a ::string whose value is equal to s.
Matcher<StringPiece>::Matcher(const internal::string& s) { Matcher<::string>::Matcher(const ::string& s) { *this = Eq(s); }
// Constructs a matcher that matches a string whose value is equal to s.
Matcher<::string>::Matcher(const char* s) { *this = Eq(::string(s)); }
#endif // GTEST_HAS_GLOBAL_STRING
#if GTEST_HAS_ABSL
// Constructs a matcher that matches a const absl::string_view& whose value is
// equal to s.
Matcher<const absl::string_view&>::Matcher(const std::string& s) {
*this = Eq(s); *this = Eq(s);
} }
// Constructs a matcher that matches a StringPiece whose value is equal to s. #if GTEST_HAS_GLOBAL_STRING
Matcher<StringPiece>::Matcher(const char* s) { // Constructs a matcher that matches a const absl::string_view& whose value is
*this = Eq(internal::string(s)); // equal to s.
Matcher<const absl::string_view&>::Matcher(const ::string& s) { *this = Eq(s); }
#endif // GTEST_HAS_GLOBAL_STRING
// Constructs a matcher that matches a const absl::string_view& whose value is
// equal to s.
Matcher<const absl::string_view&>::Matcher(const char* s) {
*this = Eq(std::string(s));
} }
// Constructs a matcher that matches a StringPiece whose value is equal to s. // Constructs a matcher that matches a const absl::string_view& whose value is
Matcher<StringPiece>::Matcher(StringPiece s) { // equal to s.
*this = Eq(s.ToString()); Matcher<const absl::string_view&>::Matcher(absl::string_view s) {
*this = Eq(std::string(s));
} }
#endif // GTEST_HAS_STRING_PIECE_
namespace internal { // Constructs a matcher that matches a absl::string_view whose value is equal to
// s.
Matcher<absl::string_view>::Matcher(const std::string& s) { *this = Eq(s); }
// Joins a vector of strings as if they are fields of a tuple; returns #if GTEST_HAS_GLOBAL_STRING
// the joined string. // Constructs a matcher that matches a absl::string_view whose value is equal to
GTEST_API_ string JoinAsTuple(const Strings& fields) { // s.
switch (fields.size()) { Matcher<absl::string_view>::Matcher(const ::string& s) { *this = Eq(s); }
case 0: #endif // GTEST_HAS_GLOBAL_STRING
return "";
case 1: // Constructs a matcher that matches a absl::string_view whose value is equal to
return fields[0]; // s.
default: Matcher<absl::string_view>::Matcher(const char* s) {
string result = "(" + fields[0]; *this = Eq(std::string(s));
for (size_t i = 1; i < fields.size(); i++) {
result += ", ";
result += fields[i];
}
result += ")";
return result;
}
} }
// Constructs a matcher that matches a absl::string_view whose value is equal to
// s.
Matcher<absl::string_view>::Matcher(absl::string_view s) {
*this = Eq(std::string(s));
}
#endif // GTEST_HAS_ABSL
namespace internal {
// Returns the description for a matcher defined using the MATCHER*() // Returns the description for a matcher defined using the MATCHER*()
// macro where the user-supplied description string is "", if // macro where the user-supplied description string is "", if
// 'negation' is false; otherwise returns the description of the // 'negation' is false; otherwise returns the description of the
// negation of the matcher. 'param_values' contains a list of strings // negation of the matcher. 'param_values' contains a list of strings
// that are the print-out of the matcher's parameters. // that are the print-out of the matcher's parameters.
GTEST_API_ string FormatMatcherDescription(bool negation, GTEST_API_ std::string FormatMatcherDescription(bool negation,
const char* matcher_name, const char* matcher_name,
const Strings& param_values) { const Strings& param_values) {
string result = ConvertIdentifierNameToWords(matcher_name); std::string result = ConvertIdentifierNameToWords(matcher_name);
if (param_values.size() >= 1) if (param_values.size() >= 1) result += " " + JoinAsTuple(param_values);
result += " " + JoinAsTuple(param_values);
return negation ? "not (" + result + ")" : result; return negation ? "not (" + result + ")" : result;
} }
...@@ -200,8 +234,7 @@ class MaxBipartiteMatchState { ...@@ -200,8 +234,7 @@ class MaxBipartiteMatchState {
explicit MaxBipartiteMatchState(const MatchMatrix& graph) explicit MaxBipartiteMatchState(const MatchMatrix& graph)
: graph_(&graph), : graph_(&graph),
left_(graph_->LhsSize(), kUnused), left_(graph_->LhsSize(), kUnused),
right_(graph_->RhsSize(), kUnused) { right_(graph_->RhsSize(), kUnused) {}
}
// Returns the edges of a maximal match, each in the form {left, right}. // Returns the edges of a maximal match, each in the form {left, right}.
ElementMatcherPairs Compute() { ElementMatcherPairs Compute() {
...@@ -258,10 +291,8 @@ class MaxBipartiteMatchState { ...@@ -258,10 +291,8 @@ class MaxBipartiteMatchState {
// //
bool TryAugment(size_t ilhs, ::std::vector<char>* seen) { bool TryAugment(size_t ilhs, ::std::vector<char>* seen) {
for (size_t irhs = 0; irhs < graph_->RhsSize(); ++irhs) { for (size_t irhs = 0; irhs < graph_->RhsSize(); ++irhs) {
if ((*seen)[irhs]) if ((*seen)[irhs]) continue;
continue; if (!graph_->HasEdge(ilhs, irhs)) continue;
if (!graph_->HasEdge(ilhs, irhs))
continue;
// There's an available edge from ilhs to irhs. // There's an available edge from ilhs to irhs.
(*seen)[irhs] = 1; (*seen)[irhs] = 1;
// Next a search is performed to determine whether // Next a search is performed to determine whether
...@@ -304,8 +335,7 @@ class MaxBipartiteMatchState { ...@@ -304,8 +335,7 @@ class MaxBipartiteMatchState {
const size_t MaxBipartiteMatchState::kUnused; const size_t MaxBipartiteMatchState::kUnused;
GTEST_API_ ElementMatcherPairs GTEST_API_ ElementMatcherPairs FindMaxBipartiteMatching(const MatchMatrix& g) {
FindMaxBipartiteMatching(const MatchMatrix& g) {
return MaxBipartiteMatchState(g).Compute(); return MaxBipartiteMatchState(g).Compute();
} }
...@@ -314,7 +344,7 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs, ...@@ -314,7 +344,7 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs,
typedef ElementMatcherPairs::const_iterator Iter; typedef ElementMatcherPairs::const_iterator Iter;
::std::ostream& os = *stream; ::std::ostream& os = *stream;
os << "{"; os << "{";
const char *sep = ""; const char* sep = "";
for (Iter it = pairs.begin(); it != pairs.end(); ++it) { for (Iter it = pairs.begin(); it != pairs.end(); ++it) {
os << sep << "\n (" os << sep << "\n ("
<< "element #" << it->first << ", " << "element #" << it->first << ", "
...@@ -324,38 +354,6 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs, ...@@ -324,38 +354,6 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs,
os << "\n}"; os << "\n}";
} }
// Tries to find a pairing, and explains the result.
GTEST_API_ bool FindPairing(const MatchMatrix& matrix,
MatchResultListener* listener) {
ElementMatcherPairs matches = FindMaxBipartiteMatching(matrix);
size_t max_flow = matches.size();
bool result = (max_flow == matrix.RhsSize());
if (!result) {
if (listener->IsInterested()) {
*listener << "where no permutation of the elements can "
"satisfy all matchers, and the closest match is "
<< max_flow << " of " << matrix.RhsSize()
<< " matchers with the pairings:\n";
LogElementMatcherPairVec(matches, listener->stream());
}
return false;
}
if (matches.size() > 1) {
if (listener->IsInterested()) {
const char *sep = "where:\n";
for (size_t mi = 0; mi < matches.size(); ++mi) {
*listener << sep << " - element #" << matches[mi].first
<< " is matched by matcher #" << matches[mi].second;
sep = ",\n";
}
}
}
return true;
}
bool MatchMatrix::NextGraph() { bool MatchMatrix::NextGraph() {
for (size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) { for (size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) {
for (size_t irhs = 0; irhs < RhsSize(); ++irhs) { for (size_t irhs = 0; irhs < RhsSize(); ++irhs) {
...@@ -381,7 +379,7 @@ void MatchMatrix::Randomize() { ...@@ -381,7 +379,7 @@ void MatchMatrix::Randomize() {
std::string MatchMatrix::DebugString() const { std::string MatchMatrix::DebugString() const {
::std::stringstream ss; ::std::stringstream ss;
const char *sep = ""; const char* sep = "";
for (size_t i = 0; i < LhsSize(); ++i) { for (size_t i = 0; i < LhsSize(); ++i) {
ss << sep; ss << sep;
for (size_t j = 0; j < RhsSize(); ++j) { for (size_t j = 0; j < RhsSize(); ++j) {
...@@ -394,44 +392,83 @@ std::string MatchMatrix::DebugString() const { ...@@ -394,44 +392,83 @@ std::string MatchMatrix::DebugString() const {
void UnorderedElementsAreMatcherImplBase::DescribeToImpl( void UnorderedElementsAreMatcherImplBase::DescribeToImpl(
::std::ostream* os) const { ::std::ostream* os) const {
if (matcher_describers_.empty()) { switch (match_flags()) {
*os << "is empty"; case UnorderedMatcherRequire::ExactMatch:
return; if (matcher_describers_.empty()) {
} *os << "is empty";
if (matcher_describers_.size() == 1) { return;
*os << "has " << Elements(1) << " and that element "; }
matcher_describers_[0]->DescribeTo(os); if (matcher_describers_.size() == 1) {
return; *os << "has " << Elements(1) << " and that element ";
matcher_describers_[0]->DescribeTo(os);
return;
}
*os << "has " << Elements(matcher_describers_.size())
<< " and there exists some permutation of elements such that:\n";
break;
case UnorderedMatcherRequire::Superset:
*os << "a surjection from elements to requirements exists such that:\n";
break;
case UnorderedMatcherRequire::Subset:
*os << "an injection from elements to requirements exists such that:\n";
break;
} }
*os << "has " << Elements(matcher_describers_.size())
<< " and there exists some permutation of elements such that:\n";
const char* sep = ""; const char* sep = "";
for (size_t i = 0; i != matcher_describers_.size(); ++i) { for (size_t i = 0; i != matcher_describers_.size(); ++i) {
*os << sep << " - element #" << i << " "; *os << sep;
if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
*os << " - element #" << i << " ";
} else {
*os << " - an element ";
}
matcher_describers_[i]->DescribeTo(os); matcher_describers_[i]->DescribeTo(os);
sep = ", and\n"; if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
sep = ", and\n";
} else {
sep = "\n";
}
} }
} }
void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl( void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl(
::std::ostream* os) const { ::std::ostream* os) const {
if (matcher_describers_.empty()) { switch (match_flags()) {
*os << "isn't empty"; case UnorderedMatcherRequire::ExactMatch:
return; if (matcher_describers_.empty()) {
} *os << "isn't empty";
if (matcher_describers_.size() == 1) { return;
*os << "doesn't have " << Elements(1) }
<< ", or has " << Elements(1) << " that "; if (matcher_describers_.size() == 1) {
matcher_describers_[0]->DescribeNegationTo(os); *os << "doesn't have " << Elements(1) << ", or has " << Elements(1)
return; << " that ";
matcher_describers_[0]->DescribeNegationTo(os);
return;
}
*os << "doesn't have " << Elements(matcher_describers_.size())
<< ", or there exists no permutation of elements such that:\n";
break;
case UnorderedMatcherRequire::Superset:
*os << "no surjection from elements to requirements exists such that:\n";
break;
case UnorderedMatcherRequire::Subset:
*os << "no injection from elements to requirements exists such that:\n";
break;
} }
*os << "doesn't have " << Elements(matcher_describers_.size())
<< ", or there exists no permutation of elements such that:\n";
const char* sep = ""; const char* sep = "";
for (size_t i = 0; i != matcher_describers_.size(); ++i) { for (size_t i = 0; i != matcher_describers_.size(); ++i) {
*os << sep << " - element #" << i << " "; *os << sep;
if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
*os << " - element #" << i << " ";
} else {
*os << " - an element ";
}
matcher_describers_[i]->DescribeTo(os); matcher_describers_[i]->DescribeTo(os);
sep = ", and\n"; if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
sep = ", and\n";
} else {
sep = "\n";
}
} }
} }
...@@ -440,10 +477,9 @@ void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl( ...@@ -440,10 +477,9 @@ void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl(
// and better error reporting. // and better error reporting.
// Returns false, writing an explanation to 'listener', if and only // Returns false, writing an explanation to 'listener', if and only
// if the success criteria are not met. // if the success criteria are not met.
bool UnorderedElementsAreMatcherImplBase:: bool UnorderedElementsAreMatcherImplBase::VerifyMatchMatrix(
VerifyAllElementsAndMatchersAreMatched( const ::std::vector<std::string>& element_printouts,
const ::std::vector<std::string>& element_printouts, const MatchMatrix& matrix, MatchResultListener* listener) const {
const MatchMatrix& matrix, MatchResultListener* listener) const {
bool result = true; bool result = true;
::std::vector<char> element_matched(matrix.LhsSize(), 0); ::std::vector<char> element_matched(matrix.LhsSize(), 0);
::std::vector<char> matcher_matched(matrix.RhsSize(), 0); ::std::vector<char> matcher_matched(matrix.RhsSize(), 0);
...@@ -456,12 +492,11 @@ bool UnorderedElementsAreMatcherImplBase:: ...@@ -456,12 +492,11 @@ bool UnorderedElementsAreMatcherImplBase::
} }
} }
{ if (match_flags() & UnorderedMatcherRequire::Superset) {
const char* sep = const char* sep =
"where the following matchers don't match any elements:\n"; "where the following matchers don't match any elements:\n";
for (size_t mi = 0; mi < matcher_matched.size(); ++mi) { for (size_t mi = 0; mi < matcher_matched.size(); ++mi) {
if (matcher_matched[mi]) if (matcher_matched[mi]) continue;
continue;
result = false; result = false;
if (listener->IsInterested()) { if (listener->IsInterested()) {
*listener << sep << "matcher #" << mi << ": "; *listener << sep << "matcher #" << mi << ": ";
...@@ -471,7 +506,7 @@ bool UnorderedElementsAreMatcherImplBase:: ...@@ -471,7 +506,7 @@ bool UnorderedElementsAreMatcherImplBase::
} }
} }
{ if (match_flags() & UnorderedMatcherRequire::Subset) {
const char* sep = const char* sep =
"where the following elements don't match any matchers:\n"; "where the following elements don't match any matchers:\n";
const char* outer_sep = ""; const char* outer_sep = "";
...@@ -479,8 +514,7 @@ bool UnorderedElementsAreMatcherImplBase:: ...@@ -479,8 +514,7 @@ bool UnorderedElementsAreMatcherImplBase::
outer_sep = "\nand "; outer_sep = "\nand ";
} }
for (size_t ei = 0; ei < element_matched.size(); ++ei) { for (size_t ei = 0; ei < element_matched.size(); ++ei) {
if (element_matched[ei]) if (element_matched[ei]) continue;
continue;
result = false; result = false;
if (listener->IsInterested()) { if (listener->IsInterested()) {
*listener << outer_sep << sep << "element #" << ei << ": " *listener << outer_sep << sep << "element #" << ei << ": "
...@@ -493,5 +527,46 @@ bool UnorderedElementsAreMatcherImplBase:: ...@@ -493,5 +527,46 @@ bool UnorderedElementsAreMatcherImplBase::
return result; return result;
} }
bool UnorderedElementsAreMatcherImplBase::FindPairing(
const MatchMatrix& matrix, MatchResultListener* listener) const {
ElementMatcherPairs matches = FindMaxBipartiteMatching(matrix);
size_t max_flow = matches.size();
if ((match_flags() & UnorderedMatcherRequire::Superset) &&
max_flow < matrix.RhsSize()) {
if (listener->IsInterested()) {
*listener << "where no permutation of the elements can satisfy all "
"matchers, and the closest match is "
<< max_flow << " of " << matrix.RhsSize()
<< " matchers with the pairings:\n";
LogElementMatcherPairVec(matches, listener->stream());
}
return false;
}
if ((match_flags() & UnorderedMatcherRequire::Subset) &&
max_flow < matrix.LhsSize()) {
if (listener->IsInterested()) {
*listener
<< "where not all elements can be matched, and the closest match is "
<< max_flow << " of " << matrix.RhsSize()
<< " matchers with the pairings:\n";
LogElementMatcherPairVec(matches, listener->stream());
}
return false;
}
if (matches.size() > 1) {
if (listener->IsInterested()) {
const char* sep = "where:\n";
for (size_t mi = 0; mi < matches.size(); ++mi) {
*listener << sep << " - element #" << matches[mi].first
<< " is matched by matcher #" << matches[mi].second;
sep = ",\n";
}
}
}
return true;
}
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Mock - a framework for writing C++ mock classes. // Google Mock - a framework for writing C++ mock classes.
// //
...@@ -41,6 +40,7 @@ ...@@ -41,6 +40,7 @@
#include <map> #include <map>
#include <set> #include <set>
#include <string> #include <string>
#include <vector>
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
...@@ -48,6 +48,15 @@ ...@@ -48,6 +48,15 @@
# include <unistd.h> // NOLINT # include <unistd.h> // NOLINT
#endif #endif
// Silence C4800 (C4800: 'int *const ': forcing value
// to bool 'true' or 'false') for MSVC 14,15
#ifdef _MSC_VER
#if _MSC_VER <= 1900
# pragma warning(push)
# pragma warning(disable:4800)
#endif
#endif
namespace testing { namespace testing {
namespace internal { namespace internal {
...@@ -99,12 +108,19 @@ void ExpectationBase::RetireAllPreRequisites() ...@@ -99,12 +108,19 @@ void ExpectationBase::RetireAllPreRequisites()
return; return;
} }
for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin(); ::std::vector<ExpectationBase*> expectations(1, this);
it != immediate_prerequisites_.end(); ++it) { while (!expectations.empty()) {
ExpectationBase* const prerequisite = it->expectation_base().get(); ExpectationBase* exp = expectations.back();
if (!prerequisite->is_retired()) { expectations.pop_back();
prerequisite->RetireAllPreRequisites();
prerequisite->Retire(); for (ExpectationSet::const_iterator it =
exp->immediate_prerequisites_.begin();
it != exp->immediate_prerequisites_.end(); ++it) {
ExpectationBase* next = it->expectation_base().get();
if (!next->is_retired()) {
next->Retire();
expectations.push_back(next);
}
} }
} }
} }
...@@ -114,11 +130,18 @@ void ExpectationBase::RetireAllPreRequisites() ...@@ -114,11 +130,18 @@ void ExpectationBase::RetireAllPreRequisites()
bool ExpectationBase::AllPrerequisitesAreSatisfied() const bool ExpectationBase::AllPrerequisitesAreSatisfied() const
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
g_gmock_mutex.AssertHeld(); g_gmock_mutex.AssertHeld();
for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin(); ::std::vector<const ExpectationBase*> expectations(1, this);
it != immediate_prerequisites_.end(); ++it) { while (!expectations.empty()) {
if (!(it->expectation_base()->IsSatisfied()) || const ExpectationBase* exp = expectations.back();
!(it->expectation_base()->AllPrerequisitesAreSatisfied())) expectations.pop_back();
return false;
for (ExpectationSet::const_iterator it =
exp->immediate_prerequisites_.begin();
it != exp->immediate_prerequisites_.end(); ++it) {
const ExpectationBase* next = it->expectation_base().get();
if (!next->IsSatisfied()) return false;
expectations.push_back(next);
}
} }
return true; return true;
} }
...@@ -127,19 +150,28 @@ bool ExpectationBase::AllPrerequisitesAreSatisfied() const ...@@ -127,19 +150,28 @@ bool ExpectationBase::AllPrerequisitesAreSatisfied() const
void ExpectationBase::FindUnsatisfiedPrerequisites(ExpectationSet* result) const void ExpectationBase::FindUnsatisfiedPrerequisites(ExpectationSet* result) const
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
g_gmock_mutex.AssertHeld(); g_gmock_mutex.AssertHeld();
for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin(); ::std::vector<const ExpectationBase*> expectations(1, this);
it != immediate_prerequisites_.end(); ++it) { while (!expectations.empty()) {
if (it->expectation_base()->IsSatisfied()) { const ExpectationBase* exp = expectations.back();
// If *it is satisfied and has a call count of 0, some of its expectations.pop_back();
// pre-requisites may not be satisfied yet.
if (it->expectation_base()->call_count_ == 0) { for (ExpectationSet::const_iterator it =
it->expectation_base()->FindUnsatisfiedPrerequisites(result); exp->immediate_prerequisites_.begin();
it != exp->immediate_prerequisites_.end(); ++it) {
const ExpectationBase* next = it->expectation_base().get();
if (next->IsSatisfied()) {
// If *it is satisfied and has a call count of 0, some of its
// pre-requisites may not be satisfied yet.
if (next->call_count_ == 0) {
expectations.push_back(next);
}
} else {
// Now that we know next is unsatisfied, we are not so interested
// in whether its pre-requisites are satisfied. Therefore we
// don't iterate into it here.
*result += *it;
} }
} else {
// Now that we know *it is unsatisfied, we are not so interested
// in whether its pre-requisites are satisfied. Therefore we
// don't recursively call FindUnsatisfiedPrerequisites() here.
*result += *it;
} }
} }
} }
...@@ -254,11 +286,13 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg) { ...@@ -254,11 +286,13 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg) {
case kWarn: case kWarn:
Log(kWarning, Log(kWarning,
msg + msg +
"\nNOTE: You can safely ignore the above warning unless this " "\nNOTE: You can safely ignore the above warning unless this "
"call should not happen. Do not suppress it by blindly adding " "call should not happen. Do not suppress it by blindly adding "
"an EXPECT_CALL() if you don't mean to enforce the call. " "an EXPECT_CALL() if you don't mean to enforce the call. "
"See https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md#" "See "
"knowing-when-to-expect for details.\n", "https://github.com/google/googletest/blob/master/googlemock/"
"docs/CookBook.md#"
"knowing-when-to-expect for details.\n",
stack_frames_to_skip); stack_frames_to_skip);
break; break;
default: // FAIL default: // FAIL
...@@ -334,9 +368,10 @@ const char* UntypedFunctionMockerBase::Name() const ...@@ -334,9 +368,10 @@ const char* UntypedFunctionMockerBase::Name() const
// Calculates the result of invoking this mock function with the given // Calculates the result of invoking this mock function with the given
// arguments, prints it, and returns it. The caller is responsible // arguments, prints it, and returns it. The caller is responsible
// for deleting the result. // for deleting the result.
UntypedActionResultHolderBase* UntypedActionResultHolderBase* UntypedFunctionMockerBase::UntypedInvokeWith(
UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) void* const untyped_args) GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { // See the definition of untyped_expectations_ for why access to it
// is unprotected here.
if (untyped_expectations_.size() == 0) { if (untyped_expectations_.size() == 0) {
// No expectation is set on this mock method - we have an // No expectation is set on this mock method - we have an
// uninteresting call. // uninteresting call.
...@@ -355,16 +390,19 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) ...@@ -355,16 +390,19 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args)
// If the user allows this uninteresting call, we print it // If the user allows this uninteresting call, we print it
// only when they want informational messages. // only when they want informational messages.
reaction == kAllow ? LogIsVisible(kInfo) : reaction == kAllow ? LogIsVisible(kInfo) :
// If the user wants this to be a warning, we print it only // If the user wants this to be a warning, we print
// when they want to see warnings. // it only when they want to see warnings.
reaction == kWarn ? LogIsVisible(kWarning) : reaction == kWarn
// Otherwise, the user wants this to be an error, and we ? LogIsVisible(kWarning)
// should always print detailed information in the error. :
true; // Otherwise, the user wants this to be an error, and we
// should always print detailed information in the error.
true;
if (!need_to_report_uninteresting_call) { if (!need_to_report_uninteresting_call) {
// Perform the action without printing the call information. // Perform the action without printing the call information.
return this->UntypedPerformDefaultAction(untyped_args, "Function call: " + std::string(Name())); return this->UntypedPerformDefaultAction(
untyped_args, "Function call: " + std::string(Name()));
} }
// Warns about the uninteresting call. // Warns about the uninteresting call.
...@@ -446,6 +484,8 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) ...@@ -446,6 +484,8 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args)
// Returns an Expectation object that references and co-owns exp, // Returns an Expectation object that references and co-owns exp,
// which must be an expectation on this mock function. // which must be an expectation on this mock function.
Expectation UntypedFunctionMockerBase::GetHandleOf(ExpectationBase* exp) { Expectation UntypedFunctionMockerBase::GetHandleOf(ExpectationBase* exp) {
// See the definition of untyped_expectations_ for why access to it
// is unprotected here.
for (UntypedExpectations::const_iterator it = for (UntypedExpectations::const_iterator it =
untyped_expectations_.begin(); untyped_expectations_.begin();
it != untyped_expectations_.end(); ++it) { it != untyped_expectations_.end(); ++it) {
...@@ -566,7 +606,7 @@ class MockObjectRegistry { ...@@ -566,7 +606,7 @@ class MockObjectRegistry {
if (it->second.leakable) // The user said it's fine to leak this object. if (it->second.leakable) // The user said it's fine to leak this object.
continue; continue;
// TODO(wan@google.com): Print the type of the leaked object. // FIXME: Print the type of the leaked object.
// This can help the user identify the leaked object. // This can help the user identify the leaked object.
std::cout << "\n"; std::cout << "\n";
const MockObjectState& state = it->second; const MockObjectState& state = it->second;
...@@ -582,9 +622,15 @@ class MockObjectRegistry { ...@@ -582,9 +622,15 @@ class MockObjectRegistry {
leaked_count++; leaked_count++;
} }
if (leaked_count > 0) { if (leaked_count > 0) {
std::cout << "\nERROR: " << leaked_count std::cout << "\nERROR: " << leaked_count << " leaked mock "
<< " leaked mock " << (leaked_count == 1 ? "object" : "objects") << (leaked_count == 1 ? "object" : "objects")
<< " found at program exit.\n"; << " found at program exit. Expectations on a mock object is "
"verified when the object is destructed. Leaking a mock "
"means that its expectations aren't verified, which is "
"usually a test bug. If you really intend to leak a mock, "
"you can suppress this error using "
"testing::Mock::AllowLeak(mock_object), or you may use a "
"fake or stub instead of a mock.\n";
std::cout.flush(); std::cout.flush();
::std::cerr.flush(); ::std::cerr.flush();
// RUN_ALL_TESTS() has already returned when this destructor is // RUN_ALL_TESTS() has already returned when this destructor is
...@@ -736,7 +782,7 @@ void Mock::RegisterUseByOnCallOrExpectCall(const void* mock_obj, ...@@ -736,7 +782,7 @@ void Mock::RegisterUseByOnCallOrExpectCall(const void* mock_obj,
const TestInfo* const test_info = const TestInfo* const test_info =
UnitTest::GetInstance()->current_test_info(); UnitTest::GetInstance()->current_test_info();
if (test_info != NULL) { if (test_info != NULL) {
// TODO(wan@google.com): record the test case name when the // FIXME: record the test case name when the
// ON_CALL or EXPECT_CALL is invoked from SetUpTestCase() or // ON_CALL or EXPECT_CALL is invoked from SetUpTestCase() or
// TearDownTestCase(). // TearDownTestCase().
state.first_used_test_case = test_info->test_case_name(); state.first_used_test_case = test_info->test_case_name();
...@@ -828,3 +874,9 @@ InSequence::~InSequence() { ...@@ -828,3 +874,9 @@ InSequence::~InSequence() {
} }
} // namespace testing } // namespace testing
#ifdef _MSC_VER
#if _MSC_VER <= 1900
# pragma warning(pop)
#endif
#endif
...@@ -26,15 +26,14 @@ ...@@ -26,15 +26,14 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "gmock/internal/gmock-port.h" #include "gmock/internal/gmock-port.h"
namespace testing { namespace testing {
// TODO(wan@google.com): support using environment variables to // FIXME: support using environment variables to
// control the flag values, like what Google Test does. // control the flag values, like what Google Test does.
GMOCK_DEFINE_bool_(catch_leaked_mocks, true, GMOCK_DEFINE_bool_(catch_leaked_mocks, true,
...@@ -136,8 +135,8 @@ static bool ParseGoogleMockIntFlag(const char* str, const char* flag, ...@@ -136,8 +135,8 @@ static bool ParseGoogleMockIntFlag(const char* str, const char* flag,
if (value_str == NULL) return false; if (value_str == NULL) return false;
// Sets *value to the value of the flag. // Sets *value to the value of the flag.
*value = atoi(value_str); return ParseInt32(Message() << "The value of flag --" << flag,
return true; value_str, value);
} }
// The internal implementation of InitGoogleMock(). // The internal implementation of InitGoogleMock().
......
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
#include <iostream> #include <iostream>
#include "gmock/gmock.h" #include "gmock/gmock.h"
...@@ -37,7 +36,8 @@ ...@@ -37,7 +36,8 @@
// causes a link error when _tmain is defined in a static library and UNICODE // causes a link error when _tmain is defined in a static library and UNICODE
// is enabled. For this reason instead of _tmain, main function is used on // is enabled. For this reason instead of _tmain, main function is used on
// Windows. See the following link to track the current status of this bug: // Windows. See the following link to track the current status of this bug:
// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=394464 // NOLINT // https://web.archive.org/web/20170912203238/connect.microsoft.com/VisualStudio/feedback/details/394464/wmain-link-error-in-the-static-library
// // NOLINT
#if GTEST_OS_WINDOWS_MOBILE #if GTEST_OS_WINDOWS_MOBILE
# include <tchar.h> // NOLINT # include <tchar.h> // NOLINT
......
# Copyright 2017 Google Inc. # Copyright 2017 Google Inc.
# All Rights Reserved. # All Rights Reserved.
# #
# #
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# #
# Author: misterg@google.com (Gennadiy Civil) # Author: misterg@google.com (Gennadiy Civil)
# #
# Bazel Build for Google C++ Testing Framework(Google Test)-googlemock # Bazel Build for Google C++ Testing Framework(Google Test)-googlemock
licenses(["notice"]) licenses(["notice"])
...@@ -45,10 +45,79 @@ cc_test( ...@@ -45,10 +45,79 @@ cc_test(
], ],
), ),
linkopts = select({ linkopts = select({
"//:win": [], "//:windows": [],
"//:windows_msvc": [],
"//conditions:default": [ "//conditions:default": [
"-pthread", "-pthread",
], ],
}), }),
deps = ["//:gtest"], deps = ["//:gtest"],
) )
# Py tests
py_library(
name = "gmock_test_utils",
testonly = 1,
srcs = ["gmock_test_utils.py"],
)
cc_binary(
name = "gmock_leak_test_",
testonly = 1,
srcs = ["gmock_leak_test_.cc"],
deps = [
"//:gtest_main",
],
)
py_test(
name = "gmock_leak_test",
size = "medium",
srcs = ["gmock_leak_test.py"],
data = [
":gmock_leak_test_",
":gmock_test_utils",
],
)
cc_test(
name = "gmock_link_test",
size = "small",
srcs = [
"gmock_link2_test.cc",
"gmock_link_test.cc",
"gmock_link_test.h",
],
deps = [
"//:gtest_main",
],
)
cc_binary(
name = "gmock_output_test_",
srcs = ["gmock_output_test_.cc"],
deps = [
"//:gtest",
],
)
py_test(
name = "gmock_output_test",
size = "medium",
srcs = ["gmock_output_test.py"],
data = [
":gmock_output_test_",
":gmock_output_test_golden.txt",
],
deps = [":gmock_test_utils"],
)
cc_test(
name = "gmock_test",
size = "small",
srcs = ["gmock_test.cc"],
deps = [
"//:gtest_main",
],
)
...@@ -26,13 +26,21 @@ ...@@ -26,13 +26,21 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Mock - a framework for writing C++ mock classes. // Google Mock - a framework for writing C++ mock classes.
// //
// This file tests the built-in actions. // This file tests the built-in actions.
// Silence C4800 (C4800: 'int *const ': forcing value
// to bool 'true' or 'false') for MSVC 14,15
#ifdef _MSC_VER
#if _MSC_VER <= 1900
# pragma warning(push)
# pragma warning(disable:4800)
#endif
#endif
#include "gmock/gmock-actions.h" #include "gmock/gmock-actions.h"
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
...@@ -65,6 +73,7 @@ using testing::ReturnRef; ...@@ -65,6 +73,7 @@ using testing::ReturnRef;
using testing::ReturnRefOfCopy; using testing::ReturnRefOfCopy;
using testing::SetArgPointee; using testing::SetArgPointee;
using testing::SetArgumentPointee; using testing::SetArgumentPointee;
using testing::Unused;
using testing::_; using testing::_;
using testing::get; using testing::get;
using testing::internal::BuiltInDefaultValue; using testing::internal::BuiltInDefaultValue;
...@@ -78,10 +87,6 @@ using testing::tuple_element; ...@@ -78,10 +87,6 @@ using testing::tuple_element;
using testing::SetErrnoAndReturn; using testing::SetErrnoAndReturn;
#endif #endif
#if GTEST_HAS_PROTOBUF_
using testing::internal::TestMessage;
#endif // GTEST_HAS_PROTOBUF_
// Tests that BuiltInDefaultValue<T*>::Get() returns NULL. // Tests that BuiltInDefaultValue<T*>::Get() returns NULL.
TEST(BuiltInDefaultValueTest, IsNullForPointerTypes) { TEST(BuiltInDefaultValueTest, IsNullForPointerTypes) {
EXPECT_TRUE(BuiltInDefaultValue<int*>::Get() == NULL); EXPECT_TRUE(BuiltInDefaultValue<int*>::Get() == NULL);
...@@ -107,7 +112,11 @@ TEST(BuiltInDefaultValueTest, IsZeroForNumericTypes) { ...@@ -107,7 +112,11 @@ TEST(BuiltInDefaultValueTest, IsZeroForNumericTypes) {
EXPECT_EQ(0, BuiltInDefaultValue<signed wchar_t>::Get()); EXPECT_EQ(0, BuiltInDefaultValue<signed wchar_t>::Get());
#endif #endif
#if GMOCK_WCHAR_T_IS_NATIVE_ #if GMOCK_WCHAR_T_IS_NATIVE_
#if !defined(__WCHAR_UNSIGNED__)
EXPECT_EQ(0, BuiltInDefaultValue<wchar_t>::Get()); EXPECT_EQ(0, BuiltInDefaultValue<wchar_t>::Get());
#else
EXPECT_EQ(0U, BuiltInDefaultValue<wchar_t>::Get());
#endif
#endif #endif
EXPECT_EQ(0U, BuiltInDefaultValue<unsigned short>::Get()); // NOLINT EXPECT_EQ(0U, BuiltInDefaultValue<unsigned short>::Get()); // NOLINT
EXPECT_EQ(0, BuiltInDefaultValue<signed short>::Get()); // NOLINT EXPECT_EQ(0, BuiltInDefaultValue<signed short>::Get()); // NOLINT
...@@ -214,7 +223,7 @@ class MyNonDefaultConstructible { ...@@ -214,7 +223,7 @@ class MyNonDefaultConstructible {
int value_; int value_;
}; };
#if GTEST_HAS_STD_TYPE_TRAITS_ #if GTEST_LANG_CXX11
TEST(BuiltInDefaultValueTest, ExistsForDefaultConstructibleType) { TEST(BuiltInDefaultValueTest, ExistsForDefaultConstructibleType) {
EXPECT_TRUE(BuiltInDefaultValue<MyDefaultConstructible>::Exists()); EXPECT_TRUE(BuiltInDefaultValue<MyDefaultConstructible>::Exists());
...@@ -224,7 +233,7 @@ TEST(BuiltInDefaultValueTest, IsDefaultConstructedForDefaultConstructibleType) { ...@@ -224,7 +233,7 @@ TEST(BuiltInDefaultValueTest, IsDefaultConstructedForDefaultConstructibleType) {
EXPECT_EQ(42, BuiltInDefaultValue<MyDefaultConstructible>::Get().value()); EXPECT_EQ(42, BuiltInDefaultValue<MyDefaultConstructible>::Get().value());
} }
#endif // GTEST_HAS_STD_TYPE_TRAITS_ #endif // GTEST_LANG_CXX11
TEST(BuiltInDefaultValueTest, DoesNotExistForNonDefaultConstructibleType) { TEST(BuiltInDefaultValueTest, DoesNotExistForNonDefaultConstructibleType) {
EXPECT_FALSE(BuiltInDefaultValue<MyNonDefaultConstructible>::Exists()); EXPECT_FALSE(BuiltInDefaultValue<MyNonDefaultConstructible>::Exists());
...@@ -700,6 +709,9 @@ class MockClass { ...@@ -700,6 +709,9 @@ class MockClass {
MOCK_METHOD0(MakeUnique, std::unique_ptr<int>()); MOCK_METHOD0(MakeUnique, std::unique_ptr<int>());
MOCK_METHOD0(MakeUniqueBase, std::unique_ptr<Base>()); MOCK_METHOD0(MakeUniqueBase, std::unique_ptr<Base>());
MOCK_METHOD0(MakeVectorUnique, std::vector<std::unique_ptr<int>>()); MOCK_METHOD0(MakeVectorUnique, std::vector<std::unique_ptr<int>>());
MOCK_METHOD1(TakeUnique, int(std::unique_ptr<int>));
MOCK_METHOD2(TakeUnique,
int(const std::unique_ptr<int>&, std::unique_ptr<int>));
#endif #endif
private: private:
...@@ -878,105 +890,6 @@ TEST(SetArgPointeeTest, AcceptsWideCharPointer) { ...@@ -878,105 +890,6 @@ TEST(SetArgPointeeTest, AcceptsWideCharPointer) {
# endif # endif
} }
#if GTEST_HAS_PROTOBUF_
// Tests that SetArgPointee<N>(proto_buffer) sets the v1 protobuf
// variable pointed to by the N-th (0-based) argument to proto_buffer.
TEST(SetArgPointeeTest, SetsTheNthPointeeOfProtoBufferType) {
TestMessage* const msg = new TestMessage;
msg->set_member("yes");
TestMessage orig_msg;
orig_msg.CopyFrom(*msg);
Action<void(bool, TestMessage*)> a = SetArgPointee<1>(*msg);
// SetArgPointee<N>(proto_buffer) makes a copy of proto_buffer
// s.t. the action works even when the original proto_buffer has
// died. We ensure this behavior by deleting msg before using the
// action.
delete msg;
TestMessage dest;
EXPECT_FALSE(orig_msg.Equals(dest));
a.Perform(make_tuple(true, &dest));
EXPECT_TRUE(orig_msg.Equals(dest));
}
// Tests that SetArgPointee<N>(proto_buffer) sets the
// ::ProtocolMessage variable pointed to by the N-th (0-based)
// argument to proto_buffer.
TEST(SetArgPointeeTest, SetsTheNthPointeeOfProtoBufferBaseType) {
TestMessage* const msg = new TestMessage;
msg->set_member("yes");
TestMessage orig_msg;
orig_msg.CopyFrom(*msg);
Action<void(bool, ::ProtocolMessage*)> a = SetArgPointee<1>(*msg);
// SetArgPointee<N>(proto_buffer) makes a copy of proto_buffer
// s.t. the action works even when the original proto_buffer has
// died. We ensure this behavior by deleting msg before using the
// action.
delete msg;
TestMessage dest;
::ProtocolMessage* const dest_base = &dest;
EXPECT_FALSE(orig_msg.Equals(dest));
a.Perform(make_tuple(true, dest_base));
EXPECT_TRUE(orig_msg.Equals(dest));
}
// Tests that SetArgPointee<N>(proto2_buffer) sets the v2
// protobuf variable pointed to by the N-th (0-based) argument to
// proto2_buffer.
TEST(SetArgPointeeTest, SetsTheNthPointeeOfProto2BufferType) {
using testing::internal::FooMessage;
FooMessage* const msg = new FooMessage;
msg->set_int_field(2);
msg->set_string_field("hi");
FooMessage orig_msg;
orig_msg.CopyFrom(*msg);
Action<void(bool, FooMessage*)> a = SetArgPointee<1>(*msg);
// SetArgPointee<N>(proto2_buffer) makes a copy of
// proto2_buffer s.t. the action works even when the original
// proto2_buffer has died. We ensure this behavior by deleting msg
// before using the action.
delete msg;
FooMessage dest;
dest.set_int_field(0);
a.Perform(make_tuple(true, &dest));
EXPECT_EQ(2, dest.int_field());
EXPECT_EQ("hi", dest.string_field());
}
// Tests that SetArgPointee<N>(proto2_buffer) sets the
// proto2::Message variable pointed to by the N-th (0-based) argument
// to proto2_buffer.
TEST(SetArgPointeeTest, SetsTheNthPointeeOfProto2BufferBaseType) {
using testing::internal::FooMessage;
FooMessage* const msg = new FooMessage;
msg->set_int_field(2);
msg->set_string_field("hi");
FooMessage orig_msg;
orig_msg.CopyFrom(*msg);
Action<void(bool, ::proto2::Message*)> a = SetArgPointee<1>(*msg);
// SetArgPointee<N>(proto2_buffer) makes a copy of
// proto2_buffer s.t. the action works even when the original
// proto2_buffer has died. We ensure this behavior by deleting msg
// before using the action.
delete msg;
FooMessage dest;
dest.set_int_field(0);
::proto2::Message* const dest_base = &dest;
a.Perform(make_tuple(true, dest_base));
EXPECT_EQ(2, dest.int_field());
EXPECT_EQ("hi", dest.string_field());
}
#endif // GTEST_HAS_PROTOBUF_
// Tests that SetArgumentPointee<N>(v) sets the variable pointed to by // Tests that SetArgumentPointee<N>(v) sets the variable pointed to by
// the N-th (0-based) argument to v. // the N-th (0-based) argument to v.
TEST(SetArgumentPointeeTest, SetsTheNthPointee) { TEST(SetArgumentPointeeTest, SetsTheNthPointee) {
...@@ -997,105 +910,6 @@ TEST(SetArgumentPointeeTest, SetsTheNthPointee) { ...@@ -997,105 +910,6 @@ TEST(SetArgumentPointeeTest, SetsTheNthPointee) {
EXPECT_EQ('a', ch); EXPECT_EQ('a', ch);
} }
#if GTEST_HAS_PROTOBUF_
// Tests that SetArgumentPointee<N>(proto_buffer) sets the v1 protobuf
// variable pointed to by the N-th (0-based) argument to proto_buffer.
TEST(SetArgumentPointeeTest, SetsTheNthPointeeOfProtoBufferType) {
TestMessage* const msg = new TestMessage;
msg->set_member("yes");
TestMessage orig_msg;
orig_msg.CopyFrom(*msg);
Action<void(bool, TestMessage*)> a = SetArgumentPointee<1>(*msg);
// SetArgumentPointee<N>(proto_buffer) makes a copy of proto_buffer
// s.t. the action works even when the original proto_buffer has
// died. We ensure this behavior by deleting msg before using the
// action.
delete msg;
TestMessage dest;
EXPECT_FALSE(orig_msg.Equals(dest));
a.Perform(make_tuple(true, &dest));
EXPECT_TRUE(orig_msg.Equals(dest));
}
// Tests that SetArgumentPointee<N>(proto_buffer) sets the
// ::ProtocolMessage variable pointed to by the N-th (0-based)
// argument to proto_buffer.
TEST(SetArgumentPointeeTest, SetsTheNthPointeeOfProtoBufferBaseType) {
TestMessage* const msg = new TestMessage;
msg->set_member("yes");
TestMessage orig_msg;
orig_msg.CopyFrom(*msg);
Action<void(bool, ::ProtocolMessage*)> a = SetArgumentPointee<1>(*msg);
// SetArgumentPointee<N>(proto_buffer) makes a copy of proto_buffer
// s.t. the action works even when the original proto_buffer has
// died. We ensure this behavior by deleting msg before using the
// action.
delete msg;
TestMessage dest;
::ProtocolMessage* const dest_base = &dest;
EXPECT_FALSE(orig_msg.Equals(dest));
a.Perform(make_tuple(true, dest_base));
EXPECT_TRUE(orig_msg.Equals(dest));
}
// Tests that SetArgumentPointee<N>(proto2_buffer) sets the v2
// protobuf variable pointed to by the N-th (0-based) argument to
// proto2_buffer.
TEST(SetArgumentPointeeTest, SetsTheNthPointeeOfProto2BufferType) {
using testing::internal::FooMessage;
FooMessage* const msg = new FooMessage;
msg->set_int_field(2);
msg->set_string_field("hi");
FooMessage orig_msg;
orig_msg.CopyFrom(*msg);
Action<void(bool, FooMessage*)> a = SetArgumentPointee<1>(*msg);
// SetArgumentPointee<N>(proto2_buffer) makes a copy of
// proto2_buffer s.t. the action works even when the original
// proto2_buffer has died. We ensure this behavior by deleting msg
// before using the action.
delete msg;
FooMessage dest;
dest.set_int_field(0);
a.Perform(make_tuple(true, &dest));
EXPECT_EQ(2, dest.int_field());
EXPECT_EQ("hi", dest.string_field());
}
// Tests that SetArgumentPointee<N>(proto2_buffer) sets the
// proto2::Message variable pointed to by the N-th (0-based) argument
// to proto2_buffer.
TEST(SetArgumentPointeeTest, SetsTheNthPointeeOfProto2BufferBaseType) {
using testing::internal::FooMessage;
FooMessage* const msg = new FooMessage;
msg->set_int_field(2);
msg->set_string_field("hi");
FooMessage orig_msg;
orig_msg.CopyFrom(*msg);
Action<void(bool, ::proto2::Message*)> a = SetArgumentPointee<1>(*msg);
// SetArgumentPointee<N>(proto2_buffer) makes a copy of
// proto2_buffer s.t. the action works even when the original
// proto2_buffer has died. We ensure this behavior by deleting msg
// before using the action.
delete msg;
FooMessage dest;
dest.set_int_field(0);
::proto2::Message* const dest_base = &dest;
a.Perform(make_tuple(true, dest_base));
EXPECT_EQ(2, dest.int_field());
EXPECT_EQ("hi", dest.string_field());
}
#endif // GTEST_HAS_PROTOBUF_
// Sample functions and functors for testing Invoke() and etc. // Sample functions and functors for testing Invoke() and etc.
int Nullary() { return 1; } int Nullary() { return 1; }
...@@ -1406,6 +1220,153 @@ TEST(MockMethodTest, CanReturnMoveOnlyValue_Invoke) { ...@@ -1406,6 +1220,153 @@ TEST(MockMethodTest, CanReturnMoveOnlyValue_Invoke) {
EXPECT_EQ(7, *vresult[0]); EXPECT_EQ(7, *vresult[0]);
} }
TEST(MockMethodTest, CanTakeMoveOnlyValue) {
MockClass mock;
auto make = [](int i) { return std::unique_ptr<int>(new int(i)); };
EXPECT_CALL(mock, TakeUnique(_)).WillRepeatedly([](std::unique_ptr<int> i) {
return *i;
});
// DoAll() does not compile, since it would move from its arguments twice.
// EXPECT_CALL(mock, TakeUnique(_, _))
// .WillRepeatedly(DoAll(Invoke([](std::unique_ptr<int> j) {}),
// Return(1)));
EXPECT_CALL(mock, TakeUnique(testing::Pointee(7)))
.WillOnce(Return(-7))
.RetiresOnSaturation();
EXPECT_CALL(mock, TakeUnique(testing::IsNull()))
.WillOnce(Return(-1))
.RetiresOnSaturation();
EXPECT_EQ(5, mock.TakeUnique(make(5)));
EXPECT_EQ(-7, mock.TakeUnique(make(7)));
EXPECT_EQ(7, mock.TakeUnique(make(7)));
EXPECT_EQ(7, mock.TakeUnique(make(7)));
EXPECT_EQ(-1, mock.TakeUnique({}));
// Some arguments are moved, some passed by reference.
auto lvalue = make(6);
EXPECT_CALL(mock, TakeUnique(_, _))
.WillOnce([](const std::unique_ptr<int>& i, std::unique_ptr<int> j) {
return *i * *j;
});
EXPECT_EQ(42, mock.TakeUnique(lvalue, make(7)));
// The unique_ptr can be saved by the action.
std::unique_ptr<int> saved;
EXPECT_CALL(mock, TakeUnique(_)).WillOnce([&saved](std::unique_ptr<int> i) {
saved = std::move(i);
return 0;
});
EXPECT_EQ(0, mock.TakeUnique(make(42)));
EXPECT_EQ(42, *saved);
}
#endif // GTEST_HAS_STD_UNIQUE_PTR_ #endif // GTEST_HAS_STD_UNIQUE_PTR_
#if GTEST_LANG_CXX11
// Tests for std::function based action.
int Add(int val, int& ref, int* ptr) { // NOLINT
int result = val + ref + *ptr;
ref = 42;
*ptr = 43;
return result;
}
int Deref(std::unique_ptr<int> ptr) { return *ptr; }
struct Double {
template <typename T>
T operator()(T t) { return 2 * t; }
};
std::unique_ptr<int> UniqueInt(int i) {
return std::unique_ptr<int>(new int(i));
}
TEST(FunctorActionTest, ActionFromFunction) {
Action<int(int, int&, int*)> a = &Add;
int x = 1, y = 2, z = 3;
EXPECT_EQ(6, a.Perform(std::forward_as_tuple(x, y, &z)));
EXPECT_EQ(42, y);
EXPECT_EQ(43, z);
Action<int(std::unique_ptr<int>)> a1 = &Deref;
EXPECT_EQ(7, a1.Perform(std::make_tuple(UniqueInt(7))));
}
TEST(FunctorActionTest, ActionFromLambda) {
Action<int(bool, int)> a1 = [](bool b, int i) { return b ? i : 0; };
EXPECT_EQ(5, a1.Perform(make_tuple(true, 5)));
EXPECT_EQ(0, a1.Perform(make_tuple(false, 5)));
std::unique_ptr<int> saved;
Action<void(std::unique_ptr<int>)> a2 = [&saved](std::unique_ptr<int> p) {
saved = std::move(p);
};
a2.Perform(make_tuple(UniqueInt(5)));
EXPECT_EQ(5, *saved);
}
TEST(FunctorActionTest, PolymorphicFunctor) {
Action<int(int)> ai = Double();
EXPECT_EQ(2, ai.Perform(make_tuple(1)));
Action<double(double)> ad = Double(); // Double? Double double!
EXPECT_EQ(3.0, ad.Perform(make_tuple(1.5)));
}
TEST(FunctorActionTest, TypeConversion) {
// Numeric promotions are allowed.
const Action<bool(int)> a1 = [](int i) { return i > 1; };
const Action<int(bool)> a2 = Action<int(bool)>(a1);
EXPECT_EQ(1, a1.Perform(make_tuple(42)));
EXPECT_EQ(0, a2.Perform(make_tuple(42)));
// Implicit constructors are allowed.
const Action<bool(std::string)> s1 = [](std::string s) { return !s.empty(); };
const Action<int(const char*)> s2 = Action<int(const char*)>(s1);
EXPECT_EQ(0, s2.Perform(make_tuple("")));
EXPECT_EQ(1, s2.Perform(make_tuple("hello")));
// Also between the lambda and the action itself.
const Action<bool(std::string)> x = [](Unused) { return 42; };
EXPECT_TRUE(x.Perform(make_tuple("hello")));
}
TEST(FunctorActionTest, UnusedArguments) {
// Verify that users can ignore uninteresting arguments.
Action<int(int, double y, double z)> a =
[](int i, Unused, Unused) { return 2 * i; };
tuple<int, double, double> dummy = make_tuple(3, 7.3, 9.44);
EXPECT_EQ(6, a.Perform(dummy));
}
// Test that basic built-in actions work with move-only arguments.
// FIXME: Currently, almost all ActionInterface-based actions will not
// work, even if they only try to use other, copyable arguments. Implement them
// if necessary (but note that DoAll cannot work on non-copyable types anyway -
// so maybe it's better to make users use lambdas instead.
TEST(MoveOnlyArgumentsTest, ReturningActions) {
Action<int(std::unique_ptr<int>)> a = Return(1);
EXPECT_EQ(1, a.Perform(make_tuple(nullptr)));
a = testing::WithoutArgs([]() { return 7; });
EXPECT_EQ(7, a.Perform(make_tuple(nullptr)));
Action<void(std::unique_ptr<int>, int*)> a2 = testing::SetArgPointee<1>(3);
int x = 0;
a2.Perform(make_tuple(nullptr, &x));
EXPECT_EQ(x, 3);
}
#endif // GTEST_LANG_CXX11
} // Unnamed namespace } // Unnamed namespace
#ifdef _MSC_VER
#if _MSC_VER == 1900
# pragma warning(pop)
#endif
#endif
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Mock - a framework for writing C++ mock classes. // Google Mock - a framework for writing C++ mock classes.
// //
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment