summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-22 18:32:21 +0000
committerajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-22 18:32:21 +0000
commit22015c33fe44a1cc36596e0b6de37a48dc13b131 (patch)
tree643966e3ad01ab48b4f1d0ab48793261c68cee02
parentad764d54ec391e95e4ea239aa8eed548ce45cb61 (diff)
downloadchromium_src-22015c33fe44a1cc36596e0b6de37a48dc13b131.zip
chromium_src-22015c33fe44a1cc36596e0b6de37a48dc13b131.tar.gz
chromium_src-22015c33fe44a1cc36596e0b6de37a48dc13b131.tar.bz2
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
-rw-r--r--DEPS2
-rw-r--r--testing/README.chromium45
-rw-r--r--testing/chromium.patch20
-rw-r--r--testing/gmock.gyp1
-rw-r--r--testing/gmock/Makefile.am22
-rw-r--r--testing/gmock/README81
-rw-r--r--testing/gmock/configure.ac2
-rw-r--r--testing/gmock/include/gmock/gmock-generated-matchers.h431
-rw-r--r--testing/gmock/include/gmock/gmock-generated-matchers.h.pump222
-rw-r--r--testing/gmock/include/gmock/gmock-matchers.h198
-rw-r--r--testing/gmock/include/gmock/gmock-printers.h101
-rw-r--r--testing/gmock/include/gmock/gmock-spec-builders.h442
-rw-r--r--testing/gmock/include/gmock/gmock.h8
-rw-r--r--testing/gmock/include/gmock/internal/gmock-internal-utils.h251
-rw-r--r--testing/gmock/include/gmock/internal/gmock-port.h19
-rw-r--r--testing/gmock/include/gmock/internal/gmock-port.h.orig326
-rw-r--r--testing/gmock/msvc/gmock_config.vsprops7
-rw-r--r--testing/gmock/scripts/generator/README2
-rwxr-xr-xtesting/gmock/scripts/generator/cpp/ast.py14
-rwxr-xr-xtesting/gmock/scripts/generator/cpp/gmock_class.py19
-rwxr-xr-xtesting/gmock/scripts/generator/cpp/gmock_class_test.py137
-rwxr-xr-xtesting/gmock/scripts/gmock-config.in2
-rwxr-xr-xtesting/gmock/scripts/gmock_doctor.py156
-rw-r--r--testing/gmock/src/gmock-internal-utils.cc44
-rw-r--r--testing/gmock/src/gmock-printers.cc5
-rw-r--r--testing/gmock/src/gmock-spec-builders.cc4
-rw-r--r--testing/gmock/test/gmock-generated-actions_test.cc96
-rw-r--r--testing/gmock/test/gmock-generated-matchers_test.cc228
-rw-r--r--testing/gmock/test/gmock-internal-utils_test.cc261
-rw-r--r--testing/gmock/test/gmock-matchers_test.cc123
-rw-r--r--testing/gmock/test/gmock-printers_test.cc99
-rw-r--r--testing/gmock/test/gmock-spec-builders_test.cc86
-rw-r--r--testing/gmock/test/gmock_link_test.h1
-rw-r--r--testing/gmock/test/gmock_output_test_.cc12
-rw-r--r--testing/gmock/test/gmock_output_test_golden.txt20
-rw-r--r--testing/gtest.gyp28
36 files changed, 2458 insertions, 1057 deletions
diff --git a/DEPS b/DEPS
index 1cbf521..590f478 100644
--- a/DEPS
+++ b/DEPS
@@ -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",
diff --git a/testing/README.chromium b/testing/README.chromium
index 67e6451..ed305ee 100644
--- a/testing/README.chromium
+++ b/testing/README.chromium
@@ -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.
diff --git a/testing/chromium.patch b/testing/chromium.patch
deleted file mode 100644
index 26b5662..0000000
--- a/testing/chromium.patch
+++ /dev/null
@@ -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__
-
diff --git a/testing/gmock.gyp b/testing/gmock.gyp
index 4e56089..dd446f2 100644
--- a/testing/gmock.gyp
+++ b/testing/gmock.gyp
@@ -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',
diff --git a/testing/gmock/Makefile.am b/testing/gmock/Makefile.am
index 7a821a0..196b927 100644
--- a/testing/gmock/Makefile.am
+++ b/testing/gmock/Makefile.am
@@ -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
diff --git a/testing/gmock/README b/testing/gmock/README
index f14279c..9cbda5d 100644
--- a/testing/gmock/README
+++ b/testing/gmock/README
@@ -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
diff --git a/testing/gmock/configure.ac b/testing/gmock/configure.ac
index c317979..78ff30d 100644
--- a/testing/gmock/configure.ac
+++ b/testing/gmock/configure.ac
@@ -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.
diff --git a/testing/gmock/include/gmock/gmock-generated-matchers.h b/testing/gmock/include/gmock/gmock-generated-matchers.h
index afe1bd4..1a3e60b 100644
--- a/testing/gmock/include/gmock/gmock-generated-matchers.h
+++ b/testing/gmock/include/gmock/gmock-generated-matchers.h
@@ -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_
diff --git a/testing/gmock/include/gmock/gmock-generated-matchers.h.pump b/testing/gmock/include/gmock/gmock-generated-matchers.h.pump
index 09dfedf..653a2e8 100644
--- a/testing/gmock/include/gmock/gmock-generated-matchers.h.pump
+++ b/testing/gmock/include/gmock/gmock-generated-matchers.h.pump
@@ -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_
diff --git a/testing/gmock/include/gmock/gmock-matchers.h b/testing/gmock/include/gmock/gmock-matchers.h
index 0497be2..dc252e3 100644
--- a/testing/gmock/include/gmock/gmock-matchers.h
+++ b/testing/gmock/include/gmock/gmock-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,
diff --git a/testing/gmock/include/gmock/gmock-printers.h b/testing/gmock/include/gmock/gmock-printers.h
index 9900243..561de3d 100644
--- a/testing/gmock/include/gmock/gmock-printers.h
+++ b/testing/gmock/include/gmock/gmock-printers.h
@@ -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".
diff --git a/testing/gmock/include/gmock/gmock-spec-builders.h b/testing/gmock/include/gmock/gmock-spec-builders.h
index cc48bc0..a22bcd1 100644
--- a/testing/gmock/include/gmock/gmock-spec-builders.h
+++ b/testing/gmock/include/gmock/gmock-spec-builders.h
@@ -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;
-
- // 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);
-
- // 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());
-
- mocker->PerformDefaultAction(args, ss.str());
- ReportUninterestingCall(reaction, ss.str());
- return;
+typename Function<F>::Result FunctionMockerBase<F>::InvokeWith(
+ const typename Function<F>::ArgumentTuple& args) {
+ typedef ActionResultHolder<Result> ResultHolder;
+
+ 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(MockObject());
+
+ // 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;
-
- // 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);
- }
-
- 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());
- }
- }
-}; // class InvokeWithHelper<void, F>
+ DescribeUninterestingCall(args, &ss);
+
+ // Calculates the function result.
+ const ResultHolder result =
+ ResultHolder::PerformDefaultAction(this, args, ss.str());
+
+ // Prints the function result.
+ result.PrintAsActionResult(&ss);
+
+ ReportUninterestingCall(reaction, ss.str());
+ return result.value();
+ }
+
+ 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
diff --git a/testing/gmock/include/gmock/gmock.h b/testing/gmock/include/gmock/gmock.h
index 22e7028..29d9727 100644
--- a/testing/gmock/include/gmock/gmock.h
+++ b/testing/gmock/include/gmock/gmock.h
@@ -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(...) *
diff --git a/testing/gmock/include/gmock/internal/gmock-internal-utils.h b/testing/gmock/include/gmock/internal/gmock-internal-utils.h
index b02682f..ee6aa1e 100644
--- a/testing/gmock/include/gmock/internal/gmock-internal-utils.h
+++ b/testing/gmock/include/gmock/internal/gmock-internal-utils.h
@@ -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
diff --git a/testing/gmock/include/gmock/internal/gmock-port.h b/testing/gmock/include/gmock/internal/gmock-port.h
index 5aa0fd8..9ee8f72 100644
--- a/testing/gmock/include/gmock/internal/gmock-port.h
+++ b/testing/gmock/include/gmock/internal/gmock-port.h
@@ -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
diff --git a/testing/gmock/include/gmock/internal/gmock-port.h.orig b/testing/gmock/include/gmock/internal/gmock-port.h.orig
deleted file mode 100644
index e4f4e23..0000000
--- a/testing/gmock/include/gmock/internal/gmock-port.h.orig
+++ /dev/null
@@ -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_
diff --git a/testing/gmock/msvc/gmock_config.vsprops b/testing/gmock/msvc/gmock_config.vsprops
index fa596ef..a68c32e 100644
--- a/testing/gmock/msvc/gmock_config.vsprops
+++ b/testing/gmock/msvc/gmock_config.vsprops
@@ -6,15 +6,10 @@
>
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="&quot;$(BoostDir)/boost/tr1/tr1&quot;;&quot;$(BoostDir)&quot;;&quot;$(GTestDir)/include&quot;"
- PreprocessorDefinitions="GTEST_HAS_TR1_TUPLE=1"
+ AdditionalIncludeDirectories="&quot;$(GTestDir)/include&quot;"
/>
<UserMacro
Name="GTestDir"
Value="../gtest"
/>
- <UserMacro
- Name="BoostDir"
- Value="../boost"
- />
</VisualStudioPropertySheet>
diff --git a/testing/gmock/scripts/generator/README b/testing/gmock/scripts/generator/README
index 071bf0f..d6f9597 100644
--- a/testing/gmock/scripts/generator/README
+++ b/testing/gmock/scripts/generator/README
@@ -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
-----------------
diff --git a/testing/gmock/scripts/generator/cpp/ast.py b/testing/gmock/scripts/generator/cpp/ast.py
index 6d1c8d3..47dc9a0 100755
--- a/testing/gmock/scripts/generator/cpp/ast.py
+++ b/testing/gmock/scripts/generator/cpp/ast.py
@@ -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
diff --git a/testing/gmock/scripts/generator/cpp/gmock_class.py b/testing/gmock/scripts/generator/cpp/gmock_class.py
index 2920424..3ad0bcd 100755
--- a/testing/gmock/scripts/generator/cpp/gmock_class.py
+++ b/testing/gmock/scripts/generator/cpp/gmock_class.py
@@ -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__':
diff --git a/testing/gmock/scripts/generator/cpp/gmock_class_test.py b/testing/gmock/scripts/generator/cpp/gmock_class_test.py
new file mode 100755
index 0000000..ae00800
--- /dev/null
+++ b/testing/gmock/scripts/generator/cpp/gmock_class_test.py
@@ -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()
diff --git a/testing/gmock/scripts/gmock-config.in b/testing/gmock/scripts/gmock-config.in
index 016ad61..9ce17a2 100755
--- a/testing/gmock/scripts/gmock-config.in
+++ b/testing/gmock/scripts/gmock-config.in
@@ -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.
diff --git a/testing/gmock/scripts/gmock_doctor.py b/testing/gmock/scripts/gmock_doctor.py
index 907089e..05e4258 100755
--- a/testing/gmock/scripts/gmock_doctor.py
+++ b/testing/gmock/scripts/gmock_doctor.py
@@ -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,
]
diff --git a/testing/gmock/src/gmock-internal-utils.cc b/testing/gmock/src/gmock-internal-utils.cc
index 735abce..0e693c7 100644
--- a/testing/gmock/src/gmock-internal-utils.cc
+++ b/testing/gmock/src/gmock-internal-utils.cc
@@ -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
diff --git a/testing/gmock/src/gmock-printers.cc b/testing/gmock/src/gmock-printers.cc
index e6d4001..922a7b2 100644
--- a/testing/gmock/src/gmock-printers.cc
+++ b/testing/gmock/src/gmock-printers.cc
@@ -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.
diff --git a/testing/gmock/src/gmock-spec-builders.cc b/testing/gmock/src/gmock-spec-builders.cc
index 65a74b8..465e4d6 100644
--- a/testing/gmock/src/gmock-spec-builders.cc
+++ b/testing/gmock/src/gmock-spec-builders.cc
@@ -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);
diff --git a/testing/gmock/test/gmock-generated-actions_test.cc b/testing/gmock/test/gmock-generated-actions_test.cc
index 84e5a41..d0b2ddc 100644
--- a/testing/gmock/test/gmock-generated-actions_test.cc
+++ b/testing/gmock/test/gmock-generated-actions_test.cc
@@ -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);
}
diff --git a/testing/gmock/test/gmock-generated-matchers_test.cc b/testing/gmock/test/gmock-generated-matchers_test.cc
index 669652b..19024d0 100644
--- a/testing/gmock/test/gmock-generated-matchers_test.cc
+++ b/testing/gmock/test/gmock-generated-matchers_test.cc
@@ -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
diff --git a/testing/gmock/test/gmock-internal-utils_test.cc b/testing/gmock/test/gmock-internal-utils_test.cc
index 5e4dc03..9ab15af 100644
--- a/testing/gmock/test/gmock-internal-utils_test.cc
+++ b/testing/gmock/test/gmock-internal-utils_test.cc
@@ -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
diff --git a/testing/gmock/test/gmock-matchers_test.cc b/testing/gmock/test/gmock-matchers_test.cc
index e770901..3541eef 100644
--- a/testing/gmock/test/gmock-matchers_test.cc
+++ b/testing/gmock/test/gmock-matchers_test.cc
@@ -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) {
diff --git a/testing/gmock/test/gmock-printers_test.cc b/testing/gmock/test/gmock-printers_test.cc
index 29a0db8..8c03ec4 100644
--- a/testing/gmock/test/gmock-printers_test.cc
+++ b/testing/gmock/test/gmock-printers_test.cc
@@ -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());
diff --git a/testing/gmock/test/gmock-spec-builders_test.cc b/testing/gmock/test/gmock-spec-builders_test.cc
index e8c3902..058d343c 100644
--- a/testing/gmock/test/gmock-spec-builders_test.cc
+++ b/testing/gmock/test/gmock-spec-builders_test.cc
@@ -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);
diff --git a/testing/gmock/test/gmock_link_test.h b/testing/gmock/test/gmock_link_test.h
index 4e0adb7..b903f3c 100644
--- a/testing/gmock/test/gmock_link_test.h
+++ b/testing/gmock/test/gmock_link_test.h
@@ -120,6 +120,7 @@
#include <errno.h>
#endif
+#include <gmock/internal/gmock-port.h>
#include <gtest/gtest.h>
#include <iostream>
#include <vector>
diff --git a/testing/gmock/test/gmock_output_test_.cc b/testing/gmock/test/gmock_output_test_.cc
index 97619af..8244f10 100644
--- a/testing/gmock/test/gmock_output_test_.cc
+++ b/testing/gmock/test/gmock_output_test_.cc
@@ -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);
}
diff --git a/testing/gmock/test/gmock_output_test_golden.txt b/testing/gmock/test/gmock_output_test_golden.txt
index 887b7be..aeec660 100644
--- a/testing/gmock/test/gmock_output_test_golden.txt
+++ b/testing/gmock/test/gmock_output_test_golden.txt
@@ -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
diff --git a/testing/gtest.gyp b/testing/gtest.gyp
index 061667e..e9d15f5 100644
--- a/testing/gtest.gyp
+++ b/testing/gtest.gyp
@@ -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',