Upgrade gtest to r267 and gmock to r173.
This is step1 into removing the boost + tr1 dependency in windows. It also includes a hack to avoid brining in tr1/functional on gcc, which will move us closer to enabling -fno-rtti. This CL has passed the try servers. I've also tried compiling gmock, gmock_main, base, base_unittests, and webcore modules in vs2008 express editions. Review URL: http://codereview.chromium.org/140003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18923 0039d316-1c4b-4281-b951-d872f2087c98
Esse commit está contido em:
+1
-1
@@ -16,7 +16,7 @@ deps = {
|
||||
"http://open-vcdiff.googlecode.com/svn/trunk@26",
|
||||
|
||||
"src/testing/gtest":
|
||||
"http://googletest.googlecode.com/svn/trunk@243",
|
||||
"http://googletest.googlecode.com/svn/trunk@267",
|
||||
|
||||
"src/third_party/WebKit":
|
||||
"/trunk/deps/third_party/WebKit@15773",
|
||||
|
||||
+13
-32
@@ -1,7 +1,7 @@
|
||||
We include a snapshot of gmock from http://googlemock.googlecode.com/svn/trunk
|
||||
with chromium.patch applied.
|
||||
|
||||
Current revision: 157
|
||||
Current revision: 173
|
||||
|
||||
|
||||
-- HOW TO USE --
|
||||
@@ -21,38 +21,19 @@ In particular, the "For Dummies" guide is a good place to start. The
|
||||
|
||||
-- RECREATING PACKAGE --
|
||||
|
||||
Gmock requires tr1 tuple. However, Visual Studio 2005 does not include
|
||||
tr1 tuple, so a version of boost tuple was added into the third_party
|
||||
tree for chromium. Our version of gmock has been patched to search for
|
||||
this version of tuple inside our source tree.
|
||||
Starting with r173, gmock began distributing a pared down version of tr1 tuple
|
||||
that can be used on compilers without TR1. This means that we will no longer
|
||||
need TR1 or boost on windows.
|
||||
|
||||
chromium.patch modifies gmock/include/gmock/internal/gmock-port.h so that
|
||||
for _MSC_VER < 1500 (anything newer than Visual Studio 2008), boost tuple
|
||||
is loaded from boost/tr1/tr1/tuple.
|
||||
Recreating this package is now just exporting the wanted revision.
|
||||
Example:
|
||||
|
||||
To recreate this install, do the following:
|
||||
svn export --ignore-externals \
|
||||
http://googlemock.googlecode.com/svn/trunk/ gmock
|
||||
|
||||
*1) Checkout a copy from svn trunk using --ignore-externals to avoid
|
||||
getting an extra copy of gtest. Use the following command:
|
||||
svn export --ignore-externals \
|
||||
http://googlemock.googlecode.com/svn/trunk/ gmock
|
||||
2) Patch it with chromium.patch.
|
||||
When checking out a copy from svn, --ignore-externals should be used to avoid
|
||||
getting an extra copy of gtest.
|
||||
|
||||
* Pass -r [revision number] to svn export if you want a specific revision.
|
||||
The current revision of the source is listed at the top of the README.
|
||||
|
||||
|
||||
-- ALTERNATIVES TO PATCHING --
|
||||
|
||||
The patching of gmock to use boost in VS2005 was settled upon as the lowest
|
||||
impact solution for getting gmock working in VS2005. Patching gmock trades
|
||||
making some assumptions regarding the internal implementations of gmock
|
||||
and boost for a simple, easy to underatnd, implementation that provides
|
||||
relatively good insulation for the rest of the build from the boost dependency.
|
||||
|
||||
Alternate soltuions are:
|
||||
1) Drop support for VS2005 -- too heavy-handed.
|
||||
2) Add a "tuple" file parallel to gmock-port.h -- still makes assumptions
|
||||
about boost's structure.
|
||||
3) Add boost/tr1/tr1 into the include path -- dirties the include path for
|
||||
all dependencies.
|
||||
This command will grab the head of trunk. Optionally, -r [revision number] to
|
||||
can be passed to svn export if you want a specific revision. The current
|
||||
revision of the source is listed at the top of the README.
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
diff -ru gmock.orig/include/gmock/internal/gmock-port.h gmock/include/gmock/internal/gmock-port.h
|
||||
--- gmock.orig/include/gmock/internal/gmock-port.h 2009-05-22 23:58:41.000000000 -0700
|
||||
+++ gmock/include/gmock/internal/gmock-port.h 2009-05-23 00:49:01.000000000 -0700
|
||||
@@ -54,9 +54,14 @@
|
||||
// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header. This does
|
||||
// not conform to the TR1 spec, which requires the header to be <tuple>.
|
||||
#include <tr1/tuple>
|
||||
+#elif defined(_MSC_VER) && _MSC_VER < 1500
|
||||
+// For Visual Studio older than 2008, we redirect directly to boost tuple
|
||||
+// searching from boost's root. This is to avoid extra dirtying of the
|
||||
+// compiler include paths.
|
||||
+#include "boost/tr1/tr1/tuple"
|
||||
#else
|
||||
-// If the compiler is not GCC 4.0+, we assume the user is using a
|
||||
-// spec-conforming TR1 implementation.
|
||||
+// If the compiler is neither GCC 4.0+, nor Visual Studio 2008, we assume the
|
||||
+// user is using a spec-conforming TR1 implementation.
|
||||
#include <tuple>
|
||||
#endif // __GNUC__
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
'gtest.gyp:gtest',
|
||||
],
|
||||
'sources': [
|
||||
# Sources based on files in r173 of gmock.
|
||||
'gmock/include/gmock/gmock-actions.h',
|
||||
'gmock/include/gmock/gmock-cardinalities.h',
|
||||
'gmock/include/gmock/gmock-generated-actions.h',
|
||||
|
||||
@@ -135,6 +135,28 @@ check_PROGRAMS += test/gmock_test
|
||||
test_gmock_test_SOURCES = test/gmock_test.cc
|
||||
test_gmock_test_LDADD = $(GTEST_LIBS) lib/libgmock_main.la
|
||||
|
||||
# A sanity test for verifying that Google Mock works when RTTI is
|
||||
# disabled. We pick gmock-spec-builders_test.cc as it exercises all
|
||||
# components of Google Mock.
|
||||
TESTS += test/gmock_no_rtti_test
|
||||
check_PROGRAMS += test/gmock_no_rtti_test
|
||||
test_gmock_no_rtti_test_SOURCES = test/gmock-spec-builders_test.cc \
|
||||
src/gmock-all.cc
|
||||
test_gmock_no_rtti_test_CXXFLAGS = $(AM_CXXFLAGS) -fno-rtti -DGTEST_HAS_RTTI=0
|
||||
test_gmock_no_rtti_test_LDADD = $(GTEST_LIBS)
|
||||
|
||||
# A sanity test for verifying that Google Mock works with Google
|
||||
# Test's TR1 tuple implementation. We pick
|
||||
# gmock-spec-builders_test.cc as it exercises all components of Google
|
||||
# Mock.
|
||||
TESTS += test/gmock_use_own_tuple_test
|
||||
check_PROGRAMS += test/gmock_use_own_tuple_test
|
||||
test_gmock_use_own_tuple_test_SOURCES = test/gmock-spec-builders_test.cc \
|
||||
src/gmock-all.cc
|
||||
test_gmock_use_own_tuple_test_CXXFLAGS = \
|
||||
$(AM_CXXFLAGS) -DGTEST_USE_OWN_TR1_TUPLE=1
|
||||
test_gmock_use_own_tuple_test_LDADD = $(GTEST_LIBS)
|
||||
|
||||
# The following tests depend on the presence of a Python installation and are
|
||||
# keyed off of it. We only add them to the TESTS variable when a Python
|
||||
# interpreter is available. TODO(chandlerc@google.com): While we currently only
|
||||
|
||||
+32
-49
@@ -40,7 +40,7 @@ testing framework for writing tests. It works with Google Test
|
||||
(http://code.google.com/p/googletest/) out of the box. You can use
|
||||
either the copy of Google Test that comes with Google Mock, or a
|
||||
compatible version you already have. This version of Google Mock
|
||||
requires Google Test 1.3.0.
|
||||
requires Google Test 1.4.0.
|
||||
|
||||
You can also easily configure Google Mock to work with another testing
|
||||
framework of your choice; although it will still need Google Test as
|
||||
@@ -57,8 +57,7 @@ package (as described below):
|
||||
* GNU-compatible Make or "gmake"
|
||||
* POSIX-standard shell
|
||||
* POSIX(-2) Regular Expressions (regex.h)
|
||||
* gcc 4.0 or newer, or gcc 3.4 or newer with the tr1 tuple library
|
||||
(from Boost or other vendors).
|
||||
* gcc 3.4 or newer.
|
||||
|
||||
Furthermore, if you are building Google Mock from a VCS Checkout (also
|
||||
described below), there are further requirements:
|
||||
@@ -69,12 +68,6 @@ described below), there are further requirements:
|
||||
|
||||
### Windows Requirements ###
|
||||
* Microsoft Visual C++ 8.0 SP1 or newer
|
||||
* An implementation of the tr1 tuple C++ library (You can get it for
|
||||
free from http://www.boost.org/. We have verified that version
|
||||
1.36.0 works. One caveat is this implementation exposes a bug in
|
||||
Visual C++'s <type_info> header when exceptions are disabled.
|
||||
Therefore your project must enable exceptions for this
|
||||
configuration to work.)
|
||||
|
||||
### Mac OS X Requirements ###
|
||||
* Mac OS X 10.4 Tiger or newer
|
||||
@@ -141,6 +134,32 @@ which contains all of the source code. Here are some examples in Linux:
|
||||
tar -xvjf gmock-X.Y.Z.tar.bz2
|
||||
unzip gmock-X.Y.Z.zip
|
||||
|
||||
Choosing a TR1 Tuple Library
|
||||
----------------------------
|
||||
Google Mock uses the C++ Technical Report 1 (TR1) tuple library
|
||||
heavily. Unfortunately TR1 tuple is not yet widely available with all
|
||||
compilers. The good news is that Google Test 1.4.0+ implements a
|
||||
subset of TR1 tuple that's enough for Google Mock's need. Google Mock
|
||||
will automatically use that implementation when the compiler doesn't
|
||||
provide TR1 tuple.
|
||||
|
||||
Usually you don't need to care about which tuple library Google Test
|
||||
and Google Mock use. However, if your project already uses TR1 tuple,
|
||||
you need to tell Google Test and Google Mock to use the same TR1 tuple
|
||||
library the rest of your project uses (this requirement is new in
|
||||
Google Test 1.4.0 and Google Mock 1.2.0, so you may need to take care
|
||||
of it when upgrading from an earlier version), or the two tuple
|
||||
implementations will clash. To do that, add
|
||||
|
||||
-DGTEST_USE_OWN_TR1_TUPLE=0
|
||||
|
||||
to the compiler flags while compiling Google Test, Google Mock, and
|
||||
your tests.
|
||||
|
||||
If you want to use Boost's TR1 tuple library with Google Mock, please
|
||||
refer to the Boost website (http://www.boost.org/) for how to obtain
|
||||
it and set it up.
|
||||
|
||||
Building the Source
|
||||
-------------------
|
||||
### Linux and Mac OS X (without Xcode) ###
|
||||
@@ -236,46 +255,15 @@ separately.
|
||||
|
||||
### Windows ###
|
||||
The msvc/ directory contains VC++ 2005 projects for building Google
|
||||
Mock and selected tests. In order to build Google Mock you must have
|
||||
an implementation of TR1 tuple. One library that provides such
|
||||
implementation is Boost. If you choose to use Boost, download it from
|
||||
www.boost.org and install it on your system. Note that Boost TR1 tuple
|
||||
is a header-only library, so the installation only involves unpacking
|
||||
it to a suitable location - you don't need to compile it or download a
|
||||
pre-compiled Boost binary.
|
||||
|
||||
Since Boost is quite large, you may prefer to only install the files
|
||||
actually needed by Google Mock. If so, you can download TR1 tuple
|
||||
without other parts of Boost from
|
||||
http://code.google.com/p/googlemock/downloads/list.
|
||||
|
||||
After that you have two options: either set up Boost globally or
|
||||
modify the Google Mock project to point to your copy of Boost. The
|
||||
former will let all your tests use the same Boost library while the
|
||||
latter will allow each of your projects use its own copy. You can also
|
||||
use a hybrid solution: your project settings will override the
|
||||
system-wide one.
|
||||
|
||||
For example, if you unpacked boost v1.36.0 into C:\boost:
|
||||
To set up Boost such that all projects can use it:
|
||||
* Assuming you are using the Visual Studio 2005 IDE, select Tools |
|
||||
Options | Projects And Solutions | VC++ Directories.
|
||||
* In the "Show directories for" drop-down select Include Files. Add
|
||||
C:\boost\boost_1_36_0\boost\tr1\tr1 and C:\boost\boost_1_36_0 to the
|
||||
list of directories.
|
||||
|
||||
To configure your project to point to that version of Boost, replace
|
||||
the value of the BoostDir user macro with C:\boost\boost_1_36_0 in the
|
||||
msvc/gmock_config.vsprops file. You can use any text editor to edit
|
||||
that file.
|
||||
Mock and selected tests.
|
||||
|
||||
If you want to use a version of Google Test other then the one bundled with
|
||||
Google Mock, change the value of the GTestDir macro in gmock_config.vsprop
|
||||
to point to the new location.
|
||||
|
||||
After configuring Boost, just open msvc/gmock.sln and build the library and
|
||||
tests. If you want to create your own project to use with Google Mock, you'll
|
||||
have to configure it to use the gmock_config propety sheet. For that:
|
||||
Open msvc/gmock.sln and build the library and tests. If you want to
|
||||
create your own project to use with Google Mock, you'll have to
|
||||
configure it to use the gmock_config propety sheet. For that:
|
||||
* Open the Property Manager window (View | Other Windows | Property Manager)
|
||||
* Right-click on your project and select "Add Existing Property Sheet..."
|
||||
* Navigate to gmock_config.vsprops and select it.
|
||||
@@ -320,11 +308,6 @@ something like the following will do:
|
||||
g++ -I. -I./include -I${GTEST_SRCDIR} -I${GTEST_SRCDIR}/include \
|
||||
path/to/your_test.cc libgmock.a -o your_test
|
||||
|
||||
On Windows, you'll also need to add the include path for the boost
|
||||
headers to the compiler command line. See
|
||||
http://www.boost.org/doc/libs/1_36_0/doc/html/boost_tr1/usage.html for
|
||||
how to do it.
|
||||
|
||||
Regenerating Source Files
|
||||
-------------------------
|
||||
Some of Google Mock's source files are generated from templates (not
|
||||
|
||||
@@ -80,7 +80,7 @@ AC_ARG_VAR([GTEST_VERSION],
|
||||
[The version of Google Test available.])
|
||||
HAVE_BUILT_GTEST="no"
|
||||
|
||||
GTEST_MIN_VERSION="1.2.1"
|
||||
GTEST_MIN_VERSION="1.3.0"
|
||||
|
||||
AS_IF([test "x${enable_external_gtest}" = "xyes"],
|
||||
[# Begin filling in variables as we are able.
|
||||
|
||||
@@ -45,12 +45,260 @@
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// The type of the i-th (0-based) field of Tuple.
|
||||
#define GMOCK_FIELD_TYPE_(Tuple, i) \
|
||||
typename ::std::tr1::tuple_element<i, Tuple>::type
|
||||
|
||||
// TupleFields<Tuple, k0, ..., kn> is for selecting fields from a
|
||||
// tuple of type Tuple. It has two members:
|
||||
//
|
||||
// type: a tuple type whose i-th field is the ki-th field of Tuple.
|
||||
// GetSelectedFields(t): returns fields k0, ..., and kn of t as a tuple.
|
||||
//
|
||||
// For example, in class TupleFields<tuple<bool, char, int>, 2, 0>, we have:
|
||||
//
|
||||
// type is tuple<int, bool>, and
|
||||
// GetSelectedFields(make_tuple(true, 'a', 42)) is (42, true).
|
||||
|
||||
template <class Tuple, int k0 = -1, int k1 = -1, int k2 = -1, int k3 = -1,
|
||||
int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, int k8 = -1,
|
||||
int k9 = -1>
|
||||
class TupleFields;
|
||||
|
||||
// This generic version is used when there are 10 selectors.
|
||||
template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6,
|
||||
int k7, int k8, int k9>
|
||||
class TupleFields {
|
||||
public:
|
||||
typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k7), GMOCK_FIELD_TYPE_(Tuple, k8),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k9)> type;
|
||||
static type GetSelectedFields(const Tuple& t) {
|
||||
using ::std::tr1::get;
|
||||
return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
|
||||
get<k5>(t), get<k6>(t), get<k7>(t), get<k8>(t), get<k9>(t));
|
||||
}
|
||||
};
|
||||
|
||||
// The following specialization is used for 0 ~ 9 selectors.
|
||||
|
||||
template <class Tuple>
|
||||
class TupleFields<Tuple, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
|
||||
public:
|
||||
typedef ::std::tr1::tuple<> type;
|
||||
static type GetSelectedFields(const Tuple& t) {
|
||||
using ::std::tr1::get;
|
||||
return type();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tuple, int k0>
|
||||
class TupleFields<Tuple, k0, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
|
||||
public:
|
||||
typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0)> type;
|
||||
static type GetSelectedFields(const Tuple& t) {
|
||||
using ::std::tr1::get;
|
||||
return type(get<k0>(t));
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tuple, int k0, int k1>
|
||||
class TupleFields<Tuple, k0, k1, -1, -1, -1, -1, -1, -1, -1, -1> {
|
||||
public:
|
||||
typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k1)> type;
|
||||
static type GetSelectedFields(const Tuple& t) {
|
||||
using ::std::tr1::get;
|
||||
return type(get<k0>(t), get<k1>(t));
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tuple, int k0, int k1, int k2>
|
||||
class TupleFields<Tuple, k0, k1, k2, -1, -1, -1, -1, -1, -1, -1> {
|
||||
public:
|
||||
typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2)> type;
|
||||
static type GetSelectedFields(const Tuple& t) {
|
||||
using ::std::tr1::get;
|
||||
return type(get<k0>(t), get<k1>(t), get<k2>(t));
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tuple, int k0, int k1, int k2, int k3>
|
||||
class TupleFields<Tuple, k0, k1, k2, k3, -1, -1, -1, -1, -1, -1> {
|
||||
public:
|
||||
typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k3)> type;
|
||||
static type GetSelectedFields(const Tuple& t) {
|
||||
using ::std::tr1::get;
|
||||
return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t));
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tuple, int k0, int k1, int k2, int k3, int k4>
|
||||
class TupleFields<Tuple, k0, k1, k2, k3, k4, -1, -1, -1, -1, -1> {
|
||||
public:
|
||||
typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4)> type;
|
||||
static type GetSelectedFields(const Tuple& t) {
|
||||
using ::std::tr1::get;
|
||||
return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t));
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5>
|
||||
class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, -1, -1, -1, -1> {
|
||||
public:
|
||||
typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k5)> type;
|
||||
static type GetSelectedFields(const Tuple& t) {
|
||||
using ::std::tr1::get;
|
||||
return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
|
||||
get<k5>(t));
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6>
|
||||
class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, -1, -1, -1> {
|
||||
public:
|
||||
typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6)> type;
|
||||
static type GetSelectedFields(const Tuple& t) {
|
||||
using ::std::tr1::get;
|
||||
return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
|
||||
get<k5>(t), get<k6>(t));
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6,
|
||||
int k7>
|
||||
class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, k7, -1, -1> {
|
||||
public:
|
||||
typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k7)> type;
|
||||
static type GetSelectedFields(const Tuple& t) {
|
||||
using ::std::tr1::get;
|
||||
return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
|
||||
get<k5>(t), get<k6>(t), get<k7>(t));
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6,
|
||||
int k7, int k8>
|
||||
class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, k7, k8, -1> {
|
||||
public:
|
||||
typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6),
|
||||
GMOCK_FIELD_TYPE_(Tuple, k7), GMOCK_FIELD_TYPE_(Tuple, k8)> type;
|
||||
static type GetSelectedFields(const Tuple& t) {
|
||||
using ::std::tr1::get;
|
||||
return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
|
||||
get<k5>(t), get<k6>(t), get<k7>(t), get<k8>(t));
|
||||
}
|
||||
};
|
||||
|
||||
#undef GMOCK_FIELD_TYPE_
|
||||
|
||||
// Implements the Args() matcher.
|
||||
template <class ArgsTuple, int k0 = -1, int k1 = -1, int k2 = -1, int k3 = -1,
|
||||
int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, int k8 = -1,
|
||||
int k9 = -1>
|
||||
class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
|
||||
public:
|
||||
// ArgsTuple may have top-level const or reference modifiers.
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(ArgsTuple)) RawArgsTuple;
|
||||
typedef typename internal::TupleFields<RawArgsTuple, k0, k1, k2, k3, k4, k5,
|
||||
k6, k7, k8, k9>::type SelectedArgs;
|
||||
typedef Matcher<const SelectedArgs&> MonomorphicInnerMatcher;
|
||||
|
||||
template <typename InnerMatcher>
|
||||
explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher)
|
||||
: inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {}
|
||||
|
||||
virtual bool Matches(ArgsTuple args) const {
|
||||
return inner_matcher_.Matches(GetSelectedArgs(args));
|
||||
}
|
||||
|
||||
virtual void DescribeTo(::std::ostream* os) const {
|
||||
PrintIndices(os);
|
||||
inner_matcher_.DescribeTo(os);
|
||||
}
|
||||
|
||||
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||
PrintIndices(os);
|
||||
inner_matcher_.DescribeNegationTo(os);
|
||||
}
|
||||
|
||||
virtual void ExplainMatchResultTo(ArgsTuple args,
|
||||
::std::ostream* os) const {
|
||||
inner_matcher_.ExplainMatchResultTo(GetSelectedArgs(args), os);
|
||||
}
|
||||
|
||||
private:
|
||||
static SelectedArgs GetSelectedArgs(ArgsTuple args) {
|
||||
return TupleFields<RawArgsTuple, k0, k1, k2, k3, k4, k5, k6, k7, k8,
|
||||
k9>::GetSelectedFields(args);
|
||||
}
|
||||
|
||||
// Prints the indices of the selected fields.
|
||||
static void PrintIndices(::std::ostream* os) {
|
||||
*os << "are a tuple whose fields (";
|
||||
const int indices[10] = { k0, k1, k2, k3, k4, k5, k6, k7, k8, k9 };
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (indices[i] < 0)
|
||||
break;
|
||||
|
||||
if (i >= 1)
|
||||
*os << ", ";
|
||||
|
||||
*os << "#" << indices[i];
|
||||
}
|
||||
*os << ") ";
|
||||
}
|
||||
|
||||
const MonomorphicInnerMatcher inner_matcher_;
|
||||
};
|
||||
|
||||
template <class InnerMatcher, int k0 = -1, int k1 = -1, int k2 = -1,
|
||||
int k3 = -1, int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1,
|
||||
int k8 = -1, int k9 = -1>
|
||||
class ArgsMatcher {
|
||||
public:
|
||||
explicit ArgsMatcher(const InnerMatcher& inner_matcher)
|
||||
: inner_matcher_(inner_matcher) {}
|
||||
|
||||
template <typename ArgsTuple>
|
||||
operator Matcher<ArgsTuple>() const {
|
||||
return MakeMatcher(new ArgsMatcherImpl<ArgsTuple, k0, k1, k2, k3, k4, k5,
|
||||
k6, k7, k8, k9>(inner_matcher_));
|
||||
}
|
||||
|
||||
const InnerMatcher inner_matcher_;
|
||||
};
|
||||
|
||||
// Implements ElementsAre() and ElementsAreArray().
|
||||
template <typename Container>
|
||||
class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
||||
public:
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef internal::StlContainerView<RawContainer> View;
|
||||
typedef typename View::type StlContainer;
|
||||
typedef typename View::const_reference StlContainerReference;
|
||||
typedef typename StlContainer::value_type Element;
|
||||
|
||||
// Constructs the matcher from a sequence of element values or
|
||||
// element matchers.
|
||||
@@ -65,12 +313,13 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
||||
|
||||
// Returns true iff 'container' matches.
|
||||
virtual bool Matches(Container container) const {
|
||||
if (container.size() != count())
|
||||
StlContainerReference stl_container = View::ConstReference(container);
|
||||
if (stl_container.size() != count())
|
||||
return false;
|
||||
|
||||
typename RawContainer::const_iterator container_iter = container.begin();
|
||||
for (size_t i = 0; i != count(); ++container_iter, ++i) {
|
||||
if (!matchers_[i].Matches(*container_iter))
|
||||
typename StlContainer::const_iterator it = stl_container.begin();
|
||||
for (size_t i = 0; i != count(); ++it, ++i) {
|
||||
if (!matchers_[i].Matches(*it))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -116,15 +365,16 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
||||
// Explains why 'container' matches, or doesn't match, this matcher.
|
||||
virtual void ExplainMatchResultTo(Container container,
|
||||
::std::ostream* os) const {
|
||||
StlContainerReference stl_container = View::ConstReference(container);
|
||||
if (Matches(container)) {
|
||||
// We need to explain why *each* element matches (the obvious
|
||||
// ones can be skipped).
|
||||
|
||||
bool reason_printed = false;
|
||||
typename RawContainer::const_iterator container_iter = container.begin();
|
||||
for (size_t i = 0; i != count(); ++container_iter, ++i) {
|
||||
typename StlContainer::const_iterator it = stl_container.begin();
|
||||
for (size_t i = 0; i != count(); ++it, ++i) {
|
||||
::std::stringstream ss;
|
||||
matchers_[i].ExplainMatchResultTo(*container_iter, &ss);
|
||||
matchers_[i].ExplainMatchResultTo(*it, &ss);
|
||||
|
||||
const string s = ss.str();
|
||||
if (!s.empty()) {
|
||||
@@ -137,7 +387,7 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
||||
}
|
||||
} else {
|
||||
// We need to explain why the container doesn't match.
|
||||
const size_t actual_count = container.size();
|
||||
const size_t actual_count = stl_container.size();
|
||||
if (actual_count != count()) {
|
||||
// The element count doesn't match. If the container is
|
||||
// empty, there's no need to explain anything as Google Mock
|
||||
@@ -152,16 +402,16 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
||||
// The container has the right size but at least one element
|
||||
// doesn't match expectation. We need to find this element and
|
||||
// explain why it doesn't match.
|
||||
typename RawContainer::const_iterator container_iter = container.begin();
|
||||
for (size_t i = 0; i != count(); ++container_iter, ++i) {
|
||||
if (matchers_[i].Matches(*container_iter)) {
|
||||
typename StlContainer::const_iterator it = stl_container.begin();
|
||||
for (size_t i = 0; i != count(); ++it, ++i) {
|
||||
if (matchers_[i].Matches(*it)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
*os << "element " << i << " doesn't match";
|
||||
|
||||
::std::stringstream ss;
|
||||
matchers_[i].ExplainMatchResultTo(*container_iter, &ss);
|
||||
matchers_[i].ExplainMatchResultTo(*it, &ss);
|
||||
const string s = ss.str();
|
||||
if (!s.empty()) {
|
||||
*os << " (" << s << ")";
|
||||
@@ -190,7 +440,8 @@ class ElementsAreMatcher0 {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
const Matcher<const Element&>* const matchers = NULL;
|
||||
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 0));
|
||||
@@ -206,7 +457,8 @@ class ElementsAreMatcher1 {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
const Matcher<const Element&> matchers[] = {
|
||||
MatcherCast<const Element&>(e1_),
|
||||
@@ -228,7 +480,8 @@ class ElementsAreMatcher2 {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
const Matcher<const Element&> matchers[] = {
|
||||
MatcherCast<const Element&>(e1_),
|
||||
@@ -253,7 +506,8 @@ class ElementsAreMatcher3 {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
const Matcher<const Element&> matchers[] = {
|
||||
MatcherCast<const Element&>(e1_),
|
||||
@@ -280,7 +534,8 @@ class ElementsAreMatcher4 {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
const Matcher<const Element&> matchers[] = {
|
||||
MatcherCast<const Element&>(e1_),
|
||||
@@ -309,7 +564,8 @@ class ElementsAreMatcher5 {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
const Matcher<const Element&> matchers[] = {
|
||||
MatcherCast<const Element&>(e1_),
|
||||
@@ -342,7 +598,8 @@ class ElementsAreMatcher6 {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
const Matcher<const Element&> matchers[] = {
|
||||
MatcherCast<const Element&>(e1_),
|
||||
@@ -377,7 +634,8 @@ class ElementsAreMatcher7 {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
const Matcher<const Element&> matchers[] = {
|
||||
MatcherCast<const Element&>(e1_),
|
||||
@@ -414,7 +672,8 @@ class ElementsAreMatcher8 {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
const Matcher<const Element&> matchers[] = {
|
||||
MatcherCast<const Element&>(e1_),
|
||||
@@ -454,7 +713,8 @@ class ElementsAreMatcher9 {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
const Matcher<const Element&> matchers[] = {
|
||||
MatcherCast<const Element&>(e1_),
|
||||
@@ -496,7 +756,8 @@ class ElementsAreMatcher10 {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
const Matcher<const Element&> matchers[] = {
|
||||
MatcherCast<const Element&>(e1_),
|
||||
@@ -538,7 +799,8 @@ class ElementsAreArrayMatcher {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
return MakeMatcher(new ElementsAreMatcherImpl<Container>(first_, count_));
|
||||
}
|
||||
@@ -550,6 +812,84 @@ class ElementsAreArrayMatcher {
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
|
||||
// fields of it matches a_matcher. C++ doesn't support default
|
||||
// arguments for function templates, so we have to overload it.
|
||||
template <typename InnerMatcher>
|
||||
inline internal::ArgsMatcher<InnerMatcher>
|
||||
Args(const InnerMatcher& matcher) {
|
||||
return internal::ArgsMatcher<InnerMatcher>(matcher);
|
||||
}
|
||||
|
||||
template <int k1, typename InnerMatcher>
|
||||
inline internal::ArgsMatcher<InnerMatcher, k1>
|
||||
Args(const InnerMatcher& matcher) {
|
||||
return internal::ArgsMatcher<InnerMatcher, k1>(matcher);
|
||||
}
|
||||
|
||||
template <int k1, int k2, typename InnerMatcher>
|
||||
inline internal::ArgsMatcher<InnerMatcher, k1, k2>
|
||||
Args(const InnerMatcher& matcher) {
|
||||
return internal::ArgsMatcher<InnerMatcher, k1, k2>(matcher);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, typename InnerMatcher>
|
||||
inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3>
|
||||
Args(const InnerMatcher& matcher) {
|
||||
return internal::ArgsMatcher<InnerMatcher, k1, k2, k3>(matcher);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, int k4, typename InnerMatcher>
|
||||
inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4>
|
||||
Args(const InnerMatcher& matcher) {
|
||||
return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4>(matcher);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, int k4, int k5, typename InnerMatcher>
|
||||
inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5>
|
||||
Args(const InnerMatcher& matcher) {
|
||||
return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5>(matcher);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, int k4, int k5, int k6, typename InnerMatcher>
|
||||
inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6>
|
||||
Args(const InnerMatcher& matcher) {
|
||||
return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6>(matcher);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, int k4, int k5, int k6, int k7,
|
||||
typename InnerMatcher>
|
||||
inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7>
|
||||
Args(const InnerMatcher& matcher) {
|
||||
return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6,
|
||||
k7>(matcher);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
|
||||
typename InnerMatcher>
|
||||
inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8>
|
||||
Args(const InnerMatcher& matcher) {
|
||||
return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7,
|
||||
k8>(matcher);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
|
||||
int k9, typename InnerMatcher>
|
||||
inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8, k9>
|
||||
Args(const InnerMatcher& matcher) {
|
||||
return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8,
|
||||
k9>(matcher);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
|
||||
int k9, int k10, typename InnerMatcher>
|
||||
inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8, k9,
|
||||
k10>
|
||||
Args(const InnerMatcher& matcher) {
|
||||
return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8,
|
||||
k9, k10>(matcher);
|
||||
}
|
||||
|
||||
// ElementsAre(e0, e1, ..., e_n) matches an STL-style container with
|
||||
// (n + 1) elements, where the i-th element in the container must
|
||||
// match the i-th argument in the list. Each argument of
|
||||
@@ -1573,45 +1913,4 @@ string FormatMatcherDescription(
|
||||
p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>::\
|
||||
gmock_Impl<arg_type>::Matches(arg_type arg) const
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// Returns true iff element is in the STL-style container.
|
||||
template <typename Container, typename Element>
|
||||
inline bool Contains(const Container& container, const Element& element) {
|
||||
return ::std::find(container.begin(), container.end(), element) !=
|
||||
container.end();
|
||||
}
|
||||
|
||||
// Returns true iff element is in the C-style array.
|
||||
template <typename ArrayElement, size_t N, typename Element>
|
||||
inline bool Contains(const ArrayElement (&array)[N], const Element& element) {
|
||||
return ::std::find(array, array + N, element) != array + N;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Matches an STL-style container or a C-style array that contains the given
|
||||
// element.
|
||||
//
|
||||
// Examples:
|
||||
// ::std::set<int> page_ids;
|
||||
// page_ids.insert(3);
|
||||
// page_ids.insert(1);
|
||||
// EXPECT_THAT(page_ids, Contains(1));
|
||||
// EXPECT_THAT(page_ids, Contains(3.0));
|
||||
// EXPECT_THAT(page_ids, Not(Contains(4)));
|
||||
//
|
||||
// ::std::map<int, size_t> page_lengths;
|
||||
// page_lengths[1] = 100;
|
||||
// EXPECT_THAT(map_int, Contains(::std::pair<const int, size_t>(1, 100)));
|
||||
//
|
||||
// const char* user_ids[] = { "joe", "mike", "tom" };
|
||||
// EXPECT_THAT(user_ids, Contains(::std::string("tom")));
|
||||
MATCHER_P(Contains, element, "") {
|
||||
return internal::Contains(arg, element);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||
|
||||
@@ -3,6 +3,7 @@ $$ This is a Pump source file. Please use Pump to convert it to
|
||||
$$ gmock-generated-variadic-actions.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.
|
||||
//
|
||||
@@ -48,12 +49,139 @@ $var n = 10 $$ The maximum arity we support.
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
$range i 0..n-1
|
||||
|
||||
// The type of the i-th (0-based) field of Tuple.
|
||||
#define GMOCK_FIELD_TYPE_(Tuple, i) \
|
||||
typename ::std::tr1::tuple_element<i, Tuple>::type
|
||||
|
||||
// TupleFields<Tuple, k0, ..., kn> is for selecting fields from a
|
||||
// tuple of type Tuple. It has two members:
|
||||
//
|
||||
// type: a tuple type whose i-th field is the ki-th field of Tuple.
|
||||
// GetSelectedFields(t): returns fields k0, ..., and kn of t as a tuple.
|
||||
//
|
||||
// For example, in class TupleFields<tuple<bool, char, int>, 2, 0>, we have:
|
||||
//
|
||||
// type is tuple<int, bool>, and
|
||||
// GetSelectedFields(make_tuple(true, 'a', 42)) is (42, true).
|
||||
|
||||
template <class Tuple$for i [[, int k$i = -1]]>
|
||||
class TupleFields;
|
||||
|
||||
// This generic version is used when there are $n selectors.
|
||||
template <class Tuple$for i [[, int k$i]]>
|
||||
class TupleFields {
|
||||
public:
|
||||
typedef ::std::tr1::tuple<$for i, [[GMOCK_FIELD_TYPE_(Tuple, k$i)]]> type;
|
||||
static type GetSelectedFields(const Tuple& t) {
|
||||
using ::std::tr1::get;
|
||||
return type($for i, [[get<k$i>(t)]]);
|
||||
}
|
||||
};
|
||||
|
||||
// The following specialization is used for 0 ~ $(n-1) selectors.
|
||||
|
||||
$for i [[
|
||||
$$ }}}
|
||||
$range j 0..i-1
|
||||
$range k 0..n-1
|
||||
|
||||
template <class Tuple$for j [[, int k$j]]>
|
||||
class TupleFields<Tuple, $for k, [[$if k < i [[k$k]] $else [[-1]]]]> {
|
||||
public:
|
||||
typedef ::std::tr1::tuple<$for j, [[GMOCK_FIELD_TYPE_(Tuple, k$j)]]> type;
|
||||
static type GetSelectedFields(const Tuple& t) {
|
||||
using ::std::tr1::get;
|
||||
return type($for j, [[get<k$j>(t)]]);
|
||||
}
|
||||
};
|
||||
|
||||
]]
|
||||
|
||||
#undef GMOCK_FIELD_TYPE_
|
||||
|
||||
// Implements the Args() matcher.
|
||||
|
||||
$var ks = [[$for i, [[k$i]]]]
|
||||
template <class ArgsTuple$for i [[, int k$i = -1]]>
|
||||
class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
|
||||
public:
|
||||
// ArgsTuple may have top-level const or reference modifiers.
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(ArgsTuple)) RawArgsTuple;
|
||||
typedef typename internal::TupleFields<RawArgsTuple, $ks>::type SelectedArgs;
|
||||
typedef Matcher<const SelectedArgs&> MonomorphicInnerMatcher;
|
||||
|
||||
template <typename InnerMatcher>
|
||||
explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher)
|
||||
: inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {}
|
||||
|
||||
virtual bool Matches(ArgsTuple args) const {
|
||||
return inner_matcher_.Matches(GetSelectedArgs(args));
|
||||
}
|
||||
|
||||
virtual void DescribeTo(::std::ostream* os) const {
|
||||
PrintIndices(os);
|
||||
inner_matcher_.DescribeTo(os);
|
||||
}
|
||||
|
||||
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||
PrintIndices(os);
|
||||
inner_matcher_.DescribeNegationTo(os);
|
||||
}
|
||||
|
||||
virtual void ExplainMatchResultTo(ArgsTuple args,
|
||||
::std::ostream* os) const {
|
||||
inner_matcher_.ExplainMatchResultTo(GetSelectedArgs(args), os);
|
||||
}
|
||||
|
||||
private:
|
||||
static SelectedArgs GetSelectedArgs(ArgsTuple args) {
|
||||
return TupleFields<RawArgsTuple, $ks>::GetSelectedFields(args);
|
||||
}
|
||||
|
||||
// Prints the indices of the selected fields.
|
||||
static void PrintIndices(::std::ostream* os) {
|
||||
*os << "are a tuple whose fields (";
|
||||
const int indices[$n] = { $ks };
|
||||
for (int i = 0; i < $n; i++) {
|
||||
if (indices[i] < 0)
|
||||
break;
|
||||
|
||||
if (i >= 1)
|
||||
*os << ", ";
|
||||
|
||||
*os << "#" << indices[i];
|
||||
}
|
||||
*os << ") ";
|
||||
}
|
||||
|
||||
const MonomorphicInnerMatcher inner_matcher_;
|
||||
};
|
||||
|
||||
template <class InnerMatcher$for i [[, int k$i = -1]]>
|
||||
class ArgsMatcher {
|
||||
public:
|
||||
explicit ArgsMatcher(const InnerMatcher& inner_matcher)
|
||||
: inner_matcher_(inner_matcher) {}
|
||||
|
||||
template <typename ArgsTuple>
|
||||
operator Matcher<ArgsTuple>() const {
|
||||
return MakeMatcher(new ArgsMatcherImpl<ArgsTuple, $ks>(inner_matcher_));
|
||||
}
|
||||
|
||||
const InnerMatcher inner_matcher_;
|
||||
};
|
||||
|
||||
// Implements ElementsAre() and ElementsAreArray().
|
||||
template <typename Container>
|
||||
class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
||||
public:
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef internal::StlContainerView<RawContainer> View;
|
||||
typedef typename View::type StlContainer;
|
||||
typedef typename View::const_reference StlContainerReference;
|
||||
typedef typename StlContainer::value_type Element;
|
||||
|
||||
// Constructs the matcher from a sequence of element values or
|
||||
// element matchers.
|
||||
@@ -68,12 +196,13 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
||||
|
||||
// Returns true iff 'container' matches.
|
||||
virtual bool Matches(Container container) const {
|
||||
if (container.size() != count())
|
||||
StlContainerReference stl_container = View::ConstReference(container);
|
||||
if (stl_container.size() != count())
|
||||
return false;
|
||||
|
||||
typename RawContainer::const_iterator container_iter = container.begin();
|
||||
for (size_t i = 0; i != count(); ++container_iter, ++i) {
|
||||
if (!matchers_[i].Matches(*container_iter))
|
||||
typename StlContainer::const_iterator it = stl_container.begin();
|
||||
for (size_t i = 0; i != count(); ++it, ++i) {
|
||||
if (!matchers_[i].Matches(*it))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -119,15 +248,16 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
||||
// Explains why 'container' matches, or doesn't match, this matcher.
|
||||
virtual void ExplainMatchResultTo(Container container,
|
||||
::std::ostream* os) const {
|
||||
StlContainerReference stl_container = View::ConstReference(container);
|
||||
if (Matches(container)) {
|
||||
// We need to explain why *each* element matches (the obvious
|
||||
// ones can be skipped).
|
||||
|
||||
bool reason_printed = false;
|
||||
typename RawContainer::const_iterator container_iter = container.begin();
|
||||
for (size_t i = 0; i != count(); ++container_iter, ++i) {
|
||||
typename StlContainer::const_iterator it = stl_container.begin();
|
||||
for (size_t i = 0; i != count(); ++it, ++i) {
|
||||
::std::stringstream ss;
|
||||
matchers_[i].ExplainMatchResultTo(*container_iter, &ss);
|
||||
matchers_[i].ExplainMatchResultTo(*it, &ss);
|
||||
|
||||
const string s = ss.str();
|
||||
if (!s.empty()) {
|
||||
@@ -140,7 +270,7 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
||||
}
|
||||
} else {
|
||||
// We need to explain why the container doesn't match.
|
||||
const size_t actual_count = container.size();
|
||||
const size_t actual_count = stl_container.size();
|
||||
if (actual_count != count()) {
|
||||
// The element count doesn't match. If the container is
|
||||
// empty, there's no need to explain anything as Google Mock
|
||||
@@ -155,16 +285,16 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
||||
// The container has the right size but at least one element
|
||||
// doesn't match expectation. We need to find this element and
|
||||
// explain why it doesn't match.
|
||||
typename RawContainer::const_iterator container_iter = container.begin();
|
||||
for (size_t i = 0; i != count(); ++container_iter, ++i) {
|
||||
if (matchers_[i].Matches(*container_iter)) {
|
||||
typename StlContainer::const_iterator it = stl_container.begin();
|
||||
for (size_t i = 0; i != count(); ++it, ++i) {
|
||||
if (matchers_[i].Matches(*it)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
*os << "element " << i << " doesn't match";
|
||||
|
||||
::std::stringstream ss;
|
||||
matchers_[i].ExplainMatchResultTo(*container_iter, &ss);
|
||||
matchers_[i].ExplainMatchResultTo(*it, &ss);
|
||||
const string s = ss.str();
|
||||
if (!s.empty()) {
|
||||
*os << " (" << s << ")";
|
||||
@@ -193,7 +323,8 @@ class ElementsAreMatcher0 {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
const Matcher<const Element&>* const matchers = NULL;
|
||||
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 0));
|
||||
@@ -214,7 +345,8 @@ class ElementsAreMatcher$i {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
const Matcher<const Element&> matchers[] = {
|
||||
|
||||
@@ -248,7 +380,8 @@ class ElementsAreArrayMatcher {
|
||||
operator Matcher<Container>() const {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
|
||||
RawContainer;
|
||||
typedef typename RawContainer::value_type Element;
|
||||
typedef typename internal::StlContainerView<RawContainer>::type::value_type
|
||||
Element;
|
||||
|
||||
return MakeMatcher(new ElementsAreMatcherImpl<Container>(first_, count_));
|
||||
}
|
||||
@@ -260,6 +393,21 @@ class ElementsAreArrayMatcher {
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
|
||||
// fields of it matches a_matcher. C++ doesn't support default
|
||||
// arguments for function templates, so we have to overload it.
|
||||
|
||||
$range i 0..n
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
template <$for j [[int k$j, ]]typename InnerMatcher>
|
||||
inline internal::ArgsMatcher<InnerMatcher$for j [[, k$j]]>
|
||||
Args(const InnerMatcher& matcher) {
|
||||
return internal::ArgsMatcher<InnerMatcher$for j [[, k$j]]>(matcher);
|
||||
}
|
||||
|
||||
|
||||
]]
|
||||
// ElementsAre(e0, e1, ..., e_n) matches an STL-style container with
|
||||
// (n + 1) elements, where the i-th element in the container must
|
||||
// match the i-th argument in the list. Each argument of
|
||||
@@ -274,6 +422,7 @@ inline internal::ElementsAreMatcher0 ElementsAre() {
|
||||
return internal::ElementsAreMatcher0();
|
||||
}
|
||||
|
||||
$range i 1..n
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
|
||||
@@ -590,45 +739,4 @@ $var param_field_decls2 = [[$for j
|
||||
]]
|
||||
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// Returns true iff element is in the STL-style container.
|
||||
template <typename Container, typename Element>
|
||||
inline bool Contains(const Container& container, const Element& element) {
|
||||
return ::std::find(container.begin(), container.end(), element) !=
|
||||
container.end();
|
||||
}
|
||||
|
||||
// Returns true iff element is in the C-style array.
|
||||
template <typename ArrayElement, size_t N, typename Element>
|
||||
inline bool Contains(const ArrayElement (&array)[N], const Element& element) {
|
||||
return ::std::find(array, array + N, element) != array + N;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Matches an STL-style container or a C-style array that contains the given
|
||||
// element.
|
||||
//
|
||||
// Examples:
|
||||
// ::std::set<int> page_ids;
|
||||
// page_ids.insert(3);
|
||||
// page_ids.insert(1);
|
||||
// EXPECT_THAT(page_ids, Contains(1));
|
||||
// EXPECT_THAT(page_ids, Contains(3.0));
|
||||
// EXPECT_THAT(page_ids, Not(Contains(4)));
|
||||
//
|
||||
// ::std::map<int, size_t> page_lengths;
|
||||
// page_lengths[1] = 100;
|
||||
// EXPECT_THAT(map_int, Contains(::std::pair<const int, size_t>(1, 100)));
|
||||
//
|
||||
// const char* user_ids[] = { "joe", "mike", "tom" };
|
||||
// EXPECT_THAT(user_ids, Contains(::std::string("tom")));
|
||||
MATCHER_P(Contains, element, "") {
|
||||
return internal::Contains(arg, element);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||
|
||||
@@ -938,7 +938,7 @@ class MatchesRegexMatcher {
|
||||
//
|
||||
// We define this as a macro in order to eliminate duplicated source
|
||||
// code.
|
||||
#define GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(name, op, relation) \
|
||||
#define GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(name, op) \
|
||||
class name##2Matcher { \
|
||||
public: \
|
||||
template <typename T1, typename T2> \
|
||||
@@ -953,21 +953,21 @@ class MatchesRegexMatcher {
|
||||
return ::std::tr1::get<0>(args) op ::std::tr1::get<1>(args); \
|
||||
} \
|
||||
virtual void DescribeTo(::std::ostream* os) const { \
|
||||
*os << "argument #0 is " relation " argument #1"; \
|
||||
*os << "are a pair (x, y) where x " #op " y"; \
|
||||
} \
|
||||
virtual void DescribeNegationTo(::std::ostream* os) const { \
|
||||
*os << "argument #0 is not " relation " argument #1"; \
|
||||
*os << "are a pair (x, y) where x " #op " y is false"; \
|
||||
} \
|
||||
}; \
|
||||
}
|
||||
|
||||
// Implements Eq(), Ge(), Gt(), Le(), Lt(), and Ne() respectively.
|
||||
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Eq, ==, "equal to");
|
||||
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Ge, >=, "greater than or equal to");
|
||||
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Gt, >, "greater than");
|
||||
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Le, <=, "less than or equal to");
|
||||
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Lt, <, "less than");
|
||||
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Ne, !=, "not equal to");
|
||||
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Eq, ==);
|
||||
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Ge, >=);
|
||||
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Gt, >);
|
||||
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Le, <=);
|
||||
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Lt, <);
|
||||
GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Ne, !=);
|
||||
|
||||
#undef GMOCK_IMPLEMENT_COMPARISON2_MATCHER_
|
||||
|
||||
@@ -1709,60 +1709,164 @@ void ExplainMatchResultTo(const ResultOfMatcher<Callable>& matcher,
|
||||
template <typename Container>
|
||||
class ContainerEqMatcher {
|
||||
public:
|
||||
explicit ContainerEqMatcher(const Container& rhs) : rhs_(rhs) {}
|
||||
bool Matches(const Container& lhs) const { return lhs == rhs_; }
|
||||
typedef internal::StlContainerView<Container> View;
|
||||
typedef typename View::type StlContainer;
|
||||
typedef typename View::const_reference StlContainerReference;
|
||||
|
||||
// We make a copy of rhs in case the elements in it are modified
|
||||
// after this matcher is created.
|
||||
explicit ContainerEqMatcher(const Container& rhs) : rhs_(View::Copy(rhs)) {
|
||||
// Makes sure the user doesn't instantiate this class template
|
||||
// with a const or reference type.
|
||||
testing::StaticAssertTypeEq<Container,
|
||||
GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))>();
|
||||
}
|
||||
|
||||
template <typename LhsContainer>
|
||||
bool Matches(const LhsContainer& lhs) const {
|
||||
// GMOCK_REMOVE_CONST_() is needed to work around an MSVC 8.0 bug
|
||||
// that causes LhsContainer to be a const type sometimes.
|
||||
typedef internal::StlContainerView<GMOCK_REMOVE_CONST_(LhsContainer)>
|
||||
LhsView;
|
||||
StlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
|
||||
return lhs_stl_container == rhs_;
|
||||
}
|
||||
void DescribeTo(::std::ostream* os) const {
|
||||
*os << "equals ";
|
||||
UniversalPrinter<Container>::Print(rhs_, os);
|
||||
UniversalPrinter<StlContainer>::Print(rhs_, os);
|
||||
}
|
||||
void DescribeNegationTo(::std::ostream* os) const {
|
||||
*os << "does not equal ";
|
||||
UniversalPrinter<Container>::Print(rhs_, os);
|
||||
UniversalPrinter<StlContainer>::Print(rhs_, os);
|
||||
}
|
||||
|
||||
void ExplainMatchResultTo(const Container& lhs,
|
||||
template <typename LhsContainer>
|
||||
void ExplainMatchResultTo(const LhsContainer& lhs,
|
||||
::std::ostream* os) const {
|
||||
// GMOCK_REMOVE_CONST_() is needed to work around an MSVC 8.0 bug
|
||||
// that causes LhsContainer to be a const type sometimes.
|
||||
typedef internal::StlContainerView<GMOCK_REMOVE_CONST_(LhsContainer)>
|
||||
LhsView;
|
||||
typedef typename LhsView::type LhsStlContainer;
|
||||
StlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
|
||||
|
||||
// Something is different. Check for missing values first.
|
||||
bool printed_header = false;
|
||||
for (typename Container::const_iterator it = lhs.begin();
|
||||
it != lhs.end(); ++it) {
|
||||
if (std::find(rhs_.begin(), rhs_.end(), *it) == rhs_.end()) {
|
||||
for (typename LhsStlContainer::const_iterator it =
|
||||
lhs_stl_container.begin();
|
||||
it != lhs_stl_container.end(); ++it) {
|
||||
if (internal::ArrayAwareFind(rhs_.begin(), rhs_.end(), *it) ==
|
||||
rhs_.end()) {
|
||||
if (printed_header) {
|
||||
*os << ", ";
|
||||
} else {
|
||||
*os << "Only in actual: ";
|
||||
printed_header = true;
|
||||
}
|
||||
UniversalPrinter<typename Container::value_type>::Print(*it, os);
|
||||
UniversalPrinter<typename LhsStlContainer::value_type>::Print(*it, os);
|
||||
}
|
||||
}
|
||||
|
||||
// Now check for extra values.
|
||||
bool printed_header2 = false;
|
||||
for (typename Container::const_iterator it = rhs_.begin();
|
||||
for (typename StlContainer::const_iterator it = rhs_.begin();
|
||||
it != rhs_.end(); ++it) {
|
||||
if (std::find(lhs.begin(), lhs.end(), *it) == lhs.end()) {
|
||||
if (internal::ArrayAwareFind(
|
||||
lhs_stl_container.begin(), lhs_stl_container.end(), *it) ==
|
||||
lhs_stl_container.end()) {
|
||||
if (printed_header2) {
|
||||
*os << ", ";
|
||||
} else {
|
||||
*os << (printed_header ? "; not" : "Not") << " in actual: ";
|
||||
printed_header2 = true;
|
||||
}
|
||||
UniversalPrinter<typename Container::value_type>::Print(*it, os);
|
||||
UniversalPrinter<typename StlContainer::value_type>::Print(*it, os);
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
const Container rhs_;
|
||||
const StlContainer rhs_;
|
||||
};
|
||||
|
||||
template <typename Container>
|
||||
template <typename LhsContainer, typename Container>
|
||||
void ExplainMatchResultTo(const ContainerEqMatcher<Container>& matcher,
|
||||
const Container& lhs,
|
||||
const LhsContainer& lhs,
|
||||
::std::ostream* os) {
|
||||
matcher.ExplainMatchResultTo(lhs, os);
|
||||
}
|
||||
|
||||
// Implements Contains(element_matcher) for the given argument type Container.
|
||||
template <typename Container>
|
||||
class ContainsMatcherImpl : public MatcherInterface<Container> {
|
||||
public:
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer;
|
||||
typedef StlContainerView<RawContainer> View;
|
||||
typedef typename View::type StlContainer;
|
||||
typedef typename View::const_reference StlContainerReference;
|
||||
typedef typename StlContainer::value_type Element;
|
||||
|
||||
template <typename InnerMatcher>
|
||||
explicit ContainsMatcherImpl(InnerMatcher inner_matcher)
|
||||
: inner_matcher_(
|
||||
testing::SafeMatcherCast<const Element&>(inner_matcher)) {}
|
||||
|
||||
// Returns true iff 'container' matches.
|
||||
virtual bool Matches(Container container) const {
|
||||
StlContainerReference stl_container = View::ConstReference(container);
|
||||
for (typename StlContainer::const_iterator it = stl_container.begin();
|
||||
it != stl_container.end(); ++it) {
|
||||
if (inner_matcher_.Matches(*it))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Describes what this matcher does.
|
||||
virtual void DescribeTo(::std::ostream* os) const {
|
||||
*os << "contains at least one element that ";
|
||||
inner_matcher_.DescribeTo(os);
|
||||
}
|
||||
|
||||
// Describes what the negation of this matcher does.
|
||||
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||
*os << "doesn't contain any element that ";
|
||||
inner_matcher_.DescribeTo(os);
|
||||
}
|
||||
|
||||
// Explains why 'container' matches, or doesn't match, this matcher.
|
||||
virtual void ExplainMatchResultTo(Container container,
|
||||
::std::ostream* os) const {
|
||||
StlContainerReference stl_container = View::ConstReference(container);
|
||||
|
||||
// We need to explain which (if any) element matches inner_matcher_.
|
||||
typename StlContainer::const_iterator it = stl_container.begin();
|
||||
for (size_t i = 0; it != stl_container.end(); ++it, ++i) {
|
||||
if (inner_matcher_.Matches(*it)) {
|
||||
*os << "element " << i << " matches";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const Matcher<const Element&> inner_matcher_;
|
||||
};
|
||||
|
||||
// Implements polymorphic Contains(element_matcher).
|
||||
template <typename M>
|
||||
class ContainsMatcher {
|
||||
public:
|
||||
explicit ContainsMatcher(M m) : inner_matcher_(m) {}
|
||||
|
||||
template <typename Container>
|
||||
operator Matcher<Container>() const {
|
||||
return MakeMatcher(new ContainsMatcherImpl<Container>(inner_matcher_));
|
||||
}
|
||||
|
||||
private:
|
||||
const M inner_matcher_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Implements MatcherCast().
|
||||
@@ -2206,9 +2310,35 @@ Truly(Predicate pred) {
|
||||
// values that are included in one container but not the other. (Duplicate
|
||||
// values and order differences are not explained.)
|
||||
template <typename Container>
|
||||
inline PolymorphicMatcher<internal::ContainerEqMatcher<Container> >
|
||||
inline PolymorphicMatcher<internal::ContainerEqMatcher<
|
||||
GMOCK_REMOVE_CONST_(Container)> >
|
||||
ContainerEq(const Container& rhs) {
|
||||
return MakePolymorphicMatcher(internal::ContainerEqMatcher<Container>(rhs));
|
||||
// This following line is for working around a bug in MSVC 8.0,
|
||||
// which causes Container to be a const type sometimes.
|
||||
typedef GMOCK_REMOVE_CONST_(Container) RawContainer;
|
||||
return MakePolymorphicMatcher(internal::ContainerEqMatcher<RawContainer>(rhs));
|
||||
}
|
||||
|
||||
// Matches an STL-style container or a native array that contains at
|
||||
// least one element matching the given value or matcher.
|
||||
//
|
||||
// Examples:
|
||||
// ::std::set<int> page_ids;
|
||||
// page_ids.insert(3);
|
||||
// page_ids.insert(1);
|
||||
// EXPECT_THAT(page_ids, Contains(1));
|
||||
// EXPECT_THAT(page_ids, Contains(Gt(2)));
|
||||
// EXPECT_THAT(page_ids, Not(Contains(4)));
|
||||
//
|
||||
// ::std::map<int, size_t> page_lengths;
|
||||
// page_lengths[1] = 100;
|
||||
// EXPECT_THAT(map_int, Contains(::std::pair<const int, size_t>(1, 100)));
|
||||
//
|
||||
// const char* user_ids[] = { "joe", "mike", "tom" };
|
||||
// EXPECT_THAT(user_ids, Contains(Eq(::std::string("tom"))));
|
||||
template <typename M>
|
||||
inline internal::ContainsMatcher<M> Contains(M matcher) {
|
||||
return internal::ContainsMatcher<M>(matcher);
|
||||
}
|
||||
|
||||
// Returns a predicate that is satisfied by anything that matches the
|
||||
@@ -2218,6 +2348,22 @@ inline internal::MatcherAsPredicate<M> Matches(M matcher) {
|
||||
return internal::MatcherAsPredicate<M>(matcher);
|
||||
}
|
||||
|
||||
// Returns true iff the value matches the matcher.
|
||||
template <typename T, typename M>
|
||||
inline bool Value(const T& value, M matcher) {
|
||||
return testing::Matches(matcher)(value);
|
||||
}
|
||||
|
||||
// AllArgs(m) is a synonym of m. This is useful in
|
||||
//
|
||||
// EXPECT_CALL(foo, Bar(_, _)).With(AllArgs(Eq()));
|
||||
//
|
||||
// which is easier to read than
|
||||
//
|
||||
// EXPECT_CALL(foo, Bar(_, _)).With(Eq());
|
||||
template <typename InnerMatcher>
|
||||
inline InnerMatcher AllArgs(const InnerMatcher& matcher) { return matcher; }
|
||||
|
||||
// These macros allow using matchers to check values in Google Test
|
||||
// tests. ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher)
|
||||
// succeed iff the value matches the matcher. If the assertion fails,
|
||||
|
||||
@@ -66,10 +66,28 @@
|
||||
// // printed.
|
||||
// void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
|
||||
//
|
||||
// // Prints value using the type inferred by the compiler. The difference
|
||||
// // from UniversalTersePrint() is that this function prints both the
|
||||
// // pointer and the NUL-terminated string for a (const) char pointer.
|
||||
// void ::testing::internal::UniversalPrint(const T& value, ostream*);
|
||||
//
|
||||
// // Prints the fields of a tuple tersely to a string vector, one
|
||||
// // element for each field.
|
||||
// std::vector<string> UniversalTersePrintTupleFieldsToStrings(
|
||||
// const Tuple& value);
|
||||
//
|
||||
// Known limitation:
|
||||
//
|
||||
// The print primitives print the elements of an STL-style container
|
||||
// using the compiler-inferred type of *iter where iter is a
|
||||
// const_iterator of the container. When const_iterator is an input
|
||||
// iterator but not a forward iterator, this inferred type may not
|
||||
// match value_type, and the print output may be incorrect. In
|
||||
// practice, this is rarely a problem as for most containers
|
||||
// const_iterator is a forward iterator. We'll fix this if there's an
|
||||
// actual need for it. Note that this fix cannot rely on value_type
|
||||
// being defined as many user-defined container types don't have
|
||||
// value_type.
|
||||
|
||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
|
||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_
|
||||
@@ -208,6 +226,9 @@ namespace internal {
|
||||
template <typename T>
|
||||
class UniversalPrinter;
|
||||
|
||||
template <typename T>
|
||||
void UniversalPrint(const T& value, ::std::ostream* os);
|
||||
|
||||
// Used to print an STL-style container when the user doesn't define
|
||||
// a PrintTo() for it.
|
||||
template <typename C>
|
||||
@@ -227,7 +248,9 @@ void DefaultPrintTo(IsContainer /* dummy */,
|
||||
}
|
||||
}
|
||||
*os << ' ';
|
||||
PrintTo(*it, os);
|
||||
// We cannot call PrintTo(*it, os) here as PrintTo() doesn't
|
||||
// handle *it being a native array.
|
||||
internal::UniversalPrint(*it, os);
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
@@ -580,6 +603,41 @@ class UniversalPrinter {
|
||||
#endif // _MSC_VER
|
||||
};
|
||||
|
||||
// UniversalPrintArray(begin, len, os) prints an array of 'len'
|
||||
// elements, starting at address 'begin'.
|
||||
template <typename T>
|
||||
void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
|
||||
if (len == 0) {
|
||||
*os << "{}";
|
||||
} else {
|
||||
*os << "{ ";
|
||||
const size_t kThreshold = 18;
|
||||
const size_t kChunkSize = 8;
|
||||
// If the array has more than kThreshold elements, we'll have to
|
||||
// omit some details by printing only the first and the last
|
||||
// kChunkSize elements.
|
||||
// TODO(wan@google.com): let the user control the threshold using a flag.
|
||||
if (len <= kThreshold) {
|
||||
PrintRawArrayTo(begin, len, os);
|
||||
} else {
|
||||
PrintRawArrayTo(begin, kChunkSize, os);
|
||||
*os << ", ..., ";
|
||||
PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
|
||||
}
|
||||
*os << " }";
|
||||
}
|
||||
}
|
||||
// This overload prints a (const) char array compactly.
|
||||
void UniversalPrintArray(const char* begin, size_t len, ::std::ostream* os);
|
||||
|
||||
// Prints an array of 'len' elements, starting at address 'begin', to a string.
|
||||
template <typename T>
|
||||
string UniversalPrintArrayToString(const T* begin, size_t len) {
|
||||
::std::stringstream ss;
|
||||
UniversalPrintArray(begin, len, &ss);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Implements printing an array type T[N].
|
||||
template <typename T, size_t N>
|
||||
class UniversalPrinter<T[N]> {
|
||||
@@ -587,41 +645,13 @@ class UniversalPrinter<T[N]> {
|
||||
// Prints the given array, omitting some elements when there are too
|
||||
// many.
|
||||
static void Print(const T (&a)[N], ::std::ostream* os) {
|
||||
// Prints a char array as a C string. Note that we compare 'const
|
||||
// T' with 'const char' instead of comparing T with char, in case
|
||||
// that T is already a const type.
|
||||
if (internal::type_equals<const T, const char>::value) {
|
||||
UniversalPrinter<const T*>::Print(a, os);
|
||||
return;
|
||||
}
|
||||
|
||||
if (N == 0) {
|
||||
*os << "{}";
|
||||
} else {
|
||||
*os << "{ ";
|
||||
const size_t kThreshold = 18;
|
||||
const size_t kChunkSize = 8;
|
||||
// If the array has more than kThreshold elements, we'll have to
|
||||
// omit some details by printing only the first and the last
|
||||
// kChunkSize elements.
|
||||
// TODO(wan): let the user control the threshold using a flag.
|
||||
if (N <= kThreshold) {
|
||||
PrintRawArrayTo(a, N, os);
|
||||
} else {
|
||||
PrintRawArrayTo(a, kChunkSize, os);
|
||||
*os << ", ..., ";
|
||||
PrintRawArrayTo(a + N - kChunkSize, kChunkSize, os);
|
||||
}
|
||||
*os << " }";
|
||||
}
|
||||
UniversalPrintArray(a, N, os);
|
||||
}
|
||||
|
||||
// A convenient wrapper for Print() that returns the print-out as a
|
||||
// string.
|
||||
static string PrintToString(const T (&a)[N]) {
|
||||
::std::stringstream ss;
|
||||
Print(a, &ss);
|
||||
return ss.str();
|
||||
return UniversalPrintArrayToString(a, N);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -676,6 +706,15 @@ inline void UniversalTersePrint(char* str, ::std::ostream* os) {
|
||||
UniversalTersePrint(static_cast<const char*>(str), os);
|
||||
}
|
||||
|
||||
// Prints a value using the type inferred by the compiler. The
|
||||
// difference between this and UniversalTersePrint() is that for a
|
||||
// (const) char pointer, this prints both the pointer and the
|
||||
// NUL-terminated string.
|
||||
template <typename T>
|
||||
void UniversalPrint(const T& value, ::std::ostream* os) {
|
||||
UniversalPrinter<T>::Print(value, os);
|
||||
}
|
||||
|
||||
// Prints the fields of a tuple tersely to a string vector, one
|
||||
// element for each field. See the comment before
|
||||
// UniversalTersePrint() for how we define "tersely".
|
||||
|
||||
@@ -37,16 +37,16 @@
|
||||
// a mock method. The syntax is:
|
||||
//
|
||||
// ON_CALL(mock_object, Method(argument-matchers))
|
||||
// .WithArguments(multi-argument-matcher)
|
||||
// .With(multi-argument-matcher)
|
||||
// .WillByDefault(action);
|
||||
//
|
||||
// where the .WithArguments() clause is optional.
|
||||
// where the .With() clause is optional.
|
||||
//
|
||||
// A user can use the EXPECT_CALL() macro to specify an expectation on
|
||||
// a mock method. The syntax is:
|
||||
//
|
||||
// EXPECT_CALL(mock_object, Method(argument-matchers))
|
||||
// .WithArguments(multi-argument-matchers)
|
||||
// .With(multi-argument-matchers)
|
||||
// .Times(cardinality)
|
||||
// .InSequence(sequences)
|
||||
// .WillOnce(action)
|
||||
@@ -93,10 +93,6 @@ class ExpectationTester;
|
||||
template <typename F>
|
||||
class FunctionMockerBase;
|
||||
|
||||
// Helper class for implementing FunctionMockerBase<F>::InvokeWith().
|
||||
template <typename Result, typename F>
|
||||
class InvokeWithHelper;
|
||||
|
||||
// Protects the mock object registry (in class Mock), all function
|
||||
// mockers, and all expectations.
|
||||
//
|
||||
@@ -148,20 +144,20 @@ class DefaultActionSpec {
|
||||
// bug in Symbian's C++ compiler (cannot decide between two
|
||||
// overloaded constructors of Matcher<const ArgumentTuple&>).
|
||||
extra_matcher_(A<const ArgumentTuple&>()),
|
||||
last_clause_(NONE) {
|
||||
last_clause_(kNone) {
|
||||
}
|
||||
|
||||
// Where in the source file was the default action spec defined?
|
||||
const char* file() const { return file_; }
|
||||
int line() const { return line_; }
|
||||
|
||||
// Implements the .WithArguments() clause.
|
||||
DefaultActionSpec& WithArguments(const Matcher<const ArgumentTuple&>& m) {
|
||||
// Implements the .With() clause.
|
||||
DefaultActionSpec& With(const Matcher<const ArgumentTuple&>& m) {
|
||||
// Makes sure this is called at most once.
|
||||
ExpectSpecProperty(last_clause_ < WITH_ARGUMENTS,
|
||||
".WithArguments() cannot appear "
|
||||
ExpectSpecProperty(last_clause_ < kWith,
|
||||
".With() cannot appear "
|
||||
"more than once in an ON_CALL().");
|
||||
last_clause_ = WITH_ARGUMENTS;
|
||||
last_clause_ = kWith;
|
||||
|
||||
extra_matcher_ = m;
|
||||
return *this;
|
||||
@@ -169,10 +165,10 @@ class DefaultActionSpec {
|
||||
|
||||
// Implements the .WillByDefault() clause.
|
||||
DefaultActionSpec& WillByDefault(const Action<F>& action) {
|
||||
ExpectSpecProperty(last_clause_ < WILL_BY_DEFAULT,
|
||||
ExpectSpecProperty(last_clause_ < kWillByDefault,
|
||||
".WillByDefault() must appear "
|
||||
"exactly once in an ON_CALL().");
|
||||
last_clause_ = WILL_BY_DEFAULT;
|
||||
last_clause_ = kWillByDefault;
|
||||
|
||||
ExpectSpecProperty(!action.IsDoDefault(),
|
||||
"DoDefault() cannot be used in ON_CALL().");
|
||||
@@ -187,7 +183,7 @@ class DefaultActionSpec {
|
||||
|
||||
// Returns the action specified by the user.
|
||||
const Action<F>& GetAction() const {
|
||||
AssertSpecProperty(last_clause_ == WILL_BY_DEFAULT,
|
||||
AssertSpecProperty(last_clause_ == kWillByDefault,
|
||||
".WillByDefault() must appear exactly "
|
||||
"once in an ON_CALL().");
|
||||
return action_;
|
||||
@@ -197,9 +193,9 @@ class DefaultActionSpec {
|
||||
enum Clause {
|
||||
// Do not change the order of the enum members! The run-time
|
||||
// syntax checking relies on it.
|
||||
NONE,
|
||||
WITH_ARGUMENTS,
|
||||
WILL_BY_DEFAULT,
|
||||
kNone,
|
||||
kWith,
|
||||
kWillByDefault,
|
||||
};
|
||||
|
||||
// Asserts that the ON_CALL() statement has a certain property.
|
||||
@@ -215,7 +211,7 @@ class DefaultActionSpec {
|
||||
// The information in statement
|
||||
//
|
||||
// ON_CALL(mock_object, Method(matchers))
|
||||
// .WithArguments(multi-argument-matcher)
|
||||
// .With(multi-argument-matcher)
|
||||
// .WillByDefault(action);
|
||||
//
|
||||
// is recorded in the data members like this:
|
||||
@@ -232,7 +228,7 @@ class DefaultActionSpec {
|
||||
Action<F> action_;
|
||||
|
||||
// The last clause in the ON_CALL() statement as seen so far.
|
||||
// Initially NONE and changes as the statement is parsed.
|
||||
// Initially kNone and changes as the statement is parsed.
|
||||
Clause last_clause_;
|
||||
}; // class DefaultActionSpec
|
||||
|
||||
@@ -269,9 +265,6 @@ class Mock {
|
||||
template <typename F>
|
||||
friend class internal::FunctionMockerBase;
|
||||
|
||||
template <typename R, typename Args>
|
||||
friend class internal::InvokeWithHelper;
|
||||
|
||||
template <typename M>
|
||||
friend class NiceMock;
|
||||
|
||||
@@ -444,13 +437,13 @@ class ExpectationBase {
|
||||
|
||||
enum Clause {
|
||||
// Don't change the order of the enum members!
|
||||
NONE,
|
||||
WITH_ARGUMENTS,
|
||||
TIMES,
|
||||
IN_SEQUENCE,
|
||||
WILL_ONCE,
|
||||
WILL_REPEATEDLY,
|
||||
RETIRES_ON_SATURATION,
|
||||
kNone,
|
||||
kWith,
|
||||
kTimes,
|
||||
kInSequence,
|
||||
kWillOnce,
|
||||
kWillRepeatedly,
|
||||
kRetiresOnSaturation,
|
||||
};
|
||||
|
||||
// Asserts that the EXPECT_CALL() statement has the given property.
|
||||
@@ -588,7 +581,7 @@ class Expectation : public ExpectationBase {
|
||||
repeated_action_specified_(false),
|
||||
repeated_action_(DoDefault()),
|
||||
retires_on_saturation_(false),
|
||||
last_clause_(NONE),
|
||||
last_clause_(kNone),
|
||||
action_count_checked_(false) {}
|
||||
|
||||
virtual ~Expectation() {
|
||||
@@ -597,18 +590,18 @@ class Expectation : public ExpectationBase {
|
||||
CheckActionCountIfNotDone();
|
||||
}
|
||||
|
||||
// Implements the .WithArguments() clause.
|
||||
Expectation& WithArguments(const Matcher<const ArgumentTuple&>& m) {
|
||||
if (last_clause_ == WITH_ARGUMENTS) {
|
||||
// Implements the .With() clause.
|
||||
Expectation& With(const Matcher<const ArgumentTuple&>& m) {
|
||||
if (last_clause_ == kWith) {
|
||||
ExpectSpecProperty(false,
|
||||
".WithArguments() cannot appear "
|
||||
".With() cannot appear "
|
||||
"more than once in an EXPECT_CALL().");
|
||||
} else {
|
||||
ExpectSpecProperty(last_clause_ < WITH_ARGUMENTS,
|
||||
".WithArguments() must be the first "
|
||||
ExpectSpecProperty(last_clause_ < kWith,
|
||||
".With() must be the first "
|
||||
"clause in an EXPECT_CALL().");
|
||||
}
|
||||
last_clause_ = WITH_ARGUMENTS;
|
||||
last_clause_ = kWith;
|
||||
|
||||
extra_matcher_ = m;
|
||||
return *this;
|
||||
@@ -616,17 +609,17 @@ class Expectation : public ExpectationBase {
|
||||
|
||||
// Implements the .Times() clause.
|
||||
Expectation& Times(const Cardinality& cardinality) {
|
||||
if (last_clause_ ==TIMES) {
|
||||
if (last_clause_ ==kTimes) {
|
||||
ExpectSpecProperty(false,
|
||||
".Times() cannot appear "
|
||||
"more than once in an EXPECT_CALL().");
|
||||
} else {
|
||||
ExpectSpecProperty(last_clause_ < TIMES,
|
||||
ExpectSpecProperty(last_clause_ < kTimes,
|
||||
".Times() cannot appear after "
|
||||
".InSequence(), .WillOnce(), .WillRepeatedly(), "
|
||||
"or .RetiresOnSaturation().");
|
||||
}
|
||||
last_clause_ = TIMES;
|
||||
last_clause_ = kTimes;
|
||||
|
||||
ExpectationBase::SpecifyCardinality(cardinality);
|
||||
return *this;
|
||||
@@ -639,11 +632,11 @@ class Expectation : public ExpectationBase {
|
||||
|
||||
// Implements the .InSequence() clause.
|
||||
Expectation& InSequence(const Sequence& s) {
|
||||
ExpectSpecProperty(last_clause_ <= IN_SEQUENCE,
|
||||
ExpectSpecProperty(last_clause_ <= kInSequence,
|
||||
".InSequence() cannot appear after .WillOnce(),"
|
||||
" .WillRepeatedly(), or "
|
||||
".RetiresOnSaturation().");
|
||||
last_clause_ = IN_SEQUENCE;
|
||||
last_clause_ = kInSequence;
|
||||
|
||||
s.AddExpectation(owner_->GetLinkedExpectationBase(this));
|
||||
return *this;
|
||||
@@ -667,10 +660,10 @@ class Expectation : public ExpectationBase {
|
||||
|
||||
// Implements the .WillOnce() clause.
|
||||
Expectation& WillOnce(const Action<F>& action) {
|
||||
ExpectSpecProperty(last_clause_ <= WILL_ONCE,
|
||||
ExpectSpecProperty(last_clause_ <= kWillOnce,
|
||||
".WillOnce() cannot appear after "
|
||||
".WillRepeatedly() or .RetiresOnSaturation().");
|
||||
last_clause_ = WILL_ONCE;
|
||||
last_clause_ = kWillOnce;
|
||||
|
||||
actions_.push_back(action);
|
||||
if (!cardinality_specified()) {
|
||||
@@ -681,16 +674,16 @@ class Expectation : public ExpectationBase {
|
||||
|
||||
// Implements the .WillRepeatedly() clause.
|
||||
Expectation& WillRepeatedly(const Action<F>& action) {
|
||||
if (last_clause_ == WILL_REPEATEDLY) {
|
||||
if (last_clause_ == kWillRepeatedly) {
|
||||
ExpectSpecProperty(false,
|
||||
".WillRepeatedly() cannot appear "
|
||||
"more than once in an EXPECT_CALL().");
|
||||
} else {
|
||||
ExpectSpecProperty(last_clause_ < WILL_REPEATEDLY,
|
||||
ExpectSpecProperty(last_clause_ < kWillRepeatedly,
|
||||
".WillRepeatedly() cannot appear "
|
||||
"after .RetiresOnSaturation().");
|
||||
}
|
||||
last_clause_ = WILL_REPEATEDLY;
|
||||
last_clause_ = kWillRepeatedly;
|
||||
repeated_action_specified_ = true;
|
||||
|
||||
repeated_action_ = action;
|
||||
@@ -706,10 +699,10 @@ class Expectation : public ExpectationBase {
|
||||
|
||||
// Implements the .RetiresOnSaturation() clause.
|
||||
Expectation& RetiresOnSaturation() {
|
||||
ExpectSpecProperty(last_clause_ < RETIRES_ON_SATURATION,
|
||||
ExpectSpecProperty(last_clause_ < kRetiresOnSaturation,
|
||||
".RetiresOnSaturation() cannot appear "
|
||||
"more than once.");
|
||||
last_clause_ = RETIRES_ON_SATURATION;
|
||||
last_clause_ = kRetiresOnSaturation;
|
||||
retires_on_saturation_ = true;
|
||||
|
||||
// Now that no more action clauses can be specified, we check
|
||||
@@ -724,7 +717,7 @@ class Expectation : public ExpectationBase {
|
||||
return matchers_;
|
||||
}
|
||||
|
||||
// Returns the matcher specified by the .WithArguments() clause.
|
||||
// Returns the matcher specified by the .With() clause.
|
||||
const Matcher<const ArgumentTuple&>& extra_matcher() const {
|
||||
return extra_matcher_;
|
||||
}
|
||||
@@ -763,9 +756,6 @@ class Expectation : public ExpectationBase {
|
||||
template <typename Function>
|
||||
friend class FunctionMockerBase;
|
||||
|
||||
template <typename R, typename Function>
|
||||
friend class InvokeWithHelper;
|
||||
|
||||
// The following methods will be called only after the EXPECT_CALL()
|
||||
// statement finishes and when the current thread holds
|
||||
// g_gmock_mutex.
|
||||
@@ -805,9 +795,9 @@ class Expectation : public ExpectationBase {
|
||||
DescribeMatchFailureTupleTo(matchers_, args, os);
|
||||
}
|
||||
if (!extra_matcher_.Matches(args)) {
|
||||
*os << " Expected: ";
|
||||
*os << " Expected args: ";
|
||||
extra_matcher_.DescribeTo(os);
|
||||
*os << "\n Actual: false";
|
||||
*os << "\n Actual: don't match";
|
||||
|
||||
internal::ExplainMatchResultAsNeededTo<const ArgumentTuple&>(
|
||||
extra_matcher_, args, os);
|
||||
@@ -1042,6 +1032,78 @@ class MockSpec {
|
||||
#pragma warning(disable:4355) // Temporarily disables warning 4355.
|
||||
#endif // _MSV_VER
|
||||
|
||||
// C++ treats the void type specially. For example, you cannot define
|
||||
// a void-typed variable or pass a void value to a function.
|
||||
// ActionResultHolder<T> holds a value of type T, where T must be a
|
||||
// copyable type or void (T doesn't need to be default-constructable).
|
||||
// It hides the syntactic difference between void and other types, and
|
||||
// is used to unify the code for invoking both void-returning and
|
||||
// non-void-returning mock functions. This generic definition is used
|
||||
// when T is not void.
|
||||
template <typename T>
|
||||
class ActionResultHolder {
|
||||
public:
|
||||
explicit ActionResultHolder(T value) : value_(value) {}
|
||||
|
||||
// The compiler-generated copy constructor and assignment operator
|
||||
// are exactly what we need, so we don't need to define them.
|
||||
|
||||
T value() const { return value_; }
|
||||
|
||||
// Prints the held value as an action's result to os.
|
||||
void PrintAsActionResult(::std::ostream* os) const {
|
||||
*os << "\n Returns: ";
|
||||
UniversalPrinter<T>::Print(value_, os);
|
||||
}
|
||||
|
||||
// Performs the given mock function's default action and returns the
|
||||
// result in a ActionResultHolder.
|
||||
template <typename Function, typename Arguments>
|
||||
static ActionResultHolder PerformDefaultAction(
|
||||
const FunctionMockerBase<Function>* func_mocker,
|
||||
const Arguments& args,
|
||||
const string& call_description) {
|
||||
return ActionResultHolder(
|
||||
func_mocker->PerformDefaultAction(args, call_description));
|
||||
}
|
||||
|
||||
// Performs the given action and returns the result in a
|
||||
// ActionResultHolder.
|
||||
template <typename Function, typename Arguments>
|
||||
static ActionResultHolder PerformAction(const Action<Function>& action,
|
||||
const Arguments& args) {
|
||||
return ActionResultHolder(action.Perform(args));
|
||||
}
|
||||
|
||||
private:
|
||||
T value_;
|
||||
};
|
||||
|
||||
// Specialization for T = void.
|
||||
template <>
|
||||
class ActionResultHolder<void> {
|
||||
public:
|
||||
ActionResultHolder() {}
|
||||
void value() const {}
|
||||
void PrintAsActionResult(::std::ostream* /* os */) const {}
|
||||
|
||||
template <typename Function, typename Arguments>
|
||||
static ActionResultHolder PerformDefaultAction(
|
||||
const FunctionMockerBase<Function>* func_mocker,
|
||||
const Arguments& args,
|
||||
const string& call_description) {
|
||||
func_mocker->PerformDefaultAction(args, call_description);
|
||||
return ActionResultHolder();
|
||||
}
|
||||
|
||||
template <typename Function, typename Arguments>
|
||||
static ActionResultHolder PerformAction(const Action<Function>& action,
|
||||
const Arguments& args) {
|
||||
action.Perform(args);
|
||||
return ActionResultHolder();
|
||||
}
|
||||
};
|
||||
|
||||
// The base of the function mocker class for the given function type.
|
||||
// We put the methods in this class instead of its child to avoid code
|
||||
// bloat.
|
||||
@@ -1167,16 +1229,11 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
|
||||
template <typename Function>
|
||||
friend class MockSpec;
|
||||
|
||||
template <typename R, typename Function>
|
||||
friend class InvokeWithHelper;
|
||||
|
||||
// Returns the result of invoking this mock function with the given
|
||||
// arguments. This function can be safely called from multiple
|
||||
// threads concurrently.
|
||||
// L < g_gmock_mutex
|
||||
Result InvokeWith(const ArgumentTuple& args) {
|
||||
return InvokeWithHelper<Result, F>::InvokeAndPrintResult(this, args);
|
||||
}
|
||||
Result InvokeWith(const ArgumentTuple& args);
|
||||
|
||||
// Adds and returns a default action spec for this mock function.
|
||||
// L < g_gmock_mutex
|
||||
@@ -1417,170 +1474,109 @@ bool FunctionMockerBase<F>::VerifyAndClearExpectationsLocked() {
|
||||
// manner specified by 'reaction'.
|
||||
void ReportUninterestingCall(CallReaction reaction, const string& msg);
|
||||
|
||||
// When an uninteresting or unexpected mock function is called, we
|
||||
// want to print its return value to assist the user debugging. Since
|
||||
// there's nothing to print when the function returns void, we need to
|
||||
// specialize the logic of FunctionMockerBase<F>::InvokeWith() for
|
||||
// void return values.
|
||||
//
|
||||
// C++ doesn't allow us to specialize a member function template
|
||||
// unless we also specialize its enclosing class, so we had to let
|
||||
// InvokeWith() delegate its work to a helper class InvokeWithHelper,
|
||||
// which can then be specialized.
|
||||
//
|
||||
// Note that InvokeWithHelper must be a class template (as opposed to
|
||||
// a function template), as only class templates can be partially
|
||||
// specialized.
|
||||
template <typename Result, typename F>
|
||||
class InvokeWithHelper {
|
||||
public:
|
||||
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
|
||||
|
||||
// Calculates the result of invoking the function mocked by mocker
|
||||
// with the given arguments, prints it, and returns it.
|
||||
// L < g_gmock_mutex
|
||||
static Result InvokeAndPrintResult(
|
||||
FunctionMockerBase<F>* mocker,
|
||||
const ArgumentTuple& args) {
|
||||
if (mocker->expectations_.size() == 0) {
|
||||
// No expectation is set on this mock method - we have an
|
||||
// uninteresting call.
|
||||
|
||||
// Warns about the uninteresting call.
|
||||
::std::stringstream ss;
|
||||
mocker->DescribeUninterestingCall(args, &ss);
|
||||
|
||||
// We must get Google Mock's reaction on uninteresting calls
|
||||
// made on this mock object BEFORE performing the action,
|
||||
// because the action may DELETE the mock object and make the
|
||||
// following expression meaningless.
|
||||
const CallReaction reaction =
|
||||
Mock::GetReactionOnUninterestingCalls(mocker->MockObject());
|
||||
|
||||
// Calculates the function result.
|
||||
Result result = mocker->PerformDefaultAction(args, ss.str());
|
||||
|
||||
// Prints the function result.
|
||||
ss << "\n Returns: ";
|
||||
UniversalPrinter<Result>::Print(result, &ss);
|
||||
ReportUninterestingCall(reaction, ss.str());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool is_excessive = false;
|
||||
::std::stringstream ss;
|
||||
::std::stringstream why;
|
||||
::std::stringstream loc;
|
||||
Action<F> action;
|
||||
Expectation<F>* exp;
|
||||
|
||||
// The FindMatchingExpectationAndAction() function acquires and
|
||||
// releases g_gmock_mutex.
|
||||
const bool found = mocker->FindMatchingExpectationAndAction(
|
||||
args, &exp, &action, &is_excessive, &ss, &why);
|
||||
ss << " Function call: " << mocker->Name();
|
||||
UniversalPrinter<ArgumentTuple>::Print(args, &ss);
|
||||
// In case the action deletes a piece of the expectation, we
|
||||
// generate the message beforehand.
|
||||
if (found && !is_excessive) {
|
||||
exp->DescribeLocationTo(&loc);
|
||||
}
|
||||
Result result = action.IsDoDefault() ?
|
||||
mocker->PerformDefaultAction(args, ss.str())
|
||||
: action.Perform(args);
|
||||
ss << "\n Returns: ";
|
||||
UniversalPrinter<Result>::Print(result, &ss);
|
||||
ss << "\n" << why.str();
|
||||
|
||||
if (found) {
|
||||
if (is_excessive) {
|
||||
// We had an upper-bound violation and the failure message is in ss.
|
||||
Expect(false, exp->file(), exp->line(), ss.str());
|
||||
} else {
|
||||
// We had an expected call and the matching expectation is
|
||||
// described in ss.
|
||||
Log(INFO, loc.str() + ss.str(), 3);
|
||||
}
|
||||
} else {
|
||||
// No expectation matches this call - reports a failure.
|
||||
Expect(false, NULL, -1, ss.str());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}; // class InvokeWithHelper
|
||||
|
||||
// This specialization helps to implement
|
||||
// FunctionMockerBase<F>::InvokeWith() for void-returning functions.
|
||||
// Calculates the result of invoking this mock function with the given
|
||||
// arguments, prints it, and returns it.
|
||||
// L < g_gmock_mutex
|
||||
template <typename F>
|
||||
class InvokeWithHelper<void, F> {
|
||||
public:
|
||||
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
|
||||
typename Function<F>::Result FunctionMockerBase<F>::InvokeWith(
|
||||
const typename Function<F>::ArgumentTuple& args) {
|
||||
typedef ActionResultHolder<Result> ResultHolder;
|
||||
|
||||
// Invokes the function mocked by mocker with the given arguments.
|
||||
// L < g_gmock_mutex
|
||||
static void InvokeAndPrintResult(FunctionMockerBase<F>* mocker,
|
||||
const ArgumentTuple& args) {
|
||||
const int count = static_cast<int>(mocker->expectations_.size());
|
||||
if (count == 0) {
|
||||
// No expectation is set on this mock method - we have an
|
||||
// uninteresting call.
|
||||
::std::stringstream ss;
|
||||
mocker->DescribeUninterestingCall(args, &ss);
|
||||
if (expectations_.size() == 0) {
|
||||
// No expectation is set on this mock method - we have an
|
||||
// uninteresting call.
|
||||
|
||||
// We must get Google Mock's reaction on uninteresting calls
|
||||
// made on this mock object BEFORE performing the action,
|
||||
// because the action may DELETE the mock object and make the
|
||||
// following expression meaningless.
|
||||
const CallReaction reaction =
|
||||
Mock::GetReactionOnUninterestingCalls(mocker->MockObject());
|
||||
// We must get Google Mock's reaction on uninteresting calls
|
||||
// made on this mock object BEFORE performing the action,
|
||||
// because the action may DELETE the mock object and make the
|
||||
// following expression meaningless.
|
||||
const CallReaction reaction =
|
||||
Mock::GetReactionOnUninterestingCalls(MockObject());
|
||||
|
||||
mocker->PerformDefaultAction(args, ss.str());
|
||||
ReportUninterestingCall(reaction, ss.str());
|
||||
return;
|
||||
// True iff we need to print this call's arguments and return
|
||||
// value. This definition must be kept in sync with
|
||||
// the behavior of ReportUninterestingCall().
|
||||
const bool need_to_report_uninteresting_call =
|
||||
// If the user allows this uninteresting call, we print it
|
||||
// only when he wants informational messages.
|
||||
reaction == ALLOW ? LogIsVisible(INFO) :
|
||||
// If the user wants this to be a warning, we print it only
|
||||
// when he wants to see warnings.
|
||||
reaction == WARN ? LogIsVisible(WARNING) :
|
||||
// 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) {
|
||||
// Perform the action without printing the call information.
|
||||
return PerformDefaultAction(args, "");
|
||||
}
|
||||
|
||||
bool is_excessive = false;
|
||||
// Warns about the uninteresting call.
|
||||
::std::stringstream ss;
|
||||
::std::stringstream why;
|
||||
::std::stringstream loc;
|
||||
Action<F> action;
|
||||
Expectation<F>* exp;
|
||||
DescribeUninterestingCall(args, &ss);
|
||||
|
||||
// The FindMatchingExpectationAndAction() function acquires and
|
||||
// releases g_gmock_mutex.
|
||||
const bool found = mocker->FindMatchingExpectationAndAction(
|
||||
args, &exp, &action, &is_excessive, &ss, &why);
|
||||
ss << " Function call: " << mocker->Name();
|
||||
UniversalPrinter<ArgumentTuple>::Print(args, &ss);
|
||||
ss << "\n" << why.str();
|
||||
// In case the action deletes a piece of the expectation, we
|
||||
// generate the message beforehand.
|
||||
if (found && !is_excessive) {
|
||||
exp->DescribeLocationTo(&loc);
|
||||
}
|
||||
if (action.IsDoDefault()) {
|
||||
mocker->PerformDefaultAction(args, ss.str());
|
||||
} else {
|
||||
action.Perform(args);
|
||||
}
|
||||
// Calculates the function result.
|
||||
const ResultHolder result =
|
||||
ResultHolder::PerformDefaultAction(this, args, ss.str());
|
||||
|
||||
if (found) {
|
||||
// A matching expectation and corresponding action were found.
|
||||
if (is_excessive) {
|
||||
// We had an upper-bound violation and the failure message is in ss.
|
||||
Expect(false, exp->file(), exp->line(), ss.str());
|
||||
} else {
|
||||
// We had an expected call and the matching expectation is
|
||||
// described in ss.
|
||||
Log(INFO, loc.str() + ss.str(), 3);
|
||||
}
|
||||
} else {
|
||||
// No matching expectation was found - reports an error.
|
||||
Expect(false, NULL, -1, ss.str());
|
||||
}
|
||||
// Prints the function result.
|
||||
result.PrintAsActionResult(&ss);
|
||||
|
||||
ReportUninterestingCall(reaction, ss.str());
|
||||
return result.value();
|
||||
}
|
||||
}; // class InvokeWithHelper<void, F>
|
||||
|
||||
bool is_excessive = false;
|
||||
::std::stringstream ss;
|
||||
::std::stringstream why;
|
||||
::std::stringstream loc;
|
||||
Action<F> action;
|
||||
Expectation<F>* exp;
|
||||
|
||||
// The FindMatchingExpectationAndAction() function acquires and
|
||||
// releases g_gmock_mutex.
|
||||
const bool found = FindMatchingExpectationAndAction(
|
||||
args, &exp, &action, &is_excessive, &ss, &why);
|
||||
|
||||
// True iff we need to print the call's arguments and return value.
|
||||
// This definition must be kept in sync with the uses of Expect()
|
||||
// and Log() in this function.
|
||||
const bool need_to_report_call = !found || is_excessive || LogIsVisible(INFO);
|
||||
if (!need_to_report_call) {
|
||||
// Perform the action without printing the call information.
|
||||
return action.IsDoDefault() ? PerformDefaultAction(args, "") :
|
||||
action.Perform(args);
|
||||
}
|
||||
|
||||
ss << " Function call: " << Name();
|
||||
UniversalPrinter<ArgumentTuple>::Print(args, &ss);
|
||||
|
||||
// In case the action deletes a piece of the expectation, we
|
||||
// generate the message beforehand.
|
||||
if (found && !is_excessive) {
|
||||
exp->DescribeLocationTo(&loc);
|
||||
}
|
||||
|
||||
const ResultHolder result = action.IsDoDefault() ?
|
||||
ResultHolder::PerformDefaultAction(this, args, ss.str()) :
|
||||
ResultHolder::PerformAction(action, args);
|
||||
result.PrintAsActionResult(&ss);
|
||||
ss << "\n" << why.str();
|
||||
|
||||
if (!found) {
|
||||
// No expectation matches this call - reports a failure.
|
||||
Expect(false, NULL, -1, ss.str());
|
||||
} else if (is_excessive) {
|
||||
// We had an upper-bound violation and the failure message is in ss.
|
||||
Expect(false, exp->file(), exp->line(), ss.str());
|
||||
} else {
|
||||
// We had an expected call and the matching expectation is
|
||||
// described in ss.
|
||||
Log(INFO, loc.str() + ss.str(), 2);
|
||||
}
|
||||
return result.value();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
||||
@@ -39,14 +39,14 @@
|
||||
// This file implements the following syntax:
|
||||
//
|
||||
// ON_CALL(mock_object.Method(...))
|
||||
// .WithArguments(...) ?
|
||||
// .With(...) ?
|
||||
// .WillByDefault(...);
|
||||
//
|
||||
// where WithArguments() is optional and WillByDefault() must appear
|
||||
// exactly once.
|
||||
// where With() is optional and WillByDefault() must appear exactly
|
||||
// once.
|
||||
//
|
||||
// EXPECT_CALL(mock_object.Method(...))
|
||||
// .WithArguments(...) ?
|
||||
// .With(...) ?
|
||||
// .Times(...) ?
|
||||
// .InSequence(...) *
|
||||
// .WillOnce(...) *
|
||||
|
||||
@@ -99,6 +99,17 @@ struct RemoveConst { typedef T type; }; // NOLINT
|
||||
template <typename T>
|
||||
struct RemoveConst<const T> { typedef T type; }; // NOLINT
|
||||
|
||||
// MSVC 8.0 has a bug which causes the above definition to fail to
|
||||
// remove the const in 'const int[3]'. The following specialization
|
||||
// works around the bug. However, it causes trouble with gcc and thus
|
||||
// needs to be conditionally compiled.
|
||||
#ifdef _MSC_VER
|
||||
template <typename T, size_t N>
|
||||
struct RemoveConst<T[N]> {
|
||||
typedef typename RemoveConst<T>::type type[N];
|
||||
};
|
||||
#endif // _MSC_VER
|
||||
|
||||
// A handy wrapper around RemoveConst that works when the argument
|
||||
// T depends on template parameters.
|
||||
#define GMOCK_REMOVE_CONST_(T) \
|
||||
@@ -438,6 +449,10 @@ const char kWarningVerbosity[] = "warning";
|
||||
// No logs are printed.
|
||||
const char kErrorVerbosity[] = "error";
|
||||
|
||||
// Returns true iff a log with the given severity is visible according
|
||||
// to the --gmock_verbose flag.
|
||||
bool LogIsVisible(LogSeverity severity);
|
||||
|
||||
// Prints the given message to stdout iff 'severity' >= the level
|
||||
// specified by the --gmock_verbose flag. If stack_frames_to_skip >=
|
||||
// 0, also prints the stack trace excluding the top
|
||||
@@ -447,10 +462,6 @@ const char kErrorVerbosity[] = "error";
|
||||
// conservative.
|
||||
void Log(LogSeverity severity, const string& message, int stack_frames_to_skip);
|
||||
|
||||
// The universal value printer (public/gmock-printers.h) needs this
|
||||
// to declare an unused << operator in the global namespace.
|
||||
struct Unused {};
|
||||
|
||||
// TODO(wan@google.com): group all type utilities together.
|
||||
|
||||
// Type traits.
|
||||
@@ -478,6 +489,238 @@ inline T Invalid() {
|
||||
template <>
|
||||
inline void Invalid<void>() {}
|
||||
|
||||
// Utilities for native arrays.
|
||||
|
||||
// ArrayEq() compares two k-dimensional native arrays using the
|
||||
// elements' operator==, where k can be any integer >= 0. When k is
|
||||
// 0, ArrayEq() degenerates into comparing a single pair of values.
|
||||
|
||||
template <typename T, typename U>
|
||||
bool ArrayEq(const T* lhs, size_t size, const U* rhs);
|
||||
|
||||
// This generic version is used when k is 0.
|
||||
template <typename T, typename U>
|
||||
inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
|
||||
|
||||
// This overload is used when k >= 1.
|
||||
template <typename T, typename U, size_t N>
|
||||
inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
|
||||
return internal::ArrayEq(lhs, N, rhs);
|
||||
}
|
||||
|
||||
// This helper reduces code bloat. If we instead put its logic inside
|
||||
// the previous ArrayEq() function, arrays with different sizes would
|
||||
// lead to different copies of the template code.
|
||||
template <typename T, typename U>
|
||||
bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
|
||||
for (size_t i = 0; i != size; i++) {
|
||||
if (!internal::ArrayEq(lhs[i], rhs[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Finds the first element in the iterator range [begin, end) that
|
||||
// equals elem. Element may be a native array type itself.
|
||||
template <typename Iter, typename Element>
|
||||
Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
|
||||
for (Iter it = begin; it != end; ++it) {
|
||||
if (internal::ArrayEq(*it, elem))
|
||||
return it;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
// CopyArray() copies a k-dimensional native array using the elements'
|
||||
// operator=, where k can be any integer >= 0. When k is 0,
|
||||
// CopyArray() degenerates into copying a single value.
|
||||
|
||||
template <typename T, typename U>
|
||||
void CopyArray(const T* from, size_t size, U* to);
|
||||
|
||||
// This generic version is used when k is 0.
|
||||
template <typename T, typename U>
|
||||
inline void CopyArray(const T& from, U* to) { *to = from; }
|
||||
|
||||
// This overload is used when k >= 1.
|
||||
template <typename T, typename U, size_t N>
|
||||
inline void CopyArray(const T(&from)[N], U(*to)[N]) {
|
||||
internal::CopyArray(from, N, *to);
|
||||
}
|
||||
|
||||
// This helper reduces code bloat. If we instead put its logic inside
|
||||
// the previous CopyArray() function, arrays with different sizes
|
||||
// would lead to different copies of the template code.
|
||||
template <typename T, typename U>
|
||||
void CopyArray(const T* from, size_t size, U* to) {
|
||||
for (size_t i = 0; i != size; i++) {
|
||||
internal::CopyArray(from[i], to + i);
|
||||
}
|
||||
}
|
||||
|
||||
// The relation between an NativeArray object (see below) and the
|
||||
// native array it represents.
|
||||
enum RelationToSource {
|
||||
kReference, // The NativeArray references the native array.
|
||||
kCopy // The NativeArray makes a copy of the native array and
|
||||
// owns the copy.
|
||||
};
|
||||
|
||||
// Adapts a native array to a read-only STL-style container. Instead
|
||||
// of the complete STL container concept, this adaptor only implements
|
||||
// members useful for Google Mock's container matchers. New members
|
||||
// should be added as needed. To simplify the implementation, we only
|
||||
// support Element being a raw type (i.e. having no top-level const or
|
||||
// reference modifier). It's the client's responsibility to satisfy
|
||||
// this requirement. Element can be an array type itself (hence
|
||||
// multi-dimensional arrays are supported).
|
||||
template <typename Element>
|
||||
class NativeArray {
|
||||
public:
|
||||
// STL-style container typedefs.
|
||||
typedef Element value_type;
|
||||
typedef const Element* const_iterator;
|
||||
|
||||
// Constructs from a native array passed by reference.
|
||||
template <size_t N>
|
||||
NativeArray(const Element (&array)[N], RelationToSource relation) {
|
||||
Init(array, N, relation);
|
||||
}
|
||||
|
||||
// Constructs from a native array passed by a pointer and a size.
|
||||
// For generality we don't artificially restrict the types of the
|
||||
// pointer and the size.
|
||||
template <typename Pointer, typename Size>
|
||||
NativeArray(const ::std::tr1::tuple<Pointer, Size>& array,
|
||||
RelationToSource relation) {
|
||||
Init(internal::GetRawPointer(::std::tr1::get<0>(array)),
|
||||
::std::tr1::get<1>(array),
|
||||
relation);
|
||||
}
|
||||
|
||||
// Copy constructor.
|
||||
NativeArray(const NativeArray& rhs) {
|
||||
Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
|
||||
}
|
||||
|
||||
~NativeArray() {
|
||||
// Ensures that the user doesn't instantiate NativeArray with a
|
||||
// const or reference type.
|
||||
testing::StaticAssertTypeEq<Element,
|
||||
GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Element))>();
|
||||
if (relation_to_source_ == kCopy)
|
||||
delete[] array_;
|
||||
}
|
||||
|
||||
// STL-style container methods.
|
||||
size_t size() const { return size_; }
|
||||
const_iterator begin() const { return array_; }
|
||||
const_iterator end() const { return array_ + size_; }
|
||||
bool operator==(const NativeArray& rhs) const {
|
||||
return size() == rhs.size() &&
|
||||
ArrayEq(begin(), size(), rhs.begin());
|
||||
}
|
||||
|
||||
private:
|
||||
// Not implemented as we don't want to support assignment.
|
||||
void operator=(const NativeArray& rhs);
|
||||
|
||||
// Initializes this object; makes a copy of the input array if
|
||||
// 'relation' is kCopy.
|
||||
void Init(const Element* array, size_t size, RelationToSource relation) {
|
||||
if (relation == kReference) {
|
||||
array_ = array;
|
||||
} else {
|
||||
Element* const copy = new Element[size];
|
||||
CopyArray(array, size, copy);
|
||||
array_ = copy;
|
||||
}
|
||||
size_ = size;
|
||||
relation_to_source_ = relation;
|
||||
}
|
||||
|
||||
const Element* array_;
|
||||
size_t size_;
|
||||
RelationToSource relation_to_source_;
|
||||
};
|
||||
|
||||
// Given a raw type (i.e. having no top-level reference or const
|
||||
// modifier) RawContainer that's either an STL-style container or a
|
||||
// native array, class StlContainerView<RawContainer> has the
|
||||
// following members:
|
||||
//
|
||||
// - type is a type that provides an STL-style container view to
|
||||
// (i.e. implements the STL container concept for) RawContainer;
|
||||
// - const_reference is a type that provides a reference to a const
|
||||
// RawContainer;
|
||||
// - ConstReference(raw_container) returns a const reference to an STL-style
|
||||
// container view to raw_container, which is a RawContainer.
|
||||
// - Copy(raw_container) returns an STL-style container view of a
|
||||
// copy of raw_container, which is a RawContainer.
|
||||
//
|
||||
// This generic version is used when RawContainer itself is already an
|
||||
// STL-style container.
|
||||
template <class RawContainer>
|
||||
class StlContainerView {
|
||||
public:
|
||||
typedef RawContainer type;
|
||||
typedef const type& const_reference;
|
||||
|
||||
static const_reference ConstReference(const RawContainer& container) {
|
||||
// Ensures that RawContainer is not a const type.
|
||||
testing::StaticAssertTypeEq<RawContainer,
|
||||
GMOCK_REMOVE_CONST_(RawContainer)>();
|
||||
return container;
|
||||
}
|
||||
static type Copy(const RawContainer& container) { return container; }
|
||||
};
|
||||
|
||||
// This specialization is used when RawContainer is a native array type.
|
||||
template <typename Element, size_t N>
|
||||
class StlContainerView<Element[N]> {
|
||||
public:
|
||||
typedef GMOCK_REMOVE_CONST_(Element) RawElement;
|
||||
typedef internal::NativeArray<RawElement> type;
|
||||
// NativeArray<T> can represent a native array either by value or by
|
||||
// reference (selected by a constructor argument), so 'const type'
|
||||
// can be used to reference a const native array. We cannot
|
||||
// 'typedef const type& const_reference' here, as that would mean
|
||||
// ConstReference() has to return a reference to a local variable.
|
||||
typedef const type const_reference;
|
||||
|
||||
static const_reference ConstReference(const Element (&array)[N]) {
|
||||
// Ensures that Element is not a const type.
|
||||
testing::StaticAssertTypeEq<Element, RawElement>();
|
||||
return type(array, kReference);
|
||||
}
|
||||
static type Copy(const Element (&array)[N]) {
|
||||
return type(array, kCopy);
|
||||
}
|
||||
};
|
||||
|
||||
// This specialization is used when RawContainer is a native array
|
||||
// represented as a (pointer, size) tuple.
|
||||
template <typename ElementPointer, typename Size>
|
||||
class StlContainerView< ::std::tr1::tuple<ElementPointer, Size> > {
|
||||
public:
|
||||
typedef GMOCK_REMOVE_CONST_(
|
||||
typename internal::PointeeOf<ElementPointer>::type) RawElement;
|
||||
typedef internal::NativeArray<RawElement> type;
|
||||
typedef const type const_reference;
|
||||
|
||||
static const_reference ConstReference(
|
||||
const ::std::tr1::tuple<ElementPointer, Size>& array) {
|
||||
return type(array, kReference);
|
||||
}
|
||||
static type Copy(const ::std::tr1::tuple<ElementPointer, Size>& array) {
|
||||
return type(array, kCopy);
|
||||
}
|
||||
};
|
||||
|
||||
// The following specialization prevents the user from instantiating
|
||||
// StlContainer with a reference type.
|
||||
template <typename T> class StlContainerView<T&>;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
|
||||
@@ -47,23 +47,8 @@
|
||||
|
||||
// To avoid conditional compilation everywhere, we make it
|
||||
// gmock-port.h's responsibility to #include the header implementing
|
||||
// tr1/tuple.
|
||||
#if defined(__GNUC__) && GTEST_GCC_VER_ >= 40000
|
||||
// GTEST_GCC_VER_ is defined in gtest-port.h and 40000 corresponds to
|
||||
// version 4.0.0.
|
||||
// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header. This does
|
||||
// not conform to the TR1 spec, which requires the header to be <tuple>.
|
||||
#include <tr1/tuple>
|
||||
#elif defined(_MSC_VER) && _MSC_VER < 1500
|
||||
// For Visual Studio older than 2008, we redirect directly to boost tuple
|
||||
// searching from boost's root. This is to avoid extra dirtying of the
|
||||
// compiler include paths.
|
||||
#include "boost/tr1/tr1/tuple"
|
||||
#else
|
||||
// If the compiler is neither GCC 4.0+, nor Visual Studio 2008, we assume the
|
||||
// user is using a spec-conforming TR1 implementation.
|
||||
#include <tuple>
|
||||
#endif // __GNUC__
|
||||
// tr1/tuple. gmock-port.h does this via gtest-port.h, which is
|
||||
// guaranteed to pull in the tuple header.
|
||||
|
||||
#if GTEST_OS_LINUX
|
||||
|
||||
|
||||
@@ -1,326 +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.
|
||||
//
|
||||
// Author: vadimb@google.com (Vadim Berman)
|
||||
//
|
||||
// Low-level types and utilities for porting Google Mock to various
|
||||
// platforms. They are subject to change without notice. DO NOT USE
|
||||
// THEM IN USER CODE.
|
||||
|
||||
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
|
||||
#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
|
||||
// Most of the types needed for porting Google Mock are also required
|
||||
// for Google Test and are defined in gtest-port.h.
|
||||
#include <gtest/internal/gtest-linked_ptr.h>
|
||||
#include <gtest/internal/gtest-port.h>
|
||||
|
||||
// To avoid conditional compilation everywhere, we make it
|
||||
// gmock-port.h's responsibility to #include the header implementing
|
||||
// tr1/tuple.
|
||||
#if defined(__GNUC__) && GTEST_GCC_VER_ >= 40000
|
||||
// GTEST_GCC_VER_ is defined in gtest-port.h and 40000 corresponds to
|
||||
// version 4.0.0.
|
||||
// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header. This does
|
||||
// not conform to the TR1 spec, which requires the header to be <tuple>.
|
||||
#include <tr1/tuple>
|
||||
#elif defined(_MSC_VER) && _MSC_VER < 1500
|
||||
// For Visual Studio older than 2008, we redirect directly to boost tuple
|
||||
// searching from boost's root. This is to avoid extra dirtying of the
|
||||
// compiler include paths.
|
||||
#include "boost/tr1/tr1/tuple"
|
||||
#else
|
||||
// If the compiler is not GCC 4.0+, or Visual Studio 2008, we assume the
|
||||
// user is using a spec-conforming TR1 implementation.
|
||||
#include <tuple>
|
||||
#endif // __GNUC__
|
||||
|
||||
#if GTEST_OS_LINUX
|
||||
|
||||
// On some platforms, <regex.h> needs someone to define size_t, and
|
||||
// won't compile otherwise. We can #include it here as we already
|
||||
// included <stdlib.h>, which is guaranteed to define size_t through
|
||||
// <stddef.h>.
|
||||
#include <regex.h> // NOLINT
|
||||
|
||||
// Defines this iff Google Mock uses the enhanced POSIX regular
|
||||
// expression syntax. This is public as it affects how a user uses
|
||||
// regular expression matchers.
|
||||
#define GMOCK_USES_POSIX_RE 1
|
||||
|
||||
#endif // GTEST_OS_LINUX
|
||||
|
||||
#if defined(GMOCK_USES_PCRE) || defined(GMOCK_USES_POSIX_RE)
|
||||
// Defines this iff regular expression matchers are supported. This
|
||||
// is public as it tells a user whether he can use regular expression
|
||||
// matchers.
|
||||
#define GMOCK_HAS_REGEX 1
|
||||
#endif // defined(GMOCK_USES_PCRE) || defined(GMOCK_USES_POSIX_RE)
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// For Windows, check the compiler version. At least VS 2005 SP1 is
|
||||
// required to compile Google Mock.
|
||||
#if GTEST_OS_WINDOWS
|
||||
|
||||
#if _MSC_VER < 1400
|
||||
#error "At least Visual Studio 2005 SP1 is required to compile Google Mock."
|
||||
#elif _MSC_VER == 1400
|
||||
|
||||
// Unfortunately there is no unique _MSC_VER number for SP1. So for VS 2005
|
||||
// we have to check if it has SP1 by checking whether a bug fixed in SP1
|
||||
// is present. The bug in question is
|
||||
// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101702
|
||||
// where the compiler incorrectly reports sizeof(poiter to an array).
|
||||
|
||||
class TestForSP1 {
|
||||
private: // GCC complains if x_ is used by sizeof before defining it.
|
||||
static char x_[100];
|
||||
// VS 2005 RTM incorrectly reports sizeof(&x) as 100, and that value
|
||||
// is used to trigger 'invalid negative array size' error. If you
|
||||
// see this error, upgrade to VS 2005 SP1 since Google Mock will not
|
||||
// compile in VS 2005 RTM.
|
||||
static char Google_Mock_requires_Visual_Studio_2005_SP1_or_later_to_compile_[
|
||||
sizeof(&x_) != 100 ? 1 : -1];
|
||||
};
|
||||
|
||||
#endif // _MSC_VER
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
// Use implicit_cast as a safe version of static_cast or const_cast
|
||||
// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
|
||||
// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
|
||||
// a const pointer to Foo).
|
||||
// When you use implicit_cast, the compiler checks that the cast is safe.
|
||||
// Such explicit implicit_casts are necessary in surprisingly many
|
||||
// situations where C++ demands an exact type match instead of an
|
||||
// argument type convertable to a target type.
|
||||
//
|
||||
// The From type can be inferred, so the preferred syntax for using
|
||||
// implicit_cast is the same as for static_cast etc.:
|
||||
//
|
||||
// implicit_cast<ToType>(expr)
|
||||
//
|
||||
// implicit_cast would have been part of the C++ standard library,
|
||||
// but the proposal was submitted too late. It will probably make
|
||||
// its way into the language in the future.
|
||||
template<typename To, typename From>
|
||||
inline To implicit_cast(From const &f) {
|
||||
return f;
|
||||
}
|
||||
|
||||
// When you upcast (that is, cast a pointer from type Foo to type
|
||||
// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
|
||||
// always succeed. When you downcast (that is, cast a pointer from
|
||||
// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
|
||||
// how do you know the pointer is really of type SubclassOfFoo? It
|
||||
// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
|
||||
// when you downcast, you should use this macro. In debug mode, we
|
||||
// use dynamic_cast<> to double-check the downcast is legal (we die
|
||||
// if it's not). In normal mode, we do the efficient static_cast<>
|
||||
// instead. Thus, it's important to test in debug mode to make sure
|
||||
// the cast is legal!
|
||||
// This is the only place in the code we should use dynamic_cast<>.
|
||||
// In particular, you SHOULDN'T be using dynamic_cast<> in order to
|
||||
// do RTTI (eg code like this:
|
||||
// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
|
||||
// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
|
||||
// You should design the code some other way not to need this.
|
||||
template<typename To, typename From> // use like this: down_cast<T*>(foo);
|
||||
inline To down_cast(From* f) { // so we only accept pointers
|
||||
// Ensures that To is a sub-type of From *. This test is here only
|
||||
// for compile-time type checking, and has no overhead in an
|
||||
// optimized build at run-time, as it will be optimized away
|
||||
// completely.
|
||||
if (false) {
|
||||
implicit_cast<From*, To>(0);
|
||||
}
|
||||
|
||||
#if GTEST_HAS_RTTI
|
||||
assert(f == NULL || dynamic_cast<To>(f) != NULL); // RTTI: debug mode only!
|
||||
#endif
|
||||
return static_cast<To>(f);
|
||||
}
|
||||
|
||||
// The GMOCK_COMPILE_ASSERT_ macro can be used to verify that a compile time
|
||||
// expression is true. For example, you could use it to verify the
|
||||
// size of a static array:
|
||||
//
|
||||
// GMOCK_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
|
||||
// content_type_names_incorrect_size);
|
||||
//
|
||||
// or to make sure a struct is smaller than a certain size:
|
||||
//
|
||||
// GMOCK_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large);
|
||||
//
|
||||
// The second argument to the macro is the name of the variable. If
|
||||
// the expression is false, most compilers will issue a warning/error
|
||||
// containing the name of the variable.
|
||||
|
||||
template <bool>
|
||||
struct CompileAssert {
|
||||
};
|
||||
|
||||
#define GMOCK_COMPILE_ASSERT_(expr, msg) \
|
||||
typedef ::testing::internal::CompileAssert<(bool(expr))> \
|
||||
msg[bool(expr) ? 1 : -1]
|
||||
|
||||
// Implementation details of GMOCK_COMPILE_ASSERT_:
|
||||
//
|
||||
// - GMOCK_COMPILE_ASSERT_ works by defining an array type that has -1
|
||||
// elements (and thus is invalid) when the expression is false.
|
||||
//
|
||||
// - The simpler definition
|
||||
//
|
||||
// #define GMOCK_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1]
|
||||
//
|
||||
// does not work, as gcc supports variable-length arrays whose sizes
|
||||
// are determined at run-time (this is gcc's extension and not part
|
||||
// of the C++ standard). As a result, gcc fails to reject the
|
||||
// following code with the simple definition:
|
||||
//
|
||||
// int foo;
|
||||
// GMOCK_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is
|
||||
// // not a compile-time constant.
|
||||
//
|
||||
// - By using the type CompileAssert<(bool(expr))>, we ensures that
|
||||
// expr is a compile-time constant. (Template arguments must be
|
||||
// determined at compile-time.)
|
||||
//
|
||||
// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
|
||||
// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
|
||||
//
|
||||
// CompileAssert<bool(expr)>
|
||||
//
|
||||
// instead, these compilers will refuse to compile
|
||||
//
|
||||
// GMOCK_COMPILE_ASSERT_(5 > 0, some_message);
|
||||
//
|
||||
// (They seem to think the ">" in "5 > 0" marks the end of the
|
||||
// template argument list.)
|
||||
//
|
||||
// - The array size is (bool(expr) ? 1 : -1), instead of simply
|
||||
//
|
||||
// ((expr) ? 1 : -1).
|
||||
//
|
||||
// This is to avoid running into a bug in MS VC 7.1, which
|
||||
// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
|
||||
|
||||
#if GTEST_HAS_GLOBAL_STRING
|
||||
typedef ::string string;
|
||||
#elif GTEST_HAS_STD_STRING
|
||||
typedef ::std::string string;
|
||||
#else
|
||||
#error "Google Mock requires ::std::string to compile."
|
||||
#endif // GTEST_HAS_GLOBAL_STRING
|
||||
|
||||
#if GTEST_HAS_GLOBAL_WSTRING
|
||||
typedef ::wstring wstring;
|
||||
#elif GTEST_HAS_STD_WSTRING
|
||||
typedef ::std::wstring wstring;
|
||||
#endif // GTEST_HAS_GLOBAL_WSTRING
|
||||
|
||||
// Prints the file location in the format native to the compiler.
|
||||
inline void FormatFileLocation(const char* file, int line, ::std::ostream* os) {
|
||||
if (file == NULL)
|
||||
file = "unknown file";
|
||||
if (line < 0) {
|
||||
*os << file << ":";
|
||||
} else {
|
||||
#if _MSC_VER
|
||||
*os << file << "(" << line << "):";
|
||||
#else
|
||||
*os << file << ":" << line << ":";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE.
|
||||
//
|
||||
// GMOCK_CHECK_ is an all mode assert. It aborts the program if the condition
|
||||
// is not satisfied.
|
||||
// Synopsys:
|
||||
// GMOCK_CHECK_(boolean_condition);
|
||||
// or
|
||||
// GMOCK_CHECK_(boolean_condition) << "Additional message";
|
||||
//
|
||||
// This checks the condition and if the condition is not satisfied
|
||||
// it prints message about the condition violation, including the
|
||||
// condition itself, plus additional message streamed into it, if any,
|
||||
// and then it aborts the program. It aborts the program irrespective of
|
||||
// whether it is built in the debug mode or not.
|
||||
|
||||
class GMockCheckProvider {
|
||||
public:
|
||||
GMockCheckProvider(const char* condition, const char* file, int line) {
|
||||
FormatFileLocation(file, line, &::std::cerr);
|
||||
::std::cerr << " ERROR: Condition " << condition << " failed. ";
|
||||
}
|
||||
~GMockCheckProvider() {
|
||||
::std::cerr << ::std::endl;
|
||||
abort();
|
||||
}
|
||||
::std::ostream& GetStream() { return ::std::cerr; }
|
||||
};
|
||||
#define GMOCK_CHECK_(condition) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (condition) \
|
||||
; \
|
||||
else \
|
||||
::testing::internal::GMockCheckProvider(\
|
||||
#condition, __FILE__, __LINE__).GetStream()
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
// Macro for referencing flags. This is public as we want the user to
|
||||
// use this syntax to reference Google Mock flags.
|
||||
#define GMOCK_FLAG(name) FLAGS_gmock_##name
|
||||
|
||||
// Macros for declaring flags.
|
||||
#define GMOCK_DECLARE_bool_(name) extern bool GMOCK_FLAG(name)
|
||||
#define GMOCK_DECLARE_int32_(name) \
|
||||
extern ::testing::internal::Int32 GMOCK_FLAG(name)
|
||||
#define GMOCK_DECLARE_string_(name) \
|
||||
extern ::testing::internal::String GMOCK_FLAG(name)
|
||||
|
||||
// Macros for defining flags.
|
||||
#define GMOCK_DEFINE_bool_(name, default_val, doc) \
|
||||
bool GMOCK_FLAG(name) = (default_val)
|
||||
#define GMOCK_DEFINE_int32_(name, default_val, doc) \
|
||||
::testing::internal::Int32 GMOCK_FLAG(name) = (default_val)
|
||||
#define GMOCK_DEFINE_string_(name, default_val, doc) \
|
||||
::testing::internal::String GMOCK_FLAG(name) = (default_val)
|
||||
|
||||
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
|
||||
@@ -6,15 +6,10 @@
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(BoostDir)/boost/tr1/tr1";"$(BoostDir)";"$(GTestDir)/include""
|
||||
PreprocessorDefinitions="GTEST_HAS_TR1_TUPLE=1"
|
||||
AdditionalIncludeDirectories=""$(GTestDir)/include""
|
||||
/>
|
||||
<UserMacro
|
||||
Name="GTestDir"
|
||||
Value="../gtest"
|
||||
/>
|
||||
<UserMacro
|
||||
Name="BoostDir"
|
||||
Value="../boost"
|
||||
/>
|
||||
</VisualStudioPropertySheet>
|
||||
|
||||
@@ -23,7 +23,7 @@ the environment. For example to use an indent of 4 spaces:
|
||||
|
||||
INDENT=4 gmock_gen.py header-file.h ClassName
|
||||
|
||||
This version was made from SVN revision 279 in the cppclean repository.
|
||||
This version was made from SVN revision 281 in the cppclean repository.
|
||||
|
||||
Known Limitations
|
||||
-----------------
|
||||
|
||||
@@ -782,7 +782,7 @@ class AstBuilder(object):
|
||||
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:
|
||||
@@ -1551,18 +1551,22 @@ class AstBuilder(object):
|
||||
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())
|
||||
del tokens[-1] # Remove trailing '}'.
|
||||
# Replace the trailing } with the internal namespace pop token.
|
||||
tokens[-1] = internal_token
|
||||
# Handle namespace with nothing in it.
|
||||
self._AddBackTokens(tokens)
|
||||
token = tokenize.Token(_INTERNAL_TOKEN, _NAMESPACE_POP, None, None)
|
||||
self._AddBackToken(token)
|
||||
return None
|
||||
|
||||
def handle_using(self):
|
||||
@@ -1672,7 +1676,7 @@ def PrintIndentifiers(filename, should_print):
|
||||
if should_print(node):
|
||||
print(node.name)
|
||||
except KeyboardInterrupt:
|
||||
return
|
||||
return
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2008 Google Inc.
|
||||
# Copyright 2008 Google Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -73,7 +73,13 @@ def _GenerateMethods(output_lines, source, class_node):
|
||||
# of the first parameter to the end of the last parameter.
|
||||
start = node.parameters[0].start
|
||||
end = node.parameters[-1].end
|
||||
args = re.sub(' +', ' ', source[start:end].replace('\n', ''))
|
||||
# Remove // comments.
|
||||
args_strings = re.sub(r'//.*', '', source[start:end])
|
||||
# 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', ' '))
|
||||
|
||||
# Create the prototype.
|
||||
indent = ' ' * _INDENT
|
||||
@@ -120,8 +126,6 @@ def _GenerateMocks(filename, source, ast_list, desired_class_names):
|
||||
lines.append('} // namespace %s' % class_node.namespace[i])
|
||||
lines.append('') # Add an extra newline.
|
||||
|
||||
sys.stdout.write('\n'.join(lines))
|
||||
|
||||
if desired_class_names:
|
||||
missing_class_name_list = list(desired_class_names - processed_class_names)
|
||||
if missing_class_name_list:
|
||||
@@ -129,7 +133,9 @@ def _GenerateMocks(filename, source, ast_list, desired_class_names):
|
||||
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)
|
||||
sys.stderr.write('No class found in %s\n' % filename)
|
||||
|
||||
return lines
|
||||
|
||||
|
||||
def main(argv=sys.argv):
|
||||
@@ -164,7 +170,8 @@ def main(argv=sys.argv):
|
||||
# An error message was already printed since we couldn't parse.
|
||||
pass
|
||||
else:
|
||||
_GenerateMocks(filename, source, entire_ast, desired_class_names)
|
||||
lines = _GenerateMocks(filename, source, entire_ast, desired_class_names)
|
||||
sys.stdout.write('\n'.join(lines))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Arquivo executável
+137
@@ -0,0 +1,137 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2009 Neal Norwitz All Rights Reserved.
|
||||
# Portions Copyright 2009 Google Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Tests for gmock.scripts.generator.cpp.gmock_class."""
|
||||
|
||||
__author__ = 'nnorwitz@google.com (Neal Norwitz)'
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
# Allow the cpp imports below to work when run as a standalone script.
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
|
||||
from cpp import ast
|
||||
from cpp import gmock_class
|
||||
|
||||
|
||||
class TestCase(unittest.TestCase):
|
||||
"""Helper class that adds assert methods."""
|
||||
|
||||
def assertEqualIgnoreLeadingWhitespace(self, expected_lines, lines):
|
||||
"""Specialized assert that ignores the indent level."""
|
||||
stripped_lines = '\n'.join([s.lstrip() for s in lines.split('\n')])
|
||||
self.assertEqual(expected_lines, stripped_lines)
|
||||
|
||||
|
||||
class GenerateMethodsTest(TestCase):
|
||||
|
||||
def GenerateMethodSource(self, cpp_source):
|
||||
"""Helper method to convert C++ source to gMock 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 ''.join(method_source_lines)
|
||||
|
||||
def testStrangeNewlineInParameter(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual void Bar(int
|
||||
a) = 0;
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD1(Bar,\nvoid(int a));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
def testDoubleSlashCommentsInParameterListAreRemoved(self):
|
||||
source = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual void Bar(int a, // inline comments should be elided.
|
||||
int b // inline comments should be elided.
|
||||
) const = 0;
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_CONST_METHOD2(Bar,\nvoid(int a, int b));',
|
||||
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 = """
|
||||
class Foo {
|
||||
public:
|
||||
virtual const string& Bar(int /* keeper */, int b);
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
'MOCK_METHOD2(Bar,\nconst string&(int /* keeper */, int b));',
|
||||
self.GenerateMethodSource(source))
|
||||
|
||||
|
||||
class GenerateMocksTest(TestCase):
|
||||
|
||||
def GenerateMocks(self, cpp_source):
|
||||
"""Helper method to convert C++ source to complete gMock 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 = """
|
||||
namespace Foo {
|
||||
namespace Bar { class Forward; }
|
||||
namespace Baz {
|
||||
|
||||
class Test {
|
||||
public:
|
||||
virtual void Foo();
|
||||
};
|
||||
|
||||
} // namespace Baz
|
||||
} // namespace Foo
|
||||
"""
|
||||
expected = """\
|
||||
namespace Foo {
|
||||
namespace Baz {
|
||||
|
||||
class MockTest : public Test {
|
||||
public:
|
||||
MOCK_METHOD0(Foo,
|
||||
void());
|
||||
};
|
||||
|
||||
} // namespace Baz
|
||||
} // namespace Foo
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMocks(source))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -259,7 +259,7 @@ fi
|
||||
# Add the necessary Google Test bits into the various flag variables
|
||||
gmock_cppflags="${gmock_cppflags} `${gtest_config} --cppflags`"
|
||||
gmock_cxxflags="${gmock_cxxflags} `${gtest_config} --cxxflags`"
|
||||
gmock_ldflags="${gmock_ldflags}`${gtest_config} --ldflags`"
|
||||
gmock_ldflags="${gmock_ldflags} `${gtest_config} --ldflags`"
|
||||
gmock_libs="${gmock_libs} `${gtest_config} --libs`"
|
||||
|
||||
# Do an installation query if requested.
|
||||
|
||||
@@ -36,7 +36,7 @@ __author__ = 'wan@google.com (Zhanyong Wan)'
|
||||
import re
|
||||
import sys
|
||||
|
||||
_VERSION = '1.0.0'
|
||||
_VERSION = '1.0.3'
|
||||
|
||||
_COMMON_GMOCK_SYMBOLS = [
|
||||
# Matchers
|
||||
@@ -46,8 +46,12 @@ _COMMON_GMOCK_SYMBOLS = [
|
||||
'AllOf',
|
||||
'An',
|
||||
'AnyOf',
|
||||
'ContainerEq',
|
||||
'Contains',
|
||||
'ContainsRegex',
|
||||
'DoubleEq',
|
||||
'ElementsAre',
|
||||
'ElementsAreArray',
|
||||
'EndsWith',
|
||||
'Eq',
|
||||
'Field',
|
||||
@@ -59,7 +63,10 @@ _COMMON_GMOCK_SYMBOLS = [
|
||||
'Le',
|
||||
'Lt',
|
||||
'MatcherCast',
|
||||
'Matches',
|
||||
'MatchesRegex',
|
||||
'NanSensitiveDoubleEq',
|
||||
'NanSensitiveFloatEq',
|
||||
'Ne',
|
||||
'Not',
|
||||
'NotNull',
|
||||
@@ -67,6 +74,8 @@ _COMMON_GMOCK_SYMBOLS = [
|
||||
'PointeeIsInitializedProto',
|
||||
'Property',
|
||||
'Ref',
|
||||
'ResultOf',
|
||||
'SafeMatcherCast',
|
||||
'StartsWith',
|
||||
'StrCaseEq',
|
||||
'StrCaseNe',
|
||||
@@ -74,9 +83,12 @@ _COMMON_GMOCK_SYMBOLS = [
|
||||
'StrNe',
|
||||
'Truly',
|
||||
'TypedEq',
|
||||
'Value',
|
||||
|
||||
# Actions
|
||||
'Assign',
|
||||
'ByRef',
|
||||
'DeleteArg',
|
||||
'DoAll',
|
||||
'DoDefault',
|
||||
'IgnoreResult',
|
||||
@@ -84,11 +96,18 @@ _COMMON_GMOCK_SYMBOLS = [
|
||||
'InvokeArgument',
|
||||
'InvokeWithoutArgs',
|
||||
'Return',
|
||||
'ReturnNew',
|
||||
'ReturnNull',
|
||||
'ReturnRef',
|
||||
'SaveArg',
|
||||
'SetArgReferee',
|
||||
'SetArgumentPointee',
|
||||
'SetArrayArgument',
|
||||
'SetErrnoAndReturn',
|
||||
'Throw',
|
||||
'WithArg',
|
||||
'WithArgs',
|
||||
'WithoutArgs',
|
||||
|
||||
# Cardinalities
|
||||
'AnyNumber',
|
||||
@@ -106,6 +125,9 @@ _COMMON_GMOCK_SYMBOLS = [
|
||||
'Mock',
|
||||
]
|
||||
|
||||
# Regex for matching source file path and line number in gcc's errors.
|
||||
_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):\s+'
|
||||
|
||||
|
||||
def _FindAllMatches(regex, s):
|
||||
"""Generates all matches of regex in string s."""
|
||||
@@ -128,6 +150,7 @@ def _GenericDiagnoser(short_name, long_name, regex, diagnosis, msg):
|
||||
(short name of disease, long name of disease, diagnosis).
|
||||
"""
|
||||
|
||||
diagnosis = '%(file)s:%(line)s:' + diagnosis
|
||||
for m in _FindAllMatches(regex, msg):
|
||||
yield (short_name, long_name, diagnosis % m.groupdict())
|
||||
|
||||
@@ -136,9 +159,9 @@ def _NeedToReturnReferenceDiagnoser(msg):
|
||||
"""Diagnoses the NRR disease, given the error messages by gcc."""
|
||||
|
||||
regex = (r'In member function \'testing::internal::ReturnAction<R>.*\n'
|
||||
r'(?P<file>.*):(?P<line>\d+):\s+instantiated from here\n'
|
||||
+ _FILE_LINE_RE + r'instantiated from here\n'
|
||||
r'.*gmock-actions\.h.*error: creating array with negative size')
|
||||
diagnosis = """%(file)s:%(line)s:
|
||||
diagnosis = """
|
||||
You are using an Return() action in a function that returns a reference.
|
||||
Please use ReturnRef() instead."""
|
||||
return _GenericDiagnoser('NRR', 'Need to Return Reference',
|
||||
@@ -148,11 +171,11 @@ Please use ReturnRef() instead."""
|
||||
def _NeedToReturnSomethingDiagnoser(msg):
|
||||
"""Diagnoses the NRS disease, given the error messages by gcc."""
|
||||
|
||||
regex = (r'(?P<file>.*):(?P<line>\d+):\s+'
|
||||
regex = (_FILE_LINE_RE +
|
||||
r'(instantiated from here\n.'
|
||||
r'*gmock-actions\.h.*error: void value not ignored)'
|
||||
r'*gmock.*actions\.h.*error: void value not ignored)'
|
||||
r'|(error: control reaches end of non-void function)')
|
||||
diagnosis = """%(file)s:%(line)s:
|
||||
diagnosis = """
|
||||
You are using an action that returns void, but it needs to return
|
||||
*something*. Please tell it *what* to return. Perhaps you can use
|
||||
the pattern DoAll(some_action, Return(some_value))?"""
|
||||
@@ -163,10 +186,10 @@ the pattern DoAll(some_action, Return(some_value))?"""
|
||||
def _NeedToReturnNothingDiagnoser(msg):
|
||||
"""Diagnoses the NRN disease, given the error messages by gcc."""
|
||||
|
||||
regex = (r'(?P<file>.*):(?P<line>\d+):\s+instantiated from here\n'
|
||||
regex = (_FILE_LINE_RE + r'instantiated from here\n'
|
||||
r'.*gmock-actions\.h.*error: return-statement with a value, '
|
||||
r'in function returning \'void\'')
|
||||
diagnosis = """%(file)s:%(line)s:
|
||||
diagnosis = """
|
||||
You are using an action that returns *something*, but it needs to return
|
||||
void. Please use a void-returning action instead.
|
||||
|
||||
@@ -179,10 +202,10 @@ to re-arrange the order of actions in a DoAll(), if you are using one?"""
|
||||
def _IncompleteByReferenceArgumentDiagnoser(msg):
|
||||
"""Diagnoses the IBRA disease, given the error messages by gcc."""
|
||||
|
||||
regex = (r'(?P<file>.*):(?P<line>\d+):\s+instantiated from here\n'
|
||||
regex = (_FILE_LINE_RE + r'instantiated from here\n'
|
||||
r'.*gmock-printers\.h.*error: invalid application of '
|
||||
r'\'sizeof\' to incomplete type \'(?P<type>.*)\'')
|
||||
diagnosis = """%(file)s:%(line)s:
|
||||
diagnosis = """
|
||||
In order to mock this function, Google Mock needs to see the definition
|
||||
of type "%(type)s" - declaration alone is not enough. Either #include
|
||||
the header that defines it, or change the argument to be passed
|
||||
@@ -194,9 +217,9 @@ by pointer."""
|
||||
def _OverloadedFunctionMatcherDiagnoser(msg):
|
||||
"""Diagnoses the OFM disease, given the error messages by gcc."""
|
||||
|
||||
regex = (r'(?P<file>.*):(?P<line>\d+): error: no matching function for '
|
||||
regex = (_FILE_LINE_RE + r'error: no matching function for '
|
||||
r'call to \'Truly\(<unresolved overloaded function type>\)')
|
||||
diagnosis = """%(file)s:%(line)s:
|
||||
diagnosis = """
|
||||
The argument you gave to Truly() is an overloaded function. Please tell
|
||||
gcc which overloaded version you want to use.
|
||||
|
||||
@@ -211,10 +234,9 @@ you should write
|
||||
def _OverloadedFunctionActionDiagnoser(msg):
|
||||
"""Diagnoses the OFA disease, given the error messages by gcc."""
|
||||
|
||||
regex = (r'(?P<file>.*):(?P<line>\d+): error: '
|
||||
r'no matching function for call to \'Invoke\('
|
||||
regex = (_FILE_LINE_RE + r'error: no matching function for call to \'Invoke\('
|
||||
r'<unresolved overloaded function type>')
|
||||
diagnosis = """%(file)s:%(line)s:
|
||||
diagnosis = """
|
||||
You are passing an overloaded function to Invoke(). Please tell gcc
|
||||
which overloaded version you want to use.
|
||||
|
||||
@@ -229,10 +251,10 @@ you should write something like
|
||||
def _OverloadedMethodActionDiagnoser1(msg):
|
||||
"""Diagnoses the OMA disease, given the error messages by gcc."""
|
||||
|
||||
regex = (r'(?P<file>.*):(?P<line>\d+): error: '
|
||||
regex = (_FILE_LINE_RE + r'error: '
|
||||
r'.*no matching function for call to \'Invoke\(.*, '
|
||||
r'unresolved overloaded function type>')
|
||||
diagnosis = """%(file)s:%(line)s:
|
||||
diagnosis = """
|
||||
The second argument you gave to Invoke() is an overloaded method. Please
|
||||
tell gcc which overloaded version you want to use.
|
||||
|
||||
@@ -250,10 +272,10 @@ you should write something like
|
||||
def _MockObjectPointerDiagnoser(msg):
|
||||
"""Diagnoses the MOP disease, given the error messages by gcc."""
|
||||
|
||||
regex = (r'(?P<file>.*):(?P<line>\d+): error: request for member '
|
||||
regex = (_FILE_LINE_RE + r'error: request for member '
|
||||
r'\'gmock_(?P<method>.+)\' in \'(?P<mock_object>.+)\', '
|
||||
r'which is of non-class type \'(.*::)*(?P<class_name>.+)\*\'')
|
||||
diagnosis = """%(file)s:%(line)s:
|
||||
diagnosis = """
|
||||
The first argument to ON_CALL() and EXPECT_CALL() must be a mock *object*,
|
||||
not a *pointer* to it. Please write '*(%(mock_object)s)' instead of
|
||||
'%(mock_object)s' as your first argument.
|
||||
@@ -279,9 +301,9 @@ you should use the EXPECT_CALL like this:
|
||||
def _OverloadedMethodActionDiagnoser2(msg):
|
||||
"""Diagnoses the OMA disease, given the error messages by gcc."""
|
||||
|
||||
regex = (r'(?P<file>.*):(?P<line>\d+): error: no matching function for '
|
||||
regex = (_FILE_LINE_RE + r'error: no matching function for '
|
||||
r'call to \'Invoke\(.+, <unresolved overloaded function type>\)')
|
||||
diagnosis = """%(file)s:%(line)s:
|
||||
diagnosis = """
|
||||
The second argument you gave to Invoke() is an overloaded method. Please
|
||||
tell gcc which overloaded version you want to use.
|
||||
|
||||
@@ -299,9 +321,9 @@ you should write something like
|
||||
def _NeedToUseSymbolDiagnoser(msg):
|
||||
"""Diagnoses the NUS disease, given the error messages by gcc."""
|
||||
|
||||
regex = (r'(?P<file>.*):(?P<line>\d+): error: \'(?P<symbol>.+)\' '
|
||||
regex = (_FILE_LINE_RE + r'error: \'(?P<symbol>.+)\' '
|
||||
r'(was not declared in this scope|has not been declared)')
|
||||
diagnosis = """%(file)s:%(line)s:
|
||||
diagnosis = """
|
||||
'%(symbol)s' is defined by Google Mock in the testing namespace.
|
||||
Did you forget to write
|
||||
using testing::%(symbol)s;
|
||||
@@ -315,11 +337,10 @@ Did you forget to write
|
||||
def _NeedToUseReturnNullDiagnoser(msg):
|
||||
"""Diagnoses the NRNULL disease, given the error messages by gcc."""
|
||||
|
||||
regex = (r'(?P<file>.*):(?P<line>\d+):\s+instantiated from here\n'
|
||||
regex = (_FILE_LINE_RE + r'instantiated from here\n'
|
||||
r'.*gmock-actions\.h.*error: invalid conversion from '
|
||||
r'\'long int\' to \'(?P<type>.+\*)')
|
||||
|
||||
diagnosis = """%(file)s:%(line)s:
|
||||
diagnosis = """
|
||||
You are probably calling Return(NULL) and the compiler isn't sure how to turn
|
||||
NULL into a %(type)s*. Use ReturnNull() instead.
|
||||
Note: the line number may be off; please fix all instances of Return(NULL)."""
|
||||
@@ -327,23 +348,90 @@ Note: the line number may be off; please fix all instances of Return(NULL)."""
|
||||
regex, diagnosis, msg)
|
||||
|
||||
|
||||
_TTB_DIAGNOSIS = """
|
||||
In a mock class template, types or typedefs defined in the base class
|
||||
template are *not* automatically visible. This is how C++ works. Before
|
||||
you can use a type or typedef named %(type)s defined in base class Base<T>, you
|
||||
need to make it visible. One way to do it is:
|
||||
|
||||
typedef typename Base<T>::%(type)s %(type)s;"""
|
||||
|
||||
|
||||
def _TypeInTemplatedBaseDiagnoser1(msg):
|
||||
"""Diagnoses the TTB disease, given the error messages by gcc.
|
||||
|
||||
This version works when the type is used as the mock function's return
|
||||
type.
|
||||
"""
|
||||
|
||||
regex = (r'In member function \'int .*\n' + _FILE_LINE_RE +
|
||||
r'error: a function call cannot appear in a constant-expression')
|
||||
diagnosis = _TTB_DIAGNOSIS % {'type': 'Foo'}
|
||||
return _GenericDiagnoser('TTB', 'Type in Template Base',
|
||||
regex, diagnosis, msg)
|
||||
|
||||
|
||||
def _TypeInTemplatedBaseDiagnoser2(msg):
|
||||
"""Diagnoses the TTB disease, given the error messages by gcc.
|
||||
|
||||
This version works when the type is used as the mock function's sole
|
||||
parameter type.
|
||||
"""
|
||||
|
||||
regex = (r'In member function \'int .*\n'
|
||||
+ _FILE_LINE_RE +
|
||||
r'error: \'(?P<type>.+)\' was not declared in this scope\n'
|
||||
r'.*error: template argument 1 is invalid\n')
|
||||
return _GenericDiagnoser('TTB', 'Type in Template Base',
|
||||
regex, _TTB_DIAGNOSIS, msg)
|
||||
|
||||
|
||||
def _TypeInTemplatedBaseDiagnoser3(msg):
|
||||
"""Diagnoses the TTB disease, given the error messages by gcc.
|
||||
|
||||
This version works when the type is used as a parameter of a mock
|
||||
function that has multiple parameters.
|
||||
"""
|
||||
|
||||
regex = (r'error: expected `;\' before \'::\' token\n'
|
||||
+ _FILE_LINE_RE +
|
||||
r'error: \'(?P<type>.+)\' was not declared in this scope\n'
|
||||
r'.*error: template argument 1 is invalid\n'
|
||||
r'.*error: \'.+\' was not declared in this scope')
|
||||
return _GenericDiagnoser('TTB', 'Type in Template Base',
|
||||
regex, _TTB_DIAGNOSIS, msg)
|
||||
|
||||
|
||||
def _WrongMockMethodMacroDiagnoser(msg):
|
||||
"""Diagnoses the WMM disease, given the error messages by gcc."""
|
||||
|
||||
regex = (r'(?P<file>.*):(?P<line>\d+):\s+'
|
||||
regex = (_FILE_LINE_RE +
|
||||
r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n'
|
||||
r'.*\n'
|
||||
r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>'
|
||||
)
|
||||
|
||||
diagnosis = """%(file)s:%(line)s:
|
||||
r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>')
|
||||
diagnosis = """
|
||||
You are using MOCK_METHOD%(wrong_args)s to define a mock method that has
|
||||
%(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s,
|
||||
MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead."""
|
||||
return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn macro',
|
||||
return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn Macro',
|
||||
regex, diagnosis, msg)
|
||||
|
||||
|
||||
def _WrongParenPositionDiagnoser(msg):
|
||||
"""Diagnoses the WPP disease, given the error messages by gcc."""
|
||||
|
||||
regex = (_FILE_LINE_RE +
|
||||
r'error:.*testing::internal::MockSpec<.* has no member named \''
|
||||
r'(?P<method>\w+)\'')
|
||||
diagnosis = """
|
||||
The closing parenthesis of ON_CALL or EXPECT_CALL should be *before*
|
||||
".%(method)s". For example, you should write:
|
||||
EXPECT_CALL(my_mock, Foo(_)).%(method)s(...);
|
||||
instead of:
|
||||
EXPECT_CALL(my_mock, Foo(_).%(method)s(...));"""
|
||||
return _GenericDiagnoser('WPP', 'Wrong Parenthesis Position',
|
||||
regex, diagnosis, msg)
|
||||
|
||||
|
||||
_DIAGNOSERS = [
|
||||
_IncompleteByReferenceArgumentDiagnoser,
|
||||
@@ -357,7 +445,11 @@ _DIAGNOSERS = [
|
||||
_OverloadedFunctionMatcherDiagnoser,
|
||||
_OverloadedMethodActionDiagnoser1,
|
||||
_OverloadedMethodActionDiagnoser2,
|
||||
_TypeInTemplatedBaseDiagnoser1,
|
||||
_TypeInTemplatedBaseDiagnoser2,
|
||||
_TypeInTemplatedBaseDiagnoser3,
|
||||
_WrongMockMethodMacroDiagnoser,
|
||||
_WrongParenPositionDiagnoser,
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -101,6 +101,22 @@ FailureReporterInterface* GetFailureReporter() {
|
||||
// Protects global resources (stdout in particular) used by Log().
|
||||
static Mutex g_log_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX);
|
||||
|
||||
// Returns true iff a log with the given severity is visible according
|
||||
// to the --gmock_verbose flag.
|
||||
bool LogIsVisible(LogSeverity severity) {
|
||||
if (GMOCK_FLAG(verbose) == kInfoVerbosity) {
|
||||
// Always show the log if --gmock_verbose=info.
|
||||
return true;
|
||||
} else if (GMOCK_FLAG(verbose) == kErrorVerbosity) {
|
||||
// Always hide it if --gmock_verbose=error.
|
||||
return false;
|
||||
} else {
|
||||
// If --gmock_verbose is neither "info" nor "error", we treat it
|
||||
// as "warning" (its default value).
|
||||
return severity == WARNING;
|
||||
}
|
||||
}
|
||||
|
||||
// Prints the given message to stdout iff 'severity' >= the level
|
||||
// specified by the --gmock_verbose flag. If stack_frames_to_skip >=
|
||||
// 0, also prints the stack trace excluding the top
|
||||
@@ -110,30 +126,24 @@ static Mutex g_log_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX);
|
||||
// conservative.
|
||||
void Log(LogSeverity severity, const string& message,
|
||||
int stack_frames_to_skip) {
|
||||
if (GMOCK_FLAG(verbose) == kErrorVerbosity) {
|
||||
// The user is not interested in logs.
|
||||
if (!LogIsVisible(severity))
|
||||
return;
|
||||
} else if (GMOCK_FLAG(verbose) != kInfoVerbosity) {
|
||||
// The user is interested in warnings but not informational logs.
|
||||
// Note that invalid values of GMOCK_FLAG(verbose) are treated as
|
||||
// "warning", which is the default value of the flag.
|
||||
if (severity == INFO) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensures that logs from different threads don't interleave.
|
||||
MutexLock l(&g_log_mutex);
|
||||
using ::std::cout;
|
||||
|
||||
// "using ::std::cout;" doesn't work with Symbian's STLport, where cout is a
|
||||
// macro.
|
||||
|
||||
if (severity == WARNING) {
|
||||
// Prints a GMOCK WARNING marker to make the warnings easily searchable.
|
||||
cout << "\nGMOCK WARNING:";
|
||||
std::cout << "\nGMOCK WARNING:";
|
||||
}
|
||||
// Pre-pends a new-line to message if it doesn't start with one.
|
||||
if (message.empty() || message[0] != '\n') {
|
||||
cout << "\n";
|
||||
std::cout << "\n";
|
||||
}
|
||||
cout << message;
|
||||
std::cout << message;
|
||||
if (stack_frames_to_skip >= 0) {
|
||||
#ifdef NDEBUG
|
||||
// In opt mode, we have to be conservative and skip no stack frame.
|
||||
@@ -146,13 +156,13 @@ void Log(LogSeverity severity, const string& message,
|
||||
|
||||
// Appends a new-line to message if it doesn't end with one.
|
||||
if (!message.empty() && *message.rbegin() != '\n') {
|
||||
cout << "\n";
|
||||
std::cout << "\n";
|
||||
}
|
||||
cout << "Stack trace:\n"
|
||||
std::cout << "Stack trace:\n"
|
||||
<< ::testing::internal::GetCurrentOsStackTraceExceptTop(
|
||||
::testing::UnitTest::GetInstance(), actual_to_skip);
|
||||
}
|
||||
cout << ::std::flush;
|
||||
std::cout << ::std::flush;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
@@ -242,6 +242,11 @@ static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) {
|
||||
*os << "\"";
|
||||
}
|
||||
|
||||
// Prints a (const) char array of 'len' elements, starting at address 'begin'.
|
||||
void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
|
||||
PrintCharsAsStringTo(begin, len, os);
|
||||
}
|
||||
|
||||
// Prints the given array of wide characters to the ostream.
|
||||
// The array starts at *begin, the length is len, it may include L'\0'
|
||||
// characters and may not be null-terminated.
|
||||
|
||||
@@ -139,10 +139,10 @@ ThreadLocal<Sequence*> g_gmock_implicit_sequence;
|
||||
void ReportUninterestingCall(CallReaction reaction, const string& msg) {
|
||||
switch (reaction) {
|
||||
case ALLOW:
|
||||
Log(INFO, msg, 4);
|
||||
Log(INFO, msg, 3);
|
||||
break;
|
||||
case WARN:
|
||||
Log(WARNING, msg, 4);
|
||||
Log(WARNING, msg, 3);
|
||||
break;
|
||||
default: // FAIL
|
||||
Expect(false, NULL, -1, msg);
|
||||
|
||||
@@ -269,13 +269,19 @@ TEST(InvokeTest, FunctionThatTakes6Arguments) {
|
||||
EXPECT_EQ(123456, a.Perform(make_tuple(100000, 20000, 3000, 400, 50, 6)));
|
||||
}
|
||||
|
||||
// A helper that turns the type of a C-string literal from const
|
||||
// char[N] to const char*.
|
||||
inline const char* CharPtr(const char* s) { return s; }
|
||||
|
||||
// Tests using Invoke() with a 7-argument function.
|
||||
TEST(InvokeTest, FunctionThatTakes7Arguments) {
|
||||
Action<string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*)> a =
|
||||
Invoke(Concat7);
|
||||
EXPECT_EQ("1234567",
|
||||
a.Perform(make_tuple("1", "2", "3", "4", "5", "6", "7")));
|
||||
a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 8-argument function.
|
||||
@@ -284,7 +290,9 @@ TEST(InvokeTest, FunctionThatTakes8Arguments) {
|
||||
const char*, const char*, const char*, const char*)> a =
|
||||
Invoke(Concat8);
|
||||
EXPECT_EQ("12345678",
|
||||
a.Perform(make_tuple("1", "2", "3", "4", "5", "6", "7", "8")));
|
||||
a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"), CharPtr("8"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 9-argument function.
|
||||
@@ -293,7 +301,9 @@ TEST(InvokeTest, FunctionThatTakes9Arguments) {
|
||||
const char*, const char*, const char*, const char*,
|
||||
const char*)> a = Invoke(Concat9);
|
||||
EXPECT_EQ("123456789",
|
||||
a.Perform(make_tuple("1", "2", "3", "4", "5", "6", "7", "8", "9")));
|
||||
a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"), CharPtr("8"), CharPtr("9"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 10-argument function.
|
||||
@@ -301,15 +311,18 @@ TEST(InvokeTest, FunctionThatTakes10Arguments) {
|
||||
Action<string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*, const char*,
|
||||
const char*, const char*)> a = Invoke(Concat10);
|
||||
EXPECT_EQ("1234567890", a.Perform(make_tuple("1", "2", "3", "4", "5", "6",
|
||||
"7", "8", "9", "0")));
|
||||
EXPECT_EQ("1234567890",
|
||||
a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"), CharPtr("8"), CharPtr("9"),
|
||||
CharPtr("0"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with functions with parameters declared as Unused.
|
||||
TEST(InvokeTest, FunctionWithUnusedParameters) {
|
||||
Action<int(int, int, double, const string&)> a1 =
|
||||
Invoke(SumOfFirst2);
|
||||
EXPECT_EQ(12, a1.Perform(make_tuple(10, 2, 5.6, "hi")));
|
||||
EXPECT_EQ(12, a1.Perform(make_tuple(10, 2, 5.6, CharPtr("hi"))));
|
||||
|
||||
Action<int(int, int, bool, int*)> a2 =
|
||||
Invoke(SumOfFirst2);
|
||||
@@ -321,7 +334,7 @@ TEST(InvokeTest, MethodWithUnusedParameters) {
|
||||
Foo foo;
|
||||
Action<int(string, bool, int, int)> a1 =
|
||||
Invoke(&foo, &Foo::SumOfLast2);
|
||||
EXPECT_EQ(12, a1.Perform(make_tuple("hi", true, 10, 2)));
|
||||
EXPECT_EQ(12, a1.Perform(make_tuple(CharPtr("hi"), true, 10, 2)));
|
||||
|
||||
Action<int(char, double, int, int)> a2 =
|
||||
Invoke(&foo, &Foo::SumOfLast2);
|
||||
@@ -400,7 +413,9 @@ TEST(InvokeMethodTest, MethodThatTakes7Arguments) {
|
||||
const char*, const char*, const char*)> a =
|
||||
Invoke(&foo, &Foo::Concat7);
|
||||
EXPECT_EQ("1234567",
|
||||
a.Perform(make_tuple("1", "2", "3", "4", "5", "6", "7")));
|
||||
a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 8-argument method.
|
||||
@@ -410,7 +425,9 @@ TEST(InvokeMethodTest, MethodThatTakes8Arguments) {
|
||||
const char*, const char*, const char*, const char*)> a =
|
||||
Invoke(&foo, &Foo::Concat8);
|
||||
EXPECT_EQ("12345678",
|
||||
a.Perform(make_tuple("1", "2", "3", "4", "5", "6", "7", "8")));
|
||||
a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"), CharPtr("8"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 9-argument method.
|
||||
@@ -420,7 +437,9 @@ TEST(InvokeMethodTest, MethodThatTakes9Arguments) {
|
||||
const char*, const char*, const char*, const char*,
|
||||
const char*)> a = Invoke(&foo, &Foo::Concat9);
|
||||
EXPECT_EQ("123456789",
|
||||
a.Perform(make_tuple("1", "2", "3", "4", "5", "6", "7", "8", "9")));
|
||||
a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"), CharPtr("8"), CharPtr("9"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 10-argument method.
|
||||
@@ -429,8 +448,11 @@ TEST(InvokeMethodTest, MethodThatTakes10Arguments) {
|
||||
Action<string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*, const char*,
|
||||
const char*, const char*)> a = Invoke(&foo, &Foo::Concat10);
|
||||
EXPECT_EQ("1234567890", a.Perform(make_tuple("1", "2", "3", "4", "5", "6",
|
||||
"7", "8", "9", "0")));
|
||||
EXPECT_EQ("1234567890",
|
||||
a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"), CharPtr("8"), CharPtr("9"),
|
||||
CharPtr("0"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke(f) as an action of a compatible type.
|
||||
@@ -665,7 +687,7 @@ TEST(WithArgsTest, TwoArgs) {
|
||||
Action<const char*(const char* s, double x, int n)> a =
|
||||
WithArgs<0, 2>(Invoke(Binary));
|
||||
const char s[] = "Hello";
|
||||
EXPECT_EQ(s + 2, a.Perform(make_tuple(s, 0.5, 2)));
|
||||
EXPECT_EQ(s + 2, a.Perform(make_tuple(CharPtr(s), 0.5, 2)));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 3 arguments.
|
||||
@@ -679,7 +701,8 @@ TEST(WithArgsTest, ThreeArgs) {
|
||||
TEST(WithArgsTest, FourArgs) {
|
||||
Action<string(const char*, const char*, double, const char*, const char*)> a =
|
||||
WithArgs<4, 3, 1, 0>(Invoke(Concat4));
|
||||
EXPECT_EQ("4310", a.Perform(make_tuple("0", "1", 2.5, "3", "4")));
|
||||
EXPECT_EQ("4310", a.Perform(make_tuple(CharPtr("0"), CharPtr("1"), 2.5,
|
||||
CharPtr("3"), CharPtr("4"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 5 arguments.
|
||||
@@ -687,42 +710,53 @@ TEST(WithArgsTest, FiveArgs) {
|
||||
Action<string(const char*, const char*, const char*,
|
||||
const char*, const char*)> a =
|
||||
WithArgs<4, 3, 2, 1, 0>(Invoke(Concat5));
|
||||
EXPECT_EQ("43210", a.Perform(make_tuple("0", "1", "2", "3", "4")));
|
||||
EXPECT_EQ("43210",
|
||||
a.Perform(make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
|
||||
CharPtr("3"), CharPtr("4"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 6 arguments.
|
||||
TEST(WithArgsTest, SixArgs) {
|
||||
Action<string(const char*, const char*, const char*)> a =
|
||||
WithArgs<0, 1, 2, 2, 1, 0>(Invoke(Concat6));
|
||||
EXPECT_EQ("012210", a.Perform(make_tuple("0", "1", "2")));
|
||||
EXPECT_EQ("012210",
|
||||
a.Perform(make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 7 arguments.
|
||||
TEST(WithArgsTest, SevenArgs) {
|
||||
Action<string(const char*, const char*, const char*, const char*)> a =
|
||||
WithArgs<0, 1, 2, 3, 2, 1, 0>(Invoke(Concat7));
|
||||
EXPECT_EQ("0123210", a.Perform(make_tuple("0", "1", "2", "3")));
|
||||
EXPECT_EQ("0123210",
|
||||
a.Perform(make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
|
||||
CharPtr("3"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 8 arguments.
|
||||
TEST(WithArgsTest, EightArgs) {
|
||||
Action<string(const char*, const char*, const char*, const char*)> a =
|
||||
WithArgs<0, 1, 2, 3, 0, 1, 2, 3>(Invoke(Concat8));
|
||||
EXPECT_EQ("01230123", a.Perform(make_tuple("0", "1", "2", "3")));
|
||||
EXPECT_EQ("01230123",
|
||||
a.Perform(make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
|
||||
CharPtr("3"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 9 arguments.
|
||||
TEST(WithArgsTest, NineArgs) {
|
||||
Action<string(const char*, const char*, const char*, const char*)> a =
|
||||
WithArgs<0, 1, 2, 3, 1, 2, 3, 2, 3>(Invoke(Concat9));
|
||||
EXPECT_EQ("012312323", a.Perform(make_tuple("0", "1", "2", "3")));
|
||||
EXPECT_EQ("012312323",
|
||||
a.Perform(make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
|
||||
CharPtr("3"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 10 arguments.
|
||||
TEST(WithArgsTest, TenArgs) {
|
||||
Action<string(const char*, const char*, const char*, const char*)> a =
|
||||
WithArgs<0, 1, 2, 3, 2, 1, 0, 1, 2, 3>(Invoke(Concat10));
|
||||
EXPECT_EQ("0123210123", a.Perform(make_tuple("0", "1", "2", "3")));
|
||||
EXPECT_EQ("0123210123",
|
||||
a.Perform(make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
|
||||
CharPtr("3"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that is not Invoke().
|
||||
@@ -736,7 +770,7 @@ class SubstractAction : public ActionInterface<int(int, int)> { // NOLINT
|
||||
TEST(WithArgsTest, NonInvokeAction) {
|
||||
Action<int(const string&, int, int)> a = // NOLINT
|
||||
WithArgs<2, 1>(MakeAction(new SubstractAction));
|
||||
EXPECT_EQ(8, a.Perform(make_tuple("hi", 2, 10)));
|
||||
EXPECT_EQ(8, a.Perform(make_tuple(CharPtr("hi"), 2, 10)));
|
||||
}
|
||||
|
||||
// Tests using WithArgs to pass all original arguments in the original order.
|
||||
@@ -758,7 +792,7 @@ TEST(WithArgsTest, ReversedArgumentOrder) {
|
||||
Action<const char*(short n, const char* input)> a = // NOLINT
|
||||
WithArgs<1, 0>(Invoke(Binary));
|
||||
const char s[] = "Hello";
|
||||
EXPECT_EQ(s + 2, a.Perform(make_tuple(2, s)));
|
||||
EXPECT_EQ(s + 2, a.Perform(make_tuple(2, CharPtr(s))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with compatible, but not identical, argument types.
|
||||
@@ -1123,16 +1157,16 @@ TEST(ActionMacroTest, CanDefineOverloadedActions) {
|
||||
typedef Action<const char*(bool, const char*)> MyAction;
|
||||
|
||||
const MyAction a1 = OverloadedAction();
|
||||
EXPECT_STREQ("hello", a1.Perform(make_tuple(false, "world")));
|
||||
EXPECT_STREQ("world", a1.Perform(make_tuple(true, "world")));
|
||||
EXPECT_STREQ("hello", a1.Perform(make_tuple(false, CharPtr("world"))));
|
||||
EXPECT_STREQ("world", a1.Perform(make_tuple(true, CharPtr("world"))));
|
||||
|
||||
const MyAction a2 = OverloadedAction("hi");
|
||||
EXPECT_STREQ("hi", a2.Perform(make_tuple(false, "world")));
|
||||
EXPECT_STREQ("world", a2.Perform(make_tuple(true, "world")));
|
||||
EXPECT_STREQ("hi", a2.Perform(make_tuple(false, CharPtr("world"))));
|
||||
EXPECT_STREQ("world", a2.Perform(make_tuple(true, CharPtr("world"))));
|
||||
|
||||
const MyAction a3 = OverloadedAction("hi", "you");
|
||||
EXPECT_STREQ("hi", a3.Perform(make_tuple(true, "world")));
|
||||
EXPECT_STREQ("you", a3.Perform(make_tuple(false, "world")));
|
||||
EXPECT_STREQ("hi", a3.Perform(make_tuple(true, CharPtr("world"))));
|
||||
EXPECT_STREQ("you", a3.Perform(make_tuple(false, CharPtr("world"))));
|
||||
}
|
||||
|
||||
// Tests ACTION_Pn where n >= 3.
|
||||
@@ -1224,8 +1258,8 @@ TEST(ActionPnMacroTest, SimpleTypePromotion) {
|
||||
PadArgument(std::string("foo"), 'r');
|
||||
Action<std::string(const char*)> promo =
|
||||
PadArgument("foo", static_cast<int>('r'));
|
||||
EXPECT_EQ("foobar", no_promo.Perform(make_tuple("ba")));
|
||||
EXPECT_EQ("foobar", promo.Perform(make_tuple("ba")));
|
||||
EXPECT_EQ("foobar", no_promo.Perform(make_tuple(CharPtr("ba"))));
|
||||
EXPECT_EQ("foobar", promo.Perform(make_tuple(CharPtr("ba"))));
|
||||
}
|
||||
|
||||
// Tests that we can partially restrict parameter types using a
|
||||
@@ -1470,7 +1504,7 @@ TEST(DeleteArgActionTest, TenArgs) {
|
||||
const Action<void(bool, int, int, const char*, bool,
|
||||
int, int, int, int, DeletionTester*)> a1 = DeleteArg<9>();
|
||||
EXPECT_FALSE(is_deleted);
|
||||
a1.Perform(make_tuple(true, 5, 6, "hi", false, 7, 8, 9, 10, t));
|
||||
a1.Perform(make_tuple(true, 5, 6, CharPtr("hi"), false, 7, 8, 9, 10, t));
|
||||
EXPECT_TRUE(is_deleted);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,13 +53,18 @@ using std::pair;
|
||||
using std::set;
|
||||
using std::stringstream;
|
||||
using std::vector;
|
||||
using std::tr1::get;
|
||||
using std::tr1::make_tuple;
|
||||
using std::tr1::tuple;
|
||||
using testing::_;
|
||||
using testing::Args;
|
||||
using testing::Contains;
|
||||
using testing::ElementsAre;
|
||||
using testing::ElementsAreArray;
|
||||
using testing::Eq;
|
||||
using testing::Ge;
|
||||
using testing::Gt;
|
||||
using testing::Lt;
|
||||
using testing::MakeMatcher;
|
||||
using testing::Matcher;
|
||||
using testing::MatcherInterface;
|
||||
@@ -69,6 +74,7 @@ using testing::Pointee;
|
||||
using testing::Ref;
|
||||
using testing::StaticAssertTypeEq;
|
||||
using testing::StrEq;
|
||||
using testing::Value;
|
||||
using testing::internal::string;
|
||||
|
||||
// Returns the description of the given matcher.
|
||||
@@ -95,6 +101,107 @@ string Explain(const MatcherType& m, const Value& x) {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Tests Args<k0, ..., kn>(m).
|
||||
|
||||
TEST(ArgsTest, AcceptsZeroTemplateArg) {
|
||||
const tuple<int, bool> t(5, true);
|
||||
EXPECT_THAT(t, Args<>(Eq(tuple<>())));
|
||||
EXPECT_THAT(t, Not(Args<>(Ne(tuple<>()))));
|
||||
}
|
||||
|
||||
TEST(ArgsTest, AcceptsOneTemplateArg) {
|
||||
const tuple<int, bool> t(5, true);
|
||||
EXPECT_THAT(t, Args<0>(Eq(make_tuple(5))));
|
||||
EXPECT_THAT(t, Args<1>(Eq(make_tuple(true))));
|
||||
EXPECT_THAT(t, Not(Args<1>(Eq(make_tuple(false)))));
|
||||
}
|
||||
|
||||
TEST(ArgsTest, AcceptsTwoTemplateArgs) {
|
||||
const tuple<short, int, long> t(4, 5, 6L); // NOLINT
|
||||
|
||||
EXPECT_THAT(t, (Args<0, 1>(Lt())));
|
||||
EXPECT_THAT(t, (Args<1, 2>(Lt())));
|
||||
EXPECT_THAT(t, Not(Args<0, 2>(Gt())));
|
||||
}
|
||||
|
||||
TEST(ArgsTest, AcceptsRepeatedTemplateArgs) {
|
||||
const tuple<short, int, long> t(4, 5, 6L); // NOLINT
|
||||
EXPECT_THAT(t, (Args<0, 0>(Eq())));
|
||||
EXPECT_THAT(t, Not(Args<1, 1>(Ne())));
|
||||
}
|
||||
|
||||
TEST(ArgsTest, AcceptsDecreasingTemplateArgs) {
|
||||
const tuple<short, int, long> t(4, 5, 6L); // NOLINT
|
||||
EXPECT_THAT(t, (Args<2, 0>(Gt())));
|
||||
EXPECT_THAT(t, Not(Args<2, 1>(Lt())));
|
||||
}
|
||||
|
||||
MATCHER(SumIsZero, "") {
|
||||
return get<0>(arg) + get<1>(arg) + get<2>(arg) == 0;
|
||||
}
|
||||
|
||||
TEST(ArgsTest, AcceptsMoreTemplateArgsThanArityOfOriginalTuple) {
|
||||
EXPECT_THAT(make_tuple(-1, 2), (Args<0, 0, 1>(SumIsZero())));
|
||||
EXPECT_THAT(make_tuple(1, 2), Not(Args<0, 0, 1>(SumIsZero())));
|
||||
}
|
||||
|
||||
TEST(ArgsTest, CanBeNested) {
|
||||
const tuple<short, int, long, int> t(4, 5, 6L, 6); // NOLINT
|
||||
EXPECT_THAT(t, (Args<1, 2, 3>(Args<1, 2>(Eq()))));
|
||||
EXPECT_THAT(t, (Args<0, 1, 3>(Args<0, 2>(Lt()))));
|
||||
}
|
||||
|
||||
TEST(ArgsTest, CanMatchTupleByValue) {
|
||||
typedef tuple<char, int, int> Tuple3;
|
||||
const Matcher<Tuple3> m = Args<1, 2>(Lt());
|
||||
EXPECT_TRUE(m.Matches(Tuple3('a', 1, 2)));
|
||||
EXPECT_FALSE(m.Matches(Tuple3('b', 2, 2)));
|
||||
}
|
||||
|
||||
TEST(ArgsTest, CanMatchTupleByReference) {
|
||||
typedef tuple<char, char, int> Tuple3;
|
||||
const Matcher<const Tuple3&> m = Args<0, 1>(Lt());
|
||||
EXPECT_TRUE(m.Matches(Tuple3('a', 'b', 2)));
|
||||
EXPECT_FALSE(m.Matches(Tuple3('b', 'b', 2)));
|
||||
}
|
||||
|
||||
// Validates that arg is printed as str.
|
||||
MATCHER_P(PrintsAs, str, "") {
|
||||
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(arg_type)) RawTuple;
|
||||
return
|
||||
testing::internal::UniversalPrinter<RawTuple>::PrintToString(arg) == str;
|
||||
}
|
||||
|
||||
TEST(ArgsTest, AcceptsTenTemplateArgs) {
|
||||
EXPECT_THAT(make_tuple(0, 1L, 2, 3L, 4, 5, 6, 7, 8, 9),
|
||||
(Args<9, 8, 7, 6, 5, 4, 3, 2, 1, 0>(
|
||||
PrintsAs("(9, 8, 7, 6, 5, 4, 3, 2, 1, 0)"))));
|
||||
EXPECT_THAT(make_tuple(0, 1L, 2, 3L, 4, 5, 6, 7, 8, 9),
|
||||
Not(Args<9, 8, 7, 6, 5, 4, 3, 2, 1, 0>(
|
||||
PrintsAs("(0, 8, 7, 6, 5, 4, 3, 2, 1, 0)"))));
|
||||
}
|
||||
|
||||
TEST(ArgsTest, DescirbesSelfCorrectly) {
|
||||
const Matcher<tuple<int, bool, char> > m = Args<2, 0>(Lt());
|
||||
EXPECT_EQ("are a tuple whose fields (#2, #0) are a pair (x, y) where x < y",
|
||||
Describe(m));
|
||||
}
|
||||
|
||||
TEST(ArgsTest, DescirbesNestedArgsCorrectly) {
|
||||
const Matcher<const tuple<int, bool, char, int>&> m =
|
||||
Args<0, 2, 3>(Args<2, 0>(Lt()));
|
||||
EXPECT_EQ("are a tuple whose fields (#0, #2, #3) are a tuple "
|
||||
"whose fields (#2, #0) are a pair (x, y) where x < y",
|
||||
Describe(m));
|
||||
}
|
||||
|
||||
TEST(ArgsTest, DescribesNegationCorrectly) {
|
||||
const Matcher<tuple<int, char> > m = Args<1, 0>(Gt());
|
||||
EXPECT_EQ("are a tuple whose fields (#1, #0) are a pair (x, y) "
|
||||
"where x > y is false",
|
||||
DescribeNegation(m));
|
||||
}
|
||||
|
||||
// For testing ExplainMatchResultTo().
|
||||
class GreaterThanMatcher : public MatcherInterface<int> {
|
||||
public:
|
||||
@@ -330,6 +437,39 @@ TEST(ElementsAreTest, WorksWithContainerPointerUsingPointee) {
|
||||
EXPECT_THAT(&v, Not(Pointee(ElementsAre(0, _, 3))));
|
||||
}
|
||||
|
||||
TEST(ElementsAreTest, WorksWithNativeArrayPassedByReference) {
|
||||
int array[] = { 0, 1, 2 };
|
||||
EXPECT_THAT(array, ElementsAre(0, 1, _));
|
||||
EXPECT_THAT(array, Not(ElementsAre(1, _, _)));
|
||||
EXPECT_THAT(array, Not(ElementsAre(0, _)));
|
||||
}
|
||||
|
||||
class NativeArrayPassedAsPointerAndSize {
|
||||
public:
|
||||
MOCK_METHOD2(Helper, void(int* array, int size));
|
||||
};
|
||||
|
||||
TEST(ElementsAreTest, WorksWithNativeArrayPassedAsPointerAndSize) {
|
||||
int array[] = { 0, 1 };
|
||||
::std::tr1::tuple<int*, size_t> array_as_tuple(array, 2);
|
||||
EXPECT_THAT(array_as_tuple, ElementsAre(0, 1));
|
||||
EXPECT_THAT(array_as_tuple, Not(ElementsAre(0)));
|
||||
|
||||
NativeArrayPassedAsPointerAndSize helper;
|
||||
EXPECT_CALL(helper, Helper(_, _))
|
||||
.With(ElementsAre(0, 1));
|
||||
helper.Helper(array, 2);
|
||||
}
|
||||
|
||||
TEST(ElementsAreTest, WorksWithTwoDimensionalNativeArray) {
|
||||
const char a2[][3] = { "hi", "lo" };
|
||||
EXPECT_THAT(a2, ElementsAre(ElementsAre('h', 'i', '\0'),
|
||||
ElementsAre('l', 'o', '\0')));
|
||||
EXPECT_THAT(a2, ElementsAre(StrEq("hi"), StrEq("lo")));
|
||||
EXPECT_THAT(a2, ElementsAre(Not(ElementsAre('h', 'o', '\0')),
|
||||
ElementsAre('l', 'o', '\0')));
|
||||
}
|
||||
|
||||
// Tests for ElementsAreArray(). Since ElementsAreArray() shares most
|
||||
// of the implementation with ElementsAre(), we don't test it as
|
||||
// thoroughly here.
|
||||
@@ -379,6 +519,17 @@ TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherArray) {
|
||||
EXPECT_THAT(test_vector, Not(ElementsAreArray(kMatcherArray)));
|
||||
}
|
||||
|
||||
// Since ElementsAre() and ElementsAreArray() share much of the
|
||||
// implementation, we only do a sanity test for native arrays here.
|
||||
TEST(ElementsAreArrayTest, WorksWithNativeArray) {
|
||||
::std::string a[] = { "hi", "ho" };
|
||||
::std::string b[] = { "hi", "ho" };
|
||||
|
||||
EXPECT_THAT(a, ElementsAreArray(b));
|
||||
EXPECT_THAT(a, ElementsAreArray(b, 2));
|
||||
EXPECT_THAT(a, Not(ElementsAreArray(b, 1)));
|
||||
}
|
||||
|
||||
// Tests for the MATCHER*() macro family.
|
||||
|
||||
// Tests that a simple MATCHER() definition works.
|
||||
@@ -443,12 +594,23 @@ namespace matcher_test {
|
||||
MATCHER(IsOdd, "") { return (arg % 2) != 0; }
|
||||
} // namespace matcher_test
|
||||
|
||||
TEST(MatcherTest, WorksInNamespace) {
|
||||
TEST(MatcherMacroTest, WorksInNamespace) {
|
||||
Matcher<int> m = matcher_test::IsOdd();
|
||||
EXPECT_FALSE(m.Matches(4));
|
||||
EXPECT_TRUE(m.Matches(5));
|
||||
}
|
||||
|
||||
// Tests that Value() can be used to compose matchers.
|
||||
MATCHER(IsPositiveOdd, "") {
|
||||
return Value(arg, matcher_test::IsOdd()) && arg > 0;
|
||||
}
|
||||
|
||||
TEST(MatcherMacroTest, CanBeComposedUsingValue) {
|
||||
EXPECT_THAT(3, IsPositiveOdd());
|
||||
EXPECT_THAT(4, Not(IsPositiveOdd()));
|
||||
EXPECT_THAT(-1, Not(IsPositiveOdd()));
|
||||
}
|
||||
|
||||
// Tests that a simple MATCHER_P() definition works.
|
||||
|
||||
MATCHER_P(IsGreaterThan32And, n, "") { return arg > 32 && arg > n; }
|
||||
@@ -742,14 +904,31 @@ TEST(MatcherPnMacroTest, TypesAreCorrect) {
|
||||
EqualsSumOf(1, 2, 3, 4, 5, 6, 7, 8, 9, '0');
|
||||
}
|
||||
|
||||
// Tests that matcher-typed parameters can be used in Value() inside a
|
||||
// MATCHER_Pn definition.
|
||||
|
||||
// Succeeds if arg matches exactly 2 of the 3 matchers.
|
||||
MATCHER_P3(TwoOf, m1, m2, m3, "") {
|
||||
const int count = static_cast<int>(Value(arg, m1))
|
||||
+ static_cast<int>(Value(arg, m2)) + static_cast<int>(Value(arg, m3));
|
||||
return count == 2;
|
||||
}
|
||||
|
||||
TEST(MatcherPnMacroTest, CanUseMatcherTypedParameterInValue) {
|
||||
EXPECT_THAT(42, TwoOf(Gt(0), Lt(50), Eq(10)));
|
||||
EXPECT_THAT(0, Not(TwoOf(Gt(-1), Lt(1), Eq(0))));
|
||||
}
|
||||
|
||||
// Tests Contains().
|
||||
|
||||
TEST(ContainsTest, ListMatchesWhenElementIsInContainer) {
|
||||
list<int> some_list;
|
||||
some_list.push_back(3);
|
||||
some_list.push_back(1);
|
||||
some_list.push_back(2);
|
||||
EXPECT_THAT(some_list, Contains(1));
|
||||
EXPECT_THAT(some_list, Contains(3.0));
|
||||
EXPECT_THAT(some_list, Contains(2.0f));
|
||||
EXPECT_THAT(some_list, Contains(Gt(2.5)));
|
||||
EXPECT_THAT(some_list, Contains(Eq(2.0f)));
|
||||
|
||||
list<string> another_list;
|
||||
another_list.push_back("fee");
|
||||
@@ -771,8 +950,8 @@ TEST(ContainsTest, SetMatchesWhenElementIsInContainer) {
|
||||
some_set.insert(3);
|
||||
some_set.insert(1);
|
||||
some_set.insert(2);
|
||||
EXPECT_THAT(some_set, Contains(1.0));
|
||||
EXPECT_THAT(some_set, Contains(3.0f));
|
||||
EXPECT_THAT(some_set, Contains(Eq(1.0)));
|
||||
EXPECT_THAT(some_set, Contains(Eq(3.0f)));
|
||||
EXPECT_THAT(some_set, Contains(2));
|
||||
|
||||
set<const char*> another_set;
|
||||
@@ -780,7 +959,7 @@ TEST(ContainsTest, SetMatchesWhenElementIsInContainer) {
|
||||
another_set.insert("fie");
|
||||
another_set.insert("foe");
|
||||
another_set.insert("fum");
|
||||
EXPECT_THAT(another_set, Contains(string("fum")));
|
||||
EXPECT_THAT(another_set, Contains(Eq(string("fum"))));
|
||||
}
|
||||
|
||||
TEST(ContainsTest, SetDoesNotMatchWhenElementIsNotInContainer) {
|
||||
@@ -795,8 +974,20 @@ TEST(ContainsTest, SetDoesNotMatchWhenElementIsNotInContainer) {
|
||||
}
|
||||
|
||||
TEST(ContainsTest, DescribesItselfCorrectly) {
|
||||
const int a[2] = { 1, 2 };
|
||||
Matcher<const int(&)[2]> m = Contains(2);
|
||||
EXPECT_EQ("element 1 matches", Explain(m, a));
|
||||
|
||||
m = Contains(3);
|
||||
EXPECT_EQ("", Explain(m, a));
|
||||
}
|
||||
|
||||
TEST(ContainsTest, ExplainsMatchResultCorrectly) {
|
||||
Matcher<vector<int> > m = Contains(1);
|
||||
EXPECT_EQ("contains 1", Describe(m));
|
||||
EXPECT_EQ("contains at least one element that is equal to 1", Describe(m));
|
||||
|
||||
Matcher<vector<int> > m2 = Not(m);
|
||||
EXPECT_EQ("doesn't contain any element that is equal to 1", Describe(m2));
|
||||
}
|
||||
|
||||
TEST(ContainsTest, MapMatchesWhenElementIsInContainer) {
|
||||
@@ -823,7 +1014,7 @@ TEST(ContainsTest, MapDoesNotMatchWhenElementIsNotInContainer) {
|
||||
|
||||
TEST(ContainsTest, ArrayMatchesWhenElementIsInContainer) {
|
||||
const char* string_array[] = { "fee", "fie", "foe", "fum" };
|
||||
EXPECT_THAT(string_array, Contains(string("fum")));
|
||||
EXPECT_THAT(string_array, Contains(Eq(string("fum"))));
|
||||
}
|
||||
|
||||
TEST(ContainsTest, ArrayDoesNotMatchWhenElementIsNotInContainer) {
|
||||
@@ -831,4 +1022,25 @@ TEST(ContainsTest, ArrayDoesNotMatchWhenElementIsNotInContainer) {
|
||||
EXPECT_THAT(int_array, Not(Contains(5)));
|
||||
}
|
||||
|
||||
TEST(ContainsTest, AcceptsMatcher) {
|
||||
const int a[] = { 1, 2, 3 };
|
||||
EXPECT_THAT(a, Contains(Gt(2)));
|
||||
EXPECT_THAT(a, Not(Contains(Gt(4))));
|
||||
}
|
||||
|
||||
TEST(ContainsTest, WorksForNativeArrayAsTuple) {
|
||||
const int a[] = { 1, 2 };
|
||||
const int* const pointer = a;
|
||||
EXPECT_THAT(make_tuple(pointer, 2), Contains(1));
|
||||
EXPECT_THAT(make_tuple(pointer, 2), Not(Contains(Gt(3))));
|
||||
}
|
||||
|
||||
TEST(ContainsTest, WorksForTwoDimensionalNativeArray) {
|
||||
int a[][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
|
||||
EXPECT_THAT(a, Contains(ElementsAre(4, 5, 6)));
|
||||
EXPECT_THAT(a, Contains(Contains(5)));
|
||||
EXPECT_THAT(a, Not(Contains(ElementsAre(3, 4, 5))));
|
||||
EXPECT_THAT(a, Contains(Not(Contains(5))));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace internal {
|
||||
|
||||
namespace {
|
||||
|
||||
using ::std::tr1::make_tuple;
|
||||
using ::std::tr1::tuple;
|
||||
|
||||
TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContainsNoWord) {
|
||||
@@ -130,6 +131,8 @@ TEST(RemoveConstTest, DoesNotAffectNonConstType) {
|
||||
// Tests that RemoveConst removes const from const types.
|
||||
TEST(RemoveConstTest, RemovesConst) {
|
||||
CompileAssertTypesEqual<int, RemoveConst<const int>::type>();
|
||||
CompileAssertTypesEqual<char[2], RemoveConst<const char[2]>::type>();
|
||||
CompileAssertTypesEqual<char[2][3], RemoveConst<const char[2][3]>::type>();
|
||||
}
|
||||
|
||||
// Tests GMOCK_REMOVE_CONST_.
|
||||
@@ -494,6 +497,34 @@ TEST(ExpectTest, FailsNonfatallyOnFalse) {
|
||||
}, "Expectation failed");
|
||||
}
|
||||
|
||||
// Tests LogIsVisible().
|
||||
|
||||
class LogIsVisibleTest : public ::testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() { original_verbose_ = GMOCK_FLAG(verbose); }
|
||||
virtual void TearDown() { GMOCK_FLAG(verbose) = original_verbose_; }
|
||||
|
||||
string original_verbose_;
|
||||
};
|
||||
|
||||
TEST_F(LogIsVisibleTest, AlwaysReturnsTrueIfVerbosityIsInfo) {
|
||||
GMOCK_FLAG(verbose) = kInfoVerbosity;
|
||||
EXPECT_TRUE(LogIsVisible(INFO));
|
||||
EXPECT_TRUE(LogIsVisible(WARNING));
|
||||
}
|
||||
|
||||
TEST_F(LogIsVisibleTest, AlwaysReturnsFalseIfVerbosityIsError) {
|
||||
GMOCK_FLAG(verbose) = kErrorVerbosity;
|
||||
EXPECT_FALSE(LogIsVisible(INFO));
|
||||
EXPECT_FALSE(LogIsVisible(WARNING));
|
||||
}
|
||||
|
||||
TEST_F(LogIsVisibleTest, WorksWhenVerbosityIsWarning) {
|
||||
GMOCK_FLAG(verbose) = kWarningVerbosity;
|
||||
EXPECT_FALSE(LogIsVisible(INFO));
|
||||
EXPECT_TRUE(LogIsVisible(WARNING));
|
||||
}
|
||||
|
||||
// TODO(wan@google.com): find a way to re-enable these tests.
|
||||
#if 0
|
||||
|
||||
@@ -693,6 +724,236 @@ TEST(OnCallTest, LogsAnythingArgument) {
|
||||
|
||||
#endif // 0
|
||||
|
||||
// Tests ArrayEq().
|
||||
|
||||
TEST(ArrayEqTest, WorksForDegeneratedArrays) {
|
||||
EXPECT_TRUE(ArrayEq(5, 5L));
|
||||
EXPECT_FALSE(ArrayEq('a', 0));
|
||||
}
|
||||
|
||||
TEST(ArrayEqTest, WorksForOneDimensionalArrays) {
|
||||
const int a[] = { 0, 1 };
|
||||
long b[] = { 0, 1 };
|
||||
EXPECT_TRUE(ArrayEq(a, b));
|
||||
EXPECT_TRUE(ArrayEq(a, 2, b));
|
||||
|
||||
b[0] = 2;
|
||||
EXPECT_FALSE(ArrayEq(a, b));
|
||||
EXPECT_FALSE(ArrayEq(a, 1, b));
|
||||
}
|
||||
|
||||
TEST(ArrayEqTest, WorksForTwoDimensionalArrays) {
|
||||
const char a[][3] = { "hi", "lo" };
|
||||
const char b[][3] = { "hi", "lo" };
|
||||
const char c[][3] = { "hi", "li" };
|
||||
|
||||
EXPECT_TRUE(ArrayEq(a, b));
|
||||
EXPECT_TRUE(ArrayEq(a, 2, b));
|
||||
|
||||
EXPECT_FALSE(ArrayEq(a, c));
|
||||
EXPECT_FALSE(ArrayEq(a, 2, c));
|
||||
}
|
||||
|
||||
// Tests ArrayAwareFind().
|
||||
|
||||
TEST(ArrayAwareFindTest, WorksForOneDimensionalArray) {
|
||||
const char a[] = "hello";
|
||||
EXPECT_EQ(a + 4, ArrayAwareFind(a, a + 5, 'o'));
|
||||
EXPECT_EQ(a + 5, ArrayAwareFind(a, a + 5, 'x'));
|
||||
}
|
||||
|
||||
TEST(ArrayAwareFindTest, WorksForTwoDimensionalArray) {
|
||||
int a[][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 } };
|
||||
const int b[2] = { 2, 3 };
|
||||
EXPECT_EQ(a + 1, ArrayAwareFind(a, a + 3, b));
|
||||
|
||||
const int c[2] = { 6, 7 };
|
||||
EXPECT_EQ(a + 3, ArrayAwareFind(a, a + 3, c));
|
||||
}
|
||||
|
||||
// Tests CopyArray().
|
||||
|
||||
TEST(CopyArrayTest, WorksForDegeneratedArrays) {
|
||||
int n = 0;
|
||||
CopyArray('a', &n);
|
||||
EXPECT_EQ('a', n);
|
||||
}
|
||||
|
||||
TEST(CopyArrayTest, WorksForOneDimensionalArrays) {
|
||||
const char a[3] = "hi";
|
||||
int b[3];
|
||||
CopyArray(a, &b);
|
||||
EXPECT_TRUE(ArrayEq(a, b));
|
||||
|
||||
int c[3];
|
||||
CopyArray(a, 3, c);
|
||||
EXPECT_TRUE(ArrayEq(a, c));
|
||||
}
|
||||
|
||||
TEST(CopyArrayTest, WorksForTwoDimensionalArrays) {
|
||||
const int a[2][3] = { { 0, 1, 2 }, { 3, 4, 5 } };
|
||||
int b[2][3];
|
||||
CopyArray(a, &b);
|
||||
EXPECT_TRUE(ArrayEq(a, b));
|
||||
|
||||
int c[2][3];
|
||||
CopyArray(a, 2, c);
|
||||
EXPECT_TRUE(ArrayEq(a, c));
|
||||
}
|
||||
|
||||
// Tests NativeArray.
|
||||
|
||||
TEST(NativeArrayTest, ConstructorFromArrayReferenceWorks) {
|
||||
const int a[3] = { 0, 1, 2 };
|
||||
NativeArray<int> na(a, kReference);
|
||||
EXPECT_EQ(3, na.size());
|
||||
EXPECT_EQ(a, na.begin());
|
||||
}
|
||||
|
||||
TEST(NativeArrayTest, ConstructorFromTupleWorks) {
|
||||
int a[3] = { 0, 1, 2 };
|
||||
int* const p = a;
|
||||
// Tests with a plain pointer.
|
||||
NativeArray<int> na(make_tuple(p, 3U), kReference);
|
||||
EXPECT_EQ(a, na.begin());
|
||||
|
||||
const linked_ptr<char> b(new char);
|
||||
*b = 'a';
|
||||
// Tests with a smart pointer.
|
||||
NativeArray<char> nb(make_tuple(b, 1), kCopy);
|
||||
EXPECT_NE(b.get(), nb.begin());
|
||||
EXPECT_EQ('a', nb.begin()[0]);
|
||||
}
|
||||
|
||||
TEST(NativeArrayTest, CreatesAndDeletesCopyOfArrayWhenAskedTo) {
|
||||
typedef int Array[2];
|
||||
Array* a = new Array[1];
|
||||
(*a)[0] = 0;
|
||||
(*a)[1] = 1;
|
||||
NativeArray<int> na(*a, kCopy);
|
||||
EXPECT_NE(*a, na.begin());
|
||||
delete[] a;
|
||||
EXPECT_EQ(0, na.begin()[0]);
|
||||
EXPECT_EQ(1, na.begin()[1]);
|
||||
|
||||
// We rely on the heap checker to verify that na deletes the copy of
|
||||
// array.
|
||||
}
|
||||
|
||||
TEST(NativeArrayTest, TypeMembersAreCorrect) {
|
||||
StaticAssertTypeEq<char, NativeArray<char>::value_type>();
|
||||
StaticAssertTypeEq<int[2], NativeArray<int[2]>::value_type>();
|
||||
|
||||
StaticAssertTypeEq<const char*, NativeArray<char>::const_iterator>();
|
||||
StaticAssertTypeEq<const bool(*)[2], NativeArray<bool[2]>::const_iterator>();
|
||||
}
|
||||
|
||||
TEST(NativeArrayTest, MethodsWork) {
|
||||
const int a[] = { 0, 1, 2 };
|
||||
NativeArray<int> na(a, kCopy);
|
||||
ASSERT_EQ(3, na.size());
|
||||
EXPECT_EQ(3, na.end() - na.begin());
|
||||
|
||||
NativeArray<int>::const_iterator it = na.begin();
|
||||
EXPECT_EQ(0, *it);
|
||||
++it;
|
||||
EXPECT_EQ(1, *it);
|
||||
it++;
|
||||
EXPECT_EQ(2, *it);
|
||||
++it;
|
||||
EXPECT_EQ(na.end(), it);
|
||||
|
||||
EXPECT_THAT(na, Eq(na));
|
||||
|
||||
NativeArray<int> na2(a, kReference);
|
||||
EXPECT_THAT(na, Eq(na2));
|
||||
|
||||
const int b1[] = { 0, 1, 1 };
|
||||
const int b2[] = { 0, 1, 2, 3 };
|
||||
EXPECT_THAT(na, Not(Eq(NativeArray<int>(b1, kReference))));
|
||||
EXPECT_THAT(na, Not(Eq(NativeArray<int>(b2, kCopy))));
|
||||
}
|
||||
|
||||
TEST(NativeArrayTest, WorksForTwoDimensionalArray) {
|
||||
const char a[2][3] = { "hi", "lo" };
|
||||
NativeArray<char[3]> na(a, kReference);
|
||||
ASSERT_EQ(2, na.size());
|
||||
EXPECT_EQ(a, na.begin());
|
||||
}
|
||||
|
||||
// Tests StlContainerView.
|
||||
|
||||
TEST(StlContainerViewTest, WorksForStlContainer) {
|
||||
StaticAssertTypeEq<std::vector<int>,
|
||||
StlContainerView<std::vector<int> >::type>();
|
||||
StaticAssertTypeEq<const std::vector<double>&,
|
||||
StlContainerView<std::vector<double> >::const_reference>();
|
||||
|
||||
typedef std::vector<char> Chars;
|
||||
Chars v1;
|
||||
const Chars& v2(StlContainerView<Chars>::ConstReference(v1));
|
||||
EXPECT_EQ(&v1, &v2);
|
||||
|
||||
v1.push_back('a');
|
||||
Chars v3 = StlContainerView<Chars>::Copy(v1);
|
||||
EXPECT_THAT(v3, Eq(v3));
|
||||
}
|
||||
|
||||
TEST(StlContainerViewTest, WorksForStaticNativeArray) {
|
||||
StaticAssertTypeEq<NativeArray<int>,
|
||||
StlContainerView<int[3]>::type>();
|
||||
StaticAssertTypeEq<NativeArray<double>,
|
||||
StlContainerView<const double[4]>::type>();
|
||||
StaticAssertTypeEq<NativeArray<char[3]>,
|
||||
StlContainerView<const char[2][3]>::type>();
|
||||
|
||||
StaticAssertTypeEq<const NativeArray<int>,
|
||||
StlContainerView<int[2]>::const_reference>();
|
||||
|
||||
int a1[3] = { 0, 1, 2 };
|
||||
NativeArray<int> a2 = StlContainerView<int[3]>::ConstReference(a1);
|
||||
EXPECT_EQ(3, a2.size());
|
||||
EXPECT_EQ(a1, a2.begin());
|
||||
|
||||
const NativeArray<int> a3 = StlContainerView<int[3]>::Copy(a1);
|
||||
ASSERT_EQ(3, a3.size());
|
||||
EXPECT_EQ(0, a3.begin()[0]);
|
||||
EXPECT_EQ(1, a3.begin()[1]);
|
||||
EXPECT_EQ(2, a3.begin()[2]);
|
||||
|
||||
// Makes sure a1 and a3 aren't aliases.
|
||||
a1[0] = 3;
|
||||
EXPECT_EQ(0, a3.begin()[0]);
|
||||
}
|
||||
|
||||
TEST(StlContainerViewTest, WorksForDynamicNativeArray) {
|
||||
StaticAssertTypeEq<NativeArray<int>,
|
||||
StlContainerView<tuple<const int*, size_t> >::type>();
|
||||
StaticAssertTypeEq<NativeArray<double>,
|
||||
StlContainerView<tuple<linked_ptr<double>, int> >::type>();
|
||||
|
||||
StaticAssertTypeEq<const NativeArray<int>,
|
||||
StlContainerView<tuple<const int*, int> >::const_reference>();
|
||||
|
||||
int a1[3] = { 0, 1, 2 };
|
||||
const int* const p1 = a1;
|
||||
NativeArray<int> a2 = StlContainerView<tuple<const int*, int> >::
|
||||
ConstReference(make_tuple(p1, 3));
|
||||
EXPECT_EQ(3, a2.size());
|
||||
EXPECT_EQ(a1, a2.begin());
|
||||
|
||||
const NativeArray<int> a3 = StlContainerView<tuple<int*, size_t> >::
|
||||
Copy(make_tuple(static_cast<int*>(a1), 3));
|
||||
ASSERT_EQ(3, a3.size());
|
||||
EXPECT_EQ(0, a3.begin()[0]);
|
||||
EXPECT_EQ(1, a3.begin()[1]);
|
||||
EXPECT_EQ(2, a3.begin()[2]);
|
||||
|
||||
// Makes sure a1 and a3 aren't aliases.
|
||||
a1[0] = 3;
|
||||
EXPECT_EQ(0, a3.begin()[0]);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
@@ -60,7 +60,9 @@ bool SkipPrefix(const char* prefix, const char** pstr);
|
||||
namespace gmock_matchers_test {
|
||||
|
||||
using std::stringstream;
|
||||
using std::tr1::make_tuple;
|
||||
using testing::A;
|
||||
using testing::AllArgs;
|
||||
using testing::AllOf;
|
||||
using testing::An;
|
||||
using testing::AnyOf;
|
||||
@@ -98,6 +100,7 @@ using testing::StrEq;
|
||||
using testing::StrNe;
|
||||
using testing::Truly;
|
||||
using testing::TypedEq;
|
||||
using testing::Value;
|
||||
using testing::_;
|
||||
using testing::internal::FloatingEqMatcher;
|
||||
using testing::internal::FormatMatcherDescriptionSyntaxError;
|
||||
@@ -1333,7 +1336,7 @@ TEST(Eq2Test, MatchesEqualArguments) {
|
||||
// Tests that Eq() describes itself properly.
|
||||
TEST(Eq2Test, CanDescribeSelf) {
|
||||
Matcher<const Tuple2&> m = Eq();
|
||||
EXPECT_EQ("argument #0 is equal to argument #1", Describe(m));
|
||||
EXPECT_EQ("are a pair (x, y) where x == y", Describe(m));
|
||||
}
|
||||
|
||||
// Tests that Ge() matches a 2-tuple where the first field >= the
|
||||
@@ -1348,8 +1351,7 @@ TEST(Ge2Test, MatchesGreaterThanOrEqualArguments) {
|
||||
// Tests that Ge() describes itself properly.
|
||||
TEST(Ge2Test, CanDescribeSelf) {
|
||||
Matcher<const Tuple2&> m = Ge();
|
||||
EXPECT_EQ("argument #0 is greater than or equal to argument #1",
|
||||
Describe(m));
|
||||
EXPECT_EQ("are a pair (x, y) where x >= y", Describe(m));
|
||||
}
|
||||
|
||||
// Tests that Gt() matches a 2-tuple where the first field > the
|
||||
@@ -1364,7 +1366,7 @@ TEST(Gt2Test, MatchesGreaterThanArguments) {
|
||||
// Tests that Gt() describes itself properly.
|
||||
TEST(Gt2Test, CanDescribeSelf) {
|
||||
Matcher<const Tuple2&> m = Gt();
|
||||
EXPECT_EQ("argument #0 is greater than argument #1", Describe(m));
|
||||
EXPECT_EQ("are a pair (x, y) where x > y", Describe(m));
|
||||
}
|
||||
|
||||
// Tests that Le() matches a 2-tuple where the first field <= the
|
||||
@@ -1379,8 +1381,7 @@ TEST(Le2Test, MatchesLessThanOrEqualArguments) {
|
||||
// Tests that Le() describes itself properly.
|
||||
TEST(Le2Test, CanDescribeSelf) {
|
||||
Matcher<const Tuple2&> m = Le();
|
||||
EXPECT_EQ("argument #0 is less than or equal to argument #1",
|
||||
Describe(m));
|
||||
EXPECT_EQ("are a pair (x, y) where x <= y", Describe(m));
|
||||
}
|
||||
|
||||
// Tests that Lt() matches a 2-tuple where the first field < the
|
||||
@@ -1395,7 +1396,7 @@ TEST(Lt2Test, MatchesLessThanArguments) {
|
||||
// Tests that Lt() describes itself properly.
|
||||
TEST(Lt2Test, CanDescribeSelf) {
|
||||
Matcher<const Tuple2&> m = Lt();
|
||||
EXPECT_EQ("argument #0 is less than argument #1", Describe(m));
|
||||
EXPECT_EQ("are a pair (x, y) where x < y", Describe(m));
|
||||
}
|
||||
|
||||
// Tests that Ne() matches a 2-tuple where the first field != the
|
||||
@@ -1410,7 +1411,7 @@ TEST(Ne2Test, MatchesUnequalArguments) {
|
||||
// Tests that Ne() describes itself properly.
|
||||
TEST(Ne2Test, CanDescribeSelf) {
|
||||
Matcher<const Tuple2&> m = Ne();
|
||||
EXPECT_EQ("argument #0 is not equal to argument #1", Describe(m));
|
||||
EXPECT_EQ("are a pair (x, y) where x != y", Describe(m));
|
||||
}
|
||||
|
||||
// Tests that Not(m) matches any value that doesn't match m.
|
||||
@@ -1670,6 +1671,54 @@ TEST(MatchesTest, WorksWithMatcherOnNonRefType) {
|
||||
EXPECT_FALSE(Matches(eq5)(2));
|
||||
}
|
||||
|
||||
// Tests Value(value, matcher). Since Value() is a simple wrapper for
|
||||
// Matches(), which has been tested already, we don't spend a lot of
|
||||
// effort on testing Value().
|
||||
TEST(ValueTest, WorksWithPolymorphicMatcher) {
|
||||
EXPECT_TRUE(Value("hi", StartsWith("h")));
|
||||
EXPECT_FALSE(Value(5, Gt(10)));
|
||||
}
|
||||
|
||||
TEST(ValueTest, WorksWithMonomorphicMatcher) {
|
||||
const Matcher<int> is_zero = Eq(0);
|
||||
EXPECT_TRUE(Value(0, is_zero));
|
||||
EXPECT_FALSE(Value('a', is_zero));
|
||||
|
||||
int n = 0;
|
||||
const Matcher<const int&> ref_n = Ref(n);
|
||||
EXPECT_TRUE(Value(n, ref_n));
|
||||
EXPECT_FALSE(Value(1, ref_n));
|
||||
}
|
||||
|
||||
TEST(AllArgsTest, WorksForTuple) {
|
||||
EXPECT_THAT(make_tuple(1, 2L), AllArgs(Lt()));
|
||||
EXPECT_THAT(make_tuple(2L, 1), Not(AllArgs(Lt())));
|
||||
}
|
||||
|
||||
TEST(AllArgsTest, WorksForNonTuple) {
|
||||
EXPECT_THAT(42, AllArgs(Gt(0)));
|
||||
EXPECT_THAT('a', Not(AllArgs(Eq('b'))));
|
||||
}
|
||||
|
||||
class AllArgsHelper {
|
||||
public:
|
||||
MOCK_METHOD2(Helper, int(char x, int y));
|
||||
};
|
||||
|
||||
TEST(AllArgsTest, WorksInWithClause) {
|
||||
AllArgsHelper helper;
|
||||
ON_CALL(helper, Helper(_, _))
|
||||
.With(AllArgs(Lt()))
|
||||
.WillByDefault(Return(1));
|
||||
EXPECT_CALL(helper, Helper(_, _));
|
||||
EXPECT_CALL(helper, Helper(_, _))
|
||||
.With(AllArgs(Gt()))
|
||||
.WillOnce(Return(2));
|
||||
|
||||
EXPECT_EQ(1, helper.Helper('\1', 2));
|
||||
EXPECT_EQ(2, helper.Helper('a', 1));
|
||||
}
|
||||
|
||||
// Tests that ASSERT_THAT() and EXPECT_THAT() work when the value
|
||||
// matches the matcher.
|
||||
TEST(MatcherAssertionTest, WorksWhenMatcherIsSatisfied) {
|
||||
@@ -2765,9 +2814,7 @@ TEST(ByRefTest, AllowsNotCopyableValueInMatchers) {
|
||||
// different element types.
|
||||
|
||||
template <typename T>
|
||||
class ContainerEqTest : public testing::Test {
|
||||
public:
|
||||
};
|
||||
class ContainerEqTest : public testing::Test {};
|
||||
|
||||
typedef testing::Types<
|
||||
std::set<int>,
|
||||
@@ -2901,6 +2948,60 @@ TEST(ContainerEqExtraTest, WorksForMaps) {
|
||||
Explain(m, test_map));
|
||||
}
|
||||
|
||||
TEST(ContainerEqExtraTest, WorksForNativeArray) {
|
||||
int a1[] = { 1, 2, 3 };
|
||||
int a2[] = { 1, 2, 3 };
|
||||
int b[] = { 1, 2, 4 };
|
||||
|
||||
EXPECT_THAT(a1, ContainerEq(a2));
|
||||
EXPECT_THAT(a1, Not(ContainerEq(b)));
|
||||
}
|
||||
|
||||
TEST(ContainerEqExtraTest, WorksForTwoDimensionalNativeArray) {
|
||||
const char a1[][3] = { "hi", "lo" };
|
||||
const char a2[][3] = { "hi", "lo" };
|
||||
const char b[][3] = { "lo", "hi" };
|
||||
|
||||
// Tests using ContainerEq() in the first dimension.
|
||||
EXPECT_THAT(a1, ContainerEq(a2));
|
||||
EXPECT_THAT(a1, Not(ContainerEq(b)));
|
||||
|
||||
// Tests using ContainerEq() in the second dimension.
|
||||
EXPECT_THAT(a1, ElementsAre(ContainerEq(a2[0]), ContainerEq(a2[1])));
|
||||
EXPECT_THAT(a1, ElementsAre(Not(ContainerEq(b[0])), ContainerEq(a2[1])));
|
||||
}
|
||||
|
||||
TEST(ContainerEqExtraTest, WorksForNativeArrayAsTuple) {
|
||||
const int a1[] = { 1, 2, 3 };
|
||||
const int a2[] = { 1, 2, 3 };
|
||||
const int b[] = { 1, 2, 3, 4 };
|
||||
|
||||
const int* const p1 = a1;
|
||||
EXPECT_THAT(make_tuple(p1, 3), ContainerEq(a2));
|
||||
EXPECT_THAT(make_tuple(p1, 3), Not(ContainerEq(b)));
|
||||
|
||||
const int c[] = { 1, 3, 2 };
|
||||
EXPECT_THAT(make_tuple(p1, 3), Not(ContainerEq(c)));
|
||||
}
|
||||
|
||||
TEST(ContainerEqExtraTest, CopiesNativeArrayParameter) {
|
||||
std::string a1[][3] = {
|
||||
{ "hi", "hello", "ciao" },
|
||||
{ "bye", "see you", "ciao" }
|
||||
};
|
||||
|
||||
std::string a2[][3] = {
|
||||
{ "hi", "hello", "ciao" },
|
||||
{ "bye", "see you", "ciao" }
|
||||
};
|
||||
|
||||
const Matcher<const std::string(&)[2][3]> m = ContainerEq(a2);
|
||||
EXPECT_THAT(a1, m);
|
||||
|
||||
a2[0][0] = "ha";
|
||||
EXPECT_THAT(a1, m);
|
||||
}
|
||||
|
||||
// Tests GetParamIndex().
|
||||
|
||||
TEST(GetParamIndexTest, WorksForEmptyParamList) {
|
||||
|
||||
@@ -154,10 +154,13 @@ using ::std::tr1::tuple;
|
||||
using ::std::vector;
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::StartsWith;
|
||||
using ::testing::internal::NativeArray;
|
||||
using ::testing::internal::Strings;
|
||||
using ::testing::internal::UniversalTersePrint;
|
||||
using ::testing::internal::UniversalPrint;
|
||||
using ::testing::internal::UniversalTersePrintTupleFieldsToStrings;
|
||||
using ::testing::internal::UniversalPrinter;
|
||||
using ::testing::internal::kReference;
|
||||
using ::testing::internal::string;
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
@@ -485,75 +488,58 @@ TEST(PrintPointerTest, MemberFunctionPointer) {
|
||||
|
||||
// Tests printing C arrays.
|
||||
|
||||
// One-dimensional array.
|
||||
|
||||
void ArrayHelper1(int (&a)[5]) { // NOLINT
|
||||
EXPECT_EQ("{ 1, 2, 3, 4, 5 }", Print(a));
|
||||
// The difference between this and Print() is that it ensures that the
|
||||
// argument is a reference to an array.
|
||||
template <typename T, size_t N>
|
||||
string PrintArrayHelper(T (&a)[N]) {
|
||||
return Print(a);
|
||||
}
|
||||
|
||||
// One-dimensional array.
|
||||
TEST(PrintArrayTest, OneDimensionalArray) {
|
||||
int a[5] = { 1, 2, 3, 4, 5 };
|
||||
ArrayHelper1(a);
|
||||
EXPECT_EQ("{ 1, 2, 3, 4, 5 }", PrintArrayHelper(a));
|
||||
}
|
||||
|
||||
// Two-dimensional array.
|
||||
|
||||
void ArrayHelper2(int (&a)[2][5]) { // NOLINT
|
||||
EXPECT_EQ("{ { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 0 } }", Print(a));
|
||||
}
|
||||
|
||||
TEST(PrintArrayTest, TwoDimensionalArray) {
|
||||
int a[2][5] = {
|
||||
{ 1, 2, 3, 4, 5 },
|
||||
{ 6, 7, 8, 9, 0 }
|
||||
};
|
||||
ArrayHelper2(a);
|
||||
EXPECT_EQ("{ { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 0 } }", PrintArrayHelper(a));
|
||||
}
|
||||
|
||||
// Array of const elements.
|
||||
|
||||
void ArrayHelper3(const bool (&a)[1]) { // NOLINT
|
||||
EXPECT_EQ("{ false }", Print(a));
|
||||
}
|
||||
|
||||
TEST(PrintArrayTest, ConstArray) {
|
||||
const bool a[1] = { false };
|
||||
ArrayHelper3(a);
|
||||
EXPECT_EQ("{ false }", PrintArrayHelper(a));
|
||||
}
|
||||
|
||||
// Char array.
|
||||
|
||||
void ArrayHelper4(char (&a)[3]) { // NOLINT
|
||||
EXPECT_EQ(PrintPointer(a) + " pointing to \"Hi\"", Print(a));
|
||||
}
|
||||
|
||||
TEST(PrintArrayTest, CharArray) {
|
||||
char a[3] = "Hi";
|
||||
ArrayHelper4(a);
|
||||
// Array a contains '\0' in the middle and doesn't end with '\0'.
|
||||
char a[3] = { 'H', '\0', 'i' };
|
||||
EXPECT_EQ("\"H\\0i\"", PrintArrayHelper(a));
|
||||
}
|
||||
|
||||
// Const char array.
|
||||
|
||||
void ArrayHelper5(const char (&a)[3]) { // NOLINT
|
||||
EXPECT_EQ(Print(a), PrintPointer(a) + " pointing to \"Hi\"");
|
||||
}
|
||||
|
||||
TEST(PrintArrayTest, ConstCharArray) {
|
||||
const char a[3] = "Hi";
|
||||
ArrayHelper5(a);
|
||||
const char a[4] = "\0Hi";
|
||||
EXPECT_EQ("\"\\0Hi\\0\"", PrintArrayHelper(a));
|
||||
}
|
||||
|
||||
// Array of objects.
|
||||
TEST(PrintArrayTest, ObjectArray) {
|
||||
string a[3] = { "Hi", "Hello", "Ni hao" };
|
||||
EXPECT_EQ("{ \"Hi\", \"Hello\", \"Ni hao\" }", Print(a));
|
||||
EXPECT_EQ("{ \"Hi\", \"Hello\", \"Ni hao\" }", PrintArrayHelper(a));
|
||||
}
|
||||
|
||||
// Array with many elements.
|
||||
TEST(PrintArrayTest, BigArray) {
|
||||
int a[100] = { 1, 2, 3 };
|
||||
EXPECT_EQ("{ 1, 2, 3, 0, 0, 0, 0, 0, ..., 0, 0, 0, 0, 0, 0, 0, 0 }",
|
||||
Print(a));
|
||||
PrintArrayHelper(a));
|
||||
}
|
||||
|
||||
// Tests printing ::string and ::std::string.
|
||||
@@ -803,6 +789,17 @@ TEST(PrintStlContainerTest, NestedContainer) {
|
||||
EXPECT_EQ("{ { 1, 2 }, { 3, 4, 5 } }", Print(v));
|
||||
}
|
||||
|
||||
TEST(PrintStlContainerTest, OneDimensionalNativeArray) {
|
||||
const int a[] = { 1, 2, 3 };
|
||||
NativeArray<int> b(a, kReference);
|
||||
EXPECT_EQ("{ 1, 2, 3 }", Print(b));
|
||||
}
|
||||
|
||||
TEST(PrintStlContainerTest, TwoDimensionalNativeArray) {
|
||||
const int a[][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
|
||||
NativeArray<int[3]> b(a, kReference);
|
||||
EXPECT_EQ("{ { 1, 2, 3 }, { 4, 5, 6 } }", Print(b));
|
||||
}
|
||||
|
||||
// Tests printing tuples.
|
||||
|
||||
@@ -995,6 +992,11 @@ TEST(PrintToStringTest, WorksForReference) {
|
||||
UniversalPrinter<const int&>::PrintToString(n));
|
||||
}
|
||||
|
||||
TEST(PrintToStringTest, WorksForArray) {
|
||||
int n[3] = { 1, 2, 3 };
|
||||
EXPECT_EQ("{ 1, 2, 3 }", UniversalPrinter<int[3]>::PrintToString(n));
|
||||
}
|
||||
|
||||
TEST(UniversalTersePrintTest, WorksForNonReference) {
|
||||
::std::stringstream ss;
|
||||
UniversalTersePrint(123, &ss);
|
||||
@@ -1025,6 +1027,37 @@ TEST(UniversalTersePrintTest, WorksForCString) {
|
||||
EXPECT_EQ("NULL", ss3.str());
|
||||
}
|
||||
|
||||
TEST(UniversalPrintTest, WorksForNonReference) {
|
||||
::std::stringstream ss;
|
||||
UniversalPrint(123, &ss);
|
||||
EXPECT_EQ("123", ss.str());
|
||||
}
|
||||
|
||||
TEST(UniversalPrintTest, WorksForReference) {
|
||||
const int& n = 123;
|
||||
::std::stringstream ss;
|
||||
UniversalPrint(n, &ss);
|
||||
EXPECT_EQ("123", ss.str());
|
||||
}
|
||||
|
||||
TEST(UniversalPrintTest, WorksForCString) {
|
||||
const char* s1 = "abc";
|
||||
::std::stringstream ss1;
|
||||
UniversalPrint(s1, &ss1);
|
||||
EXPECT_EQ(PrintPointer(s1) + " pointing to \"abc\"", string(ss1.str()));
|
||||
|
||||
char* s2 = const_cast<char*>(s1);
|
||||
::std::stringstream ss2;
|
||||
UniversalPrint(s2, &ss2);
|
||||
EXPECT_EQ(PrintPointer(s2) + " pointing to \"abc\"", string(ss2.str()));
|
||||
|
||||
const char* s3 = NULL;
|
||||
::std::stringstream ss3;
|
||||
UniversalPrint(s3, &ss3);
|
||||
EXPECT_EQ("NULL", ss3.str());
|
||||
}
|
||||
|
||||
|
||||
TEST(UniversalTersePrintTupleFieldsToStringsTest, PrintsEmptyTuple) {
|
||||
EXPECT_THAT(UniversalTersePrintTupleFieldsToStrings(make_tuple()),
|
||||
ElementsAre());
|
||||
|
||||
@@ -72,6 +72,7 @@ using testing::Const;
|
||||
using testing::DoAll;
|
||||
using testing::DoDefault;
|
||||
using testing::GMOCK_FLAG(verbose);
|
||||
using testing::Gt;
|
||||
using testing::InSequence;
|
||||
using testing::Invoke;
|
||||
using testing::InvokeWithoutArgs;
|
||||
@@ -96,6 +97,7 @@ class MockA {
|
||||
MOCK_METHOD1(DoA, void(int n)); // NOLINT
|
||||
MOCK_METHOD1(ReturnResult, Result(int n)); // NOLINT
|
||||
MOCK_METHOD2(Binary, bool(int x, int y)); // NOLINT
|
||||
MOCK_METHOD2(ReturnInt, int(int x, int y)); // NOLINT
|
||||
};
|
||||
|
||||
class MockB {
|
||||
@@ -171,25 +173,25 @@ TEST(OnCallSyntaxTest, EvaluatesSecondArgumentOnce) {
|
||||
|
||||
// Tests that the syntax of ON_CALL() is enforced at run time.
|
||||
|
||||
TEST(OnCallSyntaxTest, WithArgumentsIsOptional) {
|
||||
TEST(OnCallSyntaxTest, WithIsOptional) {
|
||||
MockA a;
|
||||
|
||||
ON_CALL(a, DoA(5))
|
||||
.WillByDefault(Return());
|
||||
ON_CALL(a, DoA(_))
|
||||
.WithArguments(_)
|
||||
.With(_)
|
||||
.WillByDefault(Return());
|
||||
}
|
||||
|
||||
TEST(OnCallSyntaxTest, WithArgumentsCanAppearAtMostOnce) {
|
||||
TEST(OnCallSyntaxTest, WithCanAppearAtMostOnce) {
|
||||
MockA a;
|
||||
|
||||
EXPECT_NONFATAL_FAILURE({ // NOLINT
|
||||
ON_CALL(a, ReturnResult(_))
|
||||
.WithArguments(_)
|
||||
.WithArguments(_)
|
||||
.With(_)
|
||||
.With(_)
|
||||
.WillByDefault(Return(Result()));
|
||||
}, ".WithArguments() cannot appear more than once in an ON_CALL()");
|
||||
}, ".With() cannot appear more than once in an ON_CALL()");
|
||||
}
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
@@ -237,47 +239,44 @@ TEST(ExpectCallSyntaxTest, EvaluatesSecondArgumentOnce) {
|
||||
|
||||
// Tests that the syntax of EXPECT_CALL() is enforced at run time.
|
||||
|
||||
TEST(ExpectCallSyntaxTest, WithArgumentsIsOptional) {
|
||||
TEST(ExpectCallSyntaxTest, WithIsOptional) {
|
||||
MockA a;
|
||||
|
||||
EXPECT_CALL(a, DoA(5))
|
||||
.Times(0);
|
||||
EXPECT_CALL(a, DoA(6))
|
||||
.WithArguments(_)
|
||||
.With(_)
|
||||
.Times(0);
|
||||
}
|
||||
|
||||
TEST(ExpectCallSyntaxTest, WithArgumentsCanAppearAtMostOnce) {
|
||||
TEST(ExpectCallSyntaxTest, WithCanAppearAtMostOnce) {
|
||||
MockA a;
|
||||
|
||||
EXPECT_NONFATAL_FAILURE({ // NOLINT
|
||||
EXPECT_CALL(a, DoA(6))
|
||||
.WithArguments(_)
|
||||
.WithArguments(_);
|
||||
}, ".WithArguments() cannot appear more than once in "
|
||||
"an EXPECT_CALL()");
|
||||
.With(_)
|
||||
.With(_);
|
||||
}, ".With() cannot appear more than once in an EXPECT_CALL()");
|
||||
|
||||
a.DoA(6);
|
||||
}
|
||||
|
||||
TEST(ExpectCallSyntaxTest, WithArgumentsMustBeFirstClause) {
|
||||
TEST(ExpectCallSyntaxTest, WithMustBeFirstClause) {
|
||||
MockA a;
|
||||
|
||||
EXPECT_NONFATAL_FAILURE({ // NOLINT
|
||||
EXPECT_CALL(a, DoA(1))
|
||||
.Times(1)
|
||||
.WithArguments(_);
|
||||
}, ".WithArguments() must be the first clause in an "
|
||||
"EXPECT_CALL()");
|
||||
.With(_);
|
||||
}, ".With() must be the first clause in an EXPECT_CALL()");
|
||||
|
||||
a.DoA(1);
|
||||
|
||||
EXPECT_NONFATAL_FAILURE({ // NOLINT
|
||||
EXPECT_CALL(a, DoA(2))
|
||||
.WillOnce(Return())
|
||||
.WithArguments(_);
|
||||
}, ".WithArguments() must be the first clause in an "
|
||||
"EXPECT_CALL()");
|
||||
.With(_);
|
||||
}, ".With() must be the first clause in an EXPECT_CALL()");
|
||||
|
||||
a.DoA(2);
|
||||
}
|
||||
@@ -1612,6 +1611,53 @@ TEST_F(GMockVerboseFlagTest, InvalidFlagIsTreatedAsWarning) {
|
||||
|
||||
#endif // 0
|
||||
|
||||
// A helper class that generates a failure when printed. We use it to
|
||||
// ensure that Google Mock doesn't print a value (even to an internal
|
||||
// buffer) when it is not supposed to do so.
|
||||
class PrintMeNot {};
|
||||
|
||||
void PrintTo(PrintMeNot /* dummy */, ::std::ostream* /* os */) {
|
||||
ADD_FAILURE() << "Google Mock is printing a value that shouldn't be "
|
||||
<< "printed even to an internal buffer.";
|
||||
}
|
||||
|
||||
class LogTestHelper {
|
||||
public:
|
||||
MOCK_METHOD1(Foo, PrintMeNot(PrintMeNot));
|
||||
};
|
||||
|
||||
class GMockLogTest : public ::testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() { original_verbose_ = GMOCK_FLAG(verbose); }
|
||||
virtual void TearDown() { GMOCK_FLAG(verbose) = original_verbose_; }
|
||||
|
||||
LogTestHelper helper_;
|
||||
string original_verbose_;
|
||||
};
|
||||
|
||||
TEST_F(GMockLogTest, DoesNotPrintGoodCallInternallyIfVerbosityIsWarning) {
|
||||
GMOCK_FLAG(verbose) = kWarningVerbosity;
|
||||
EXPECT_CALL(helper_, Foo(_))
|
||||
.WillOnce(Return(PrintMeNot()));
|
||||
helper_.Foo(PrintMeNot()); // This is an expected call.
|
||||
}
|
||||
|
||||
TEST_F(GMockLogTest, DoesNotPrintGoodCallInternallyIfVerbosityIsError) {
|
||||
GMOCK_FLAG(verbose) = kErrorVerbosity;
|
||||
EXPECT_CALL(helper_, Foo(_))
|
||||
.WillOnce(Return(PrintMeNot()));
|
||||
helper_.Foo(PrintMeNot()); // This is an expected call.
|
||||
}
|
||||
|
||||
TEST_F(GMockLogTest, DoesNotPrintWarningInternallyIfVerbosityIsError) {
|
||||
GMOCK_FLAG(verbose) = kErrorVerbosity;
|
||||
ON_CALL(helper_, Foo(_))
|
||||
.WillByDefault(Return(PrintMeNot()));
|
||||
helper_.Foo(PrintMeNot()); // This should generate a warning.
|
||||
}
|
||||
|
||||
// Tests Mock::AllowLeak().
|
||||
|
||||
TEST(AllowLeakTest, AllowsLeakingUnusedMockObject) {
|
||||
MockA* a = new MockA;
|
||||
Mock::AllowLeak(a);
|
||||
|
||||
@@ -120,6 +120,7 @@
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include <gmock/internal/gmock-port.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
@@ -177,19 +177,19 @@ TEST_F(GMockOutputTest, MismatchArguments) {
|
||||
foo_.Bar(s, 0, 0);
|
||||
}
|
||||
|
||||
TEST_F(GMockOutputTest, MismatchWithArguments) {
|
||||
TEST_F(GMockOutputTest, MismatchWith) {
|
||||
EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1)))
|
||||
.WithArguments(Ge());
|
||||
.With(Ge());
|
||||
|
||||
foo_.Bar2(2, 3); // Mismatch WithArguments()
|
||||
foo_.Bar2(2, 3); // Mismatch With()
|
||||
foo_.Bar2(2, 1);
|
||||
}
|
||||
|
||||
TEST_F(GMockOutputTest, MismatchArgumentsAndWithArguments) {
|
||||
TEST_F(GMockOutputTest, MismatchArgumentsAndWith) {
|
||||
EXPECT_CALL(foo_, Bar2(Ge(2), Ge(1)))
|
||||
.WithArguments(Ge());
|
||||
.With(Ge());
|
||||
|
||||
foo_.Bar2(1, 3); // Mismatch arguments and mismatch WithArguments()
|
||||
foo_.Bar2(1, 3); // Mismatch arguments and mismatch With()
|
||||
foo_.Bar2(2, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ FILE:#:
|
||||
Expected: to be called once
|
||||
Actual: never called - unsatisfied and active
|
||||
[ FAILED ] GMockOutputTest.MismatchArguments
|
||||
[ RUN ] GMockOutputTest.MismatchWithArguments
|
||||
[ RUN ] GMockOutputTest.MismatchWith
|
||||
unknown file: Failure
|
||||
|
||||
Unexpected mock function call - returning default value.
|
||||
@@ -183,12 +183,12 @@ Unexpected mock function call - returning default value.
|
||||
Google Mock tried the following 1 expectation, but it didn't match:
|
||||
|
||||
FILE:#:
|
||||
Expected: argument #0 is greater than or equal to argument #1
|
||||
Actual: false
|
||||
Expected args: are a pair (x, y) where x >= y
|
||||
Actual: don't match
|
||||
Expected: to be called once
|
||||
Actual: never called - unsatisfied and active
|
||||
[ FAILED ] GMockOutputTest.MismatchWithArguments
|
||||
[ RUN ] GMockOutputTest.MismatchArgumentsAndWithArguments
|
||||
[ FAILED ] GMockOutputTest.MismatchWith
|
||||
[ RUN ] GMockOutputTest.MismatchArgumentsAndWith
|
||||
unknown file: Failure
|
||||
|
||||
Unexpected mock function call - returning default value.
|
||||
@@ -199,11 +199,11 @@ Google Mock tried the following 1 expectation, but it didn't match:
|
||||
FILE:#:
|
||||
Expected arg #0: is greater than or equal to 2
|
||||
Actual: 1
|
||||
Expected: argument #0 is greater than or equal to argument #1
|
||||
Actual: false
|
||||
Expected args: are a pair (x, y) where x >= y
|
||||
Actual: don't match
|
||||
Expected: to be called once
|
||||
Actual: never called - unsatisfied and active
|
||||
[ FAILED ] GMockOutputTest.MismatchArgumentsAndWithArguments
|
||||
[ FAILED ] GMockOutputTest.MismatchArgumentsAndWith
|
||||
[ RUN ] GMockOutputTest.UnexpectedCallWithDefaultAction
|
||||
unknown file: Failure
|
||||
|
||||
@@ -290,8 +290,8 @@ Stack trace:
|
||||
[ FAILED ] GMockOutputTest.UnsatisfiedPrerequisites
|
||||
[ FAILED ] GMockOutputTest.UnsatisfiedExpectation
|
||||
[ FAILED ] GMockOutputTest.MismatchArguments
|
||||
[ FAILED ] GMockOutputTest.MismatchWithArguments
|
||||
[ FAILED ] GMockOutputTest.MismatchArgumentsAndWithArguments
|
||||
[ FAILED ] GMockOutputTest.MismatchWith
|
||||
[ FAILED ] GMockOutputTest.MismatchArgumentsAndWith
|
||||
[ FAILED ] GMockOutputTest.UnexpectedCallWithDefaultAction
|
||||
[ FAILED ] GMockOutputTest.ExcessiveCallWithDefaultAction
|
||||
|
||||
|
||||
+17
-11
@@ -12,15 +12,7 @@
|
||||
'type': '<(library)',
|
||||
'msvs_guid': 'BFE8E2A7-3B3B-43B0-A994-3058B852DB8B',
|
||||
'sources': [
|
||||
'gtest/include/gtest/internal/gtest-death-test-internal.h',
|
||||
'gtest/include/gtest/internal/gtest-filepath.h',
|
||||
'gtest/include/gtest/internal/gtest-internal.h',
|
||||
'gtest/include/gtest/internal/gtest-linked_ptr.h',
|
||||
'gtest/include/gtest/internal/gtest-param-util-generated.h',
|
||||
'gtest/include/gtest/internal/gtest-param-util.h',
|
||||
'gtest/include/gtest/internal/gtest-port.h',
|
||||
'gtest/include/gtest/internal/gtest-string.h',
|
||||
'gtest/include/gtest/internal/gtest-type-util.h',
|
||||
# Sources based on files in r267 of gmock.
|
||||
'gtest/include/gtest/gtest-death-test.h',
|
||||
'gtest/include/gtest/gtest-message.h',
|
||||
'gtest/include/gtest/gtest-param-test.h',
|
||||
@@ -30,17 +22,31 @@
|
||||
'gtest/include/gtest/gtest.h',
|
||||
'gtest/include/gtest/gtest_pred_impl.h',
|
||||
'gtest/include/gtest/gtest_prod.h',
|
||||
'gtest/src/gtest-test-part.cc',
|
||||
'gtest/src/gtest-typed-test.cc',
|
||||
'gtest/include/gtest/internal/gtest-death-test-internal.h',
|
||||
'gtest/include/gtest/internal/gtest-filepath.h',
|
||||
'gtest/include/gtest/internal/gtest-internal.h',
|
||||
'gtest/include/gtest/internal/gtest-linked_ptr.h',
|
||||
'gtest/include/gtest/internal/gtest-param-util-generated.h',
|
||||
'gtest/include/gtest/internal/gtest-param-util.h',
|
||||
'gtest/include/gtest/internal/gtest-port.h',
|
||||
'gtest/include/gtest/internal/gtest-string.h',
|
||||
'gtest/include/gtest/internal/gtest-tuple.h',
|
||||
'gtest/include/gtest/internal/gtest-type-util.h',
|
||||
'gtest/src/gtest-all.cc',
|
||||
'gtest/src/gtest-death-test.cc',
|
||||
'gtest/src/gtest-filepath.cc',
|
||||
'gtest/src/gtest-internal-inl.h',
|
||||
'gtest/src/gtest-port.cc',
|
||||
'gtest/src/gtest-test-part.cc',
|
||||
'gtest/src/gtest-typed-test.cc',
|
||||
'gtest/src/gtest.cc',
|
||||
'multiprocess_func_list.cc',
|
||||
'multiprocess_func_list.h',
|
||||
'platform_test.h',
|
||||
],
|
||||
'sources!': [
|
||||
'gtest/src/gtest-all.cc', # Not needed by our build.
|
||||
],
|
||||
'include_dirs': [
|
||||
'gtest',
|
||||
'gtest/include',
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário