diff options
author | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-25 17:03:47 +0000 |
---|---|---|
committer | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-25 17:03:47 +0000 |
commit | 762217321f240970b7a7dc404470caedbf43cd5e (patch) | |
tree | b0b66383100d57a8272e4b622580dff16b5007ee /testing/gmock | |
parent | 7ee7e191bb9f5419b6f6fd9036e6bcdc77d5cc0b (diff) | |
download | chromium_src-762217321f240970b7a7dc404470caedbf43cd5e.zip chromium_src-762217321f240970b7a7dc404470caedbf43cd5e.tar.gz chromium_src-762217321f240970b7a7dc404470caedbf43cd5e.tar.bz2 |
Update to current gtest/gmock.
Synced in new gmock, twiddled DEPS for new gtest, updated README.
BUG=34160
Review URL: http://codereview.chromium.org/1151006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42625 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'testing/gmock')
21 files changed, 1389 insertions, 890 deletions
diff --git a/testing/gmock/CHANGES b/testing/gmock/CHANGES index f703ac2..16fc85d 100644 --- a/testing/gmock/CHANGES +++ b/testing/gmock/CHANGES @@ -1,3 +1,27 @@ +Changes for 1.5.0: + + * Support for use in multi-threaded tests on platforms having pthreads + (by virtue of the Google Test thread change) + * The new matcher API lets user-defined matchers generate custom + explanations more directly and efficiently. + * Better expectation failure messages. + * NotNull() and IsNull() now work with smart pointers. + * Field() and Property() now work when the matcher argument is a pointer + passed by reference. + * Regular expression matching on all platforms. + * Added GCC 4.0 support for Google Mock Doctor. + * Added gmock_all_test.cc for compiling most Google Mock tests + in a single file. + * Significantly cleaned up compiler warnings. + * Bug fixes, better test coverage, and implementation clean-ups. + + Potentially breaking changes: + + * Custom matchers defined using MatcherInterface or MakePolymorphicMatcher() + need to be updated after upgrading to Google Mock 1.5.0; matchers defined + using MATCHER or MATCHER_P* aren't affected. + * Dropped support for 'make install'. + Changes for 1.4.0 (we skipped 1.2.* and 1.3.* to match the version of Google Test): diff --git a/testing/gmock/Makefile.am b/testing/gmock/Makefile.am index c10d81c..30941d4f 100644 --- a/testing/gmock/Makefile.am +++ b/testing/gmock/Makefile.am @@ -1,3 +1,5 @@ +# Automake file + # Nonstandard package files for distribution. EXTRA_DIST = @@ -16,6 +18,12 @@ DISTCLEANFILES = scripts/gmock-config # directories. AM_CPPFLAGS = $(GTEST_CPPFLAGS) -I$(srcdir)/include +# Modifies compiler and linker flags for pthreads compatibility. +if HAVE_PTHREADS + AM_CXXFLAGS = @PTHREAD_CFLAGS@ -DGTEST_HAS_PTHREAD=1 + AM_LIBS = @PTHREAD_LIBS@ +endif + # Build rules for libraries. lib_LTLIBRARIES = lib/libgmock.la lib/libgmock_main.la diff --git a/testing/gmock/README b/testing/gmock/README index 9cbda5d..4b3efd8 100644 --- a/testing/gmock/README +++ b/testing/gmock/README @@ -177,78 +177,12 @@ directory otherwise. ${SRCDIR}/configure # Standard GNU configure script, --help for more info -The default behavior of the configure script with respect to locating and using -Google Test is to first search for a 'gtest-config' in the system path, and -lacking this, build an internal copy of Google Test. You may optionally specify -a custom Google Test you wish to build Google Mock against, provided it is -a new enough version. - - # Configure against an installation in '/opt' with '/opt/bin/gtest-config'. - ${SRCDIR}/configure --with-gtest=/opt - -This can also be used to specify a Google Test which hasn't yet been installed. -However, it must have been configured and built as described in the Google Test -README before you configure Google Mock. To enable this feature, simply pass -the directory where you configured and built Google Test (which is not -necessarily its source directory) to Google Mock's configure script. - - # Configure against a build of Google Test in an arbitrary directory. - ${SRCDIR}/configure --with-gtest=../../my_gtest_build - -Finally, if you have a version of Google Test installed but for some reason -wish to forcibly prevent it from being used, we provide a special option. -Typically this is not needed as we fall back to the internal Google Test -packaged with Google Mock if an installed version is either unavailable or too -old to build Google Mock. When using the internally packaged Google Test, the -user does *not* need to configure or build it, that is automatically handled by -Google Mock's build system. - - # Force the use of the internally packaged Google Test, despite - # 'gtest-config' being in your PATH. - ${SRCDIR}/configure --disable-external-gtest - Once you have successfully configured Google Mock, the build steps are standard for GNU-style OSS packages. make # Standard makefile following GNU conventions make check # Builds and runs all tests - all should pass -Other programs will only be able to use Google Mock's functionality if you -install it in a location which they can access, in Linux this is typically -under '/usr/local'. The following command will install all of the Google Mock -libraries, public headers, and utilities necessary for other programs and -libraries to leverage it. Note that if Google Mock was unable to find an -external Google Test to build against, it will also install the internally -packaged Google Test in order to allow the installed Google Mock to function -properly. This Google Test install will be fully functional, and if installed -will also be uninstalled by uninstalling Google Mock. - - sudo make install # Not necessary, but allows use by other programs - -Should you need to remove Google Mock from your system after having installed -it, run the following command, and it will back out its changes. However, note -carefully that you must run this command on the *same* Google Mock build that -you ran the install from, or the results are not predictable. If you install -Google Mock on your system, and are working from a VCS checkout, make sure you -run this *before* updating your checkout of the source in order to uninstall -the same version which you installed. - - sudo make uninstall # Must be run against the exact same build as "install" - -Your project can build against Google Mock and Google Test simply by leveraging -the 'gmock-config' script. This script can be invoked directly out of the -'scripts' subdirectory of the build tree, and it will be installed in the -binary directory specified during the 'configure'. Here are some examples of -its use, see 'gmock-config --help' for more detailed information. - - gmock-config --min-version=1.0 || echo "Insufficient Google Mock version." - - g++ $(gmock-config --cppflags --cxxflags) -o foo.o -c foo.cpp - g++ $(gmock-config --ldflags --libs) -o foo foo.o - - # When using a built but not installed Google Mock: - g++ $(../../my_gmock_build/scripts/gmock-config ...) ... - Note that when building your project against Google Mock, you are building against Google Test as well. There is no need to configure Google Test separately. diff --git a/testing/gmock/configure.ac b/testing/gmock/configure.ac index 25ab6f3..8498a6c 100644 --- a/testing/gmock/configure.ac +++ b/testing/gmock/configure.ac @@ -1,5 +1,7 @@ +m4_include(gtest/m4/acx_pthread.m4) + AC_INIT([Google C++ Mocking Framework], - [1.4.0], + [1.5.0], [googlemock@googlegroups.com], [gmock]) @@ -35,6 +37,25 @@ AM_CONDITIONAL([HAVE_PYTHON],[test "$PYTHON" != ":"]) # TODO(chandlerc@google.com) Check for the necessary system headers. +# Configure pthreads. +AC_ARG_WITH([pthreads], + [AS_HELP_STRING([--with-pthreads], + [use pthreads (default is yes)])], + [with_pthreads=$withval], + [with_pthreads=check]) + +have_pthreads=no +AS_IF([test "x$with_pthreads" != "xno"], + [ACX_PTHREAD( + [], + [AS_IF([test "x$with_pthreads" != "xcheck"], + [AC_MSG_FAILURE( + [--with-pthreads was specified, but unable to be used])])]) + have_pthreads="$acx_pthread_ok"]) +AM_CONDITIONAL([HAVE_PTHREADS],[test "x$have_pthreads" == "xyes"]) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_LIBS) + # GoogleMock currently has hard dependencies upon GoogleTest above and beyond # running its own test suite, so we both provide our own version in # a subdirectory and provide some logic to use a custom version or a system @@ -80,7 +101,7 @@ AC_ARG_VAR([GTEST_VERSION], [The version of Google Test available.]) HAVE_BUILT_GTEST="no" -GTEST_MIN_VERSION="1.4.0" +GTEST_MIN_VERSION="1.5.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 18420c1..731ad7d 100644 --- a/testing/gmock/include/gmock/gmock-generated-matchers.h +++ b/testing/gmock/include/gmock/gmock-generated-matchers.h @@ -229,8 +229,9 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> { 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 bool MatchAndExplain(ArgsTuple args, + MatchResultListener* listener) const { + return inner_matcher_.MatchAndExplain(GetSelectedArgs(args), listener); } virtual void DescribeTo(::std::ostream* os) const { @@ -243,11 +244,6 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> { 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, @@ -852,14 +848,19 @@ ElementsAreArray(const T (&array)[N]) { } // namespace testing // The MATCHER* family of macros can be used in a namespace scope to -// define custom matchers easily. The syntax: +// define custom matchers easily. +// +// Basic Usage +// =========== +// +// The syntax // // MATCHER(name, description_string) { statements; } // -// will define a matcher with the given name that executes the -// statements, which must return a bool to indicate if the match -// succeeds. Inside the statements, you can refer to the value being -// matched by 'arg', and refer to its type by 'arg_type'. +// defines a matcher with the given name that executes the statements, +// which must return a bool to indicate if the match succeeds. Inside +// the statements, you can refer to the value being matched by 'arg', +// and refer to its type by 'arg_type'. // // The description string documents what the matcher does, and is used // to generate the failure message when the match fails. Since a @@ -892,6 +893,9 @@ ElementsAreArray(const T (&array)[N]) { // where the description "is even" is automatically calculated from the // matcher name IsEven. // +// Argument Type +// ============= +// // Note that the type of the value being matched (arg_type) is // determined by the context in which you use the matcher and is // supplied to you by the compiler, so you don't need to worry about @@ -902,6 +906,9 @@ ElementsAreArray(const T (&array)[N]) { // takes an int, 'arg_type' will be int; if it takes an unsigned long, // 'arg_type' will be unsigned long; and so on. // +// Parameterizing Matchers +// ======================= +// // Sometimes you'll want to parameterize the matcher. For that you // can use another macro: // @@ -932,6 +939,9 @@ ElementsAreArray(const T (&array)[N]) { // We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P10 to // support multi-parameter matchers. // +// Describing Parameterized Matchers +// ================================= +// // When defining a parameterized matcher, you can use Python-style // interpolations in the description string to refer to the parameter // values. We support the following syntax currently: @@ -964,6 +974,9 @@ ElementsAreArray(const T (&array)[N]) { // // Expected: in closed range (4, 6) // +// Types of Matcher Parameters +// =========================== +// // For the purpose of typing, you can view // // MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } @@ -991,23 +1004,44 @@ ElementsAreArray(const T (&array)[N]) { // matcher you will see the value of the referenced object but not its // address. // +// Explaining Match Results +// ======================== +// +// Sometimes the matcher description alone isn't enough to explain why +// the match has failed or succeeded. For example, when expecting a +// long string, it can be very helpful to also print the diff between +// the expected string and the actual one. To achieve that, you can +// optionally stream additional information to a special variable +// named result_listener, whose type is a pointer to class +// MatchResultListener: +// +// MATCHER_P(EqualsLongString, str, "") { +// if (arg == str) return true; +// +// *result_listener << "the difference: " +/// << DiffStrings(str, arg); +// return false; +// } +// +// Overloading Matchers +// ==================== +// // You can overload matchers with different numbers of parameters: // // MATCHER_P(Blah, a, description_string1) { ... } // MATCHER_P2(Blah, a, b, description_string2) { ... } // -// While it's tempting to always use the MATCHER* macros when defining -// a new matcher, you should also consider implementing -// MatcherInterface or using MakePolymorphicMatcher() instead, -// especially if you need to use the matcher a lot. While these -// approaches require more work, they give you more control on the -// types of the value being matched and the matcher parameters, which -// in general leads to better compiler error messages that pay off in -// the long run. They also allow overloading matchers based on -// parameter types (as opposed to just based on the number of -// parameters). +// Caveats +// ======= // -// CAVEAT: +// When defining a new matcher, you should also consider implementing +// MatcherInterface or using MakePolymorphicMatcher(). These +// approaches require more work than the MATCHER* macros, but also +// give you more control on the types of the value being matched and +// the matcher parameters, which may leads to better compiler error +// messages when the matcher is used wrong. They also allow +// overloading matchers based on parameter types (as opposed to just +// based on the number of parameters). // // MATCHER*() can only be used in a namespace scope. The reason is // that C++ doesn't yet allow function-local types to be used to @@ -1015,7 +1049,8 @@ ElementsAreArray(const T (&array)[N]) { // Once that's done, we'll consider supporting using MATCHER*() inside // a function. // -// MORE INFORMATION: +// More Information +// ================ // // To learn more about using these macros, please search for 'MATCHER' // on http://code.google.com/p/googlemock/wiki/CookBook. @@ -1028,7 +1063,8 @@ ElementsAreArray(const T (&array)[N]) { public:\ gmock_Impl(const ::testing::internal::Interpolations& gmock_interp)\ : gmock_interp_(gmock_interp) {}\ - virtual bool Matches(arg_type arg) const;\ + virtual bool MatchAndExplain(\ + arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ const ::testing::internal::Strings& gmock_printed_params = \ ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ @@ -1058,8 +1094,10 @@ ElementsAreArray(const T (&array)[N]) { return name##Matcher();\ }\ template <typename arg_type>\ - bool name##Matcher::\ - gmock_Impl<arg_type>::Matches(arg_type arg) const + bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain(\ + arg_type arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const #define MATCHER_P(name, p0, description)\ template <typename p0##_type>\ @@ -1071,7 +1109,8 @@ ElementsAreArray(const T (&array)[N]) { explicit gmock_Impl(p0##_type gmock_p0, \ const ::testing::internal::Interpolations& gmock_interp)\ : p0(gmock_p0), gmock_interp_(gmock_interp) {}\ - virtual bool Matches(arg_type arg) const;\ + virtual bool MatchAndExplain(\ + arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ const ::testing::internal::Strings& gmock_printed_params = \ ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ @@ -1105,8 +1144,10 @@ ElementsAreArray(const T (&array)[N]) { }\ template <typename p0##_type>\ template <typename arg_type>\ - bool name##MatcherP<p0##_type>::\ - gmock_Impl<arg_type>::Matches(arg_type arg) const + bool name##MatcherP<p0##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ + arg_type arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const #define MATCHER_P2(name, p0, p1, description)\ template <typename p0##_type, typename p1##_type>\ @@ -1118,7 +1159,8 @@ ElementsAreArray(const T (&array)[N]) { gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, \ const ::testing::internal::Interpolations& gmock_interp)\ : p0(gmock_p0), p1(gmock_p1), gmock_interp_(gmock_interp) {}\ - virtual bool Matches(arg_type arg) const;\ + virtual bool MatchAndExplain(\ + arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ const ::testing::internal::Strings& gmock_printed_params = \ ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ @@ -1156,8 +1198,11 @@ ElementsAreArray(const T (&array)[N]) { }\ template <typename p0##_type, typename p1##_type>\ template <typename arg_type>\ - bool name##MatcherP2<p0##_type, p1##_type>::\ - gmock_Impl<arg_type>::Matches(arg_type arg) const + bool name##MatcherP2<p0##_type, \ + p1##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ + arg_type arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const #define MATCHER_P3(name, p0, p1, p2, description)\ template <typename p0##_type, typename p1##_type, typename p2##_type>\ @@ -1170,7 +1215,8 @@ ElementsAreArray(const T (&array)[N]) { const ::testing::internal::Interpolations& gmock_interp)\ : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ gmock_interp_(gmock_interp) {}\ - virtual bool Matches(arg_type arg) const;\ + virtual bool MatchAndExplain(\ + arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ const ::testing::internal::Strings& gmock_printed_params = \ ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ @@ -1211,8 +1257,11 @@ ElementsAreArray(const T (&array)[N]) { }\ template <typename p0##_type, typename p1##_type, typename p2##_type>\ template <typename arg_type>\ - bool name##MatcherP3<p0##_type, p1##_type, p2##_type>::\ - gmock_Impl<arg_type>::Matches(arg_type arg) const + bool name##MatcherP3<p0##_type, p1##_type, \ + p2##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ + arg_type arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const #define MATCHER_P4(name, p0, p1, p2, p3, description)\ template <typename p0##_type, typename p1##_type, typename p2##_type, \ @@ -1227,7 +1276,8 @@ ElementsAreArray(const T (&array)[N]) { const ::testing::internal::Interpolations& gmock_interp)\ : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \ gmock_interp_(gmock_interp) {}\ - virtual bool Matches(arg_type arg) const;\ + virtual bool MatchAndExplain(\ + arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ const ::testing::internal::Strings& gmock_printed_params = \ ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ @@ -1275,8 +1325,11 @@ ElementsAreArray(const T (&array)[N]) { template <typename p0##_type, typename p1##_type, typename p2##_type, \ typename p3##_type>\ template <typename arg_type>\ - bool name##MatcherP4<p0##_type, p1##_type, p2##_type, p3##_type>::\ - gmock_Impl<arg_type>::Matches(arg_type arg) const + bool name##MatcherP4<p0##_type, p1##_type, p2##_type, \ + p3##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ + arg_type arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const #define MATCHER_P5(name, p0, p1, p2, p3, p4, description)\ template <typename p0##_type, typename p1##_type, typename p2##_type, \ @@ -1291,7 +1344,8 @@ ElementsAreArray(const T (&array)[N]) { const ::testing::internal::Interpolations& gmock_interp)\ : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \ p4(gmock_p4), gmock_interp_(gmock_interp) {}\ - virtual bool Matches(arg_type arg) const;\ + virtual bool MatchAndExplain(\ + arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ const ::testing::internal::Strings& gmock_printed_params = \ ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ @@ -1342,8 +1396,11 @@ ElementsAreArray(const T (&array)[N]) { template <typename p0##_type, typename p1##_type, typename p2##_type, \ typename p3##_type, typename p4##_type>\ template <typename arg_type>\ - bool name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type>::\ - gmock_Impl<arg_type>::Matches(arg_type arg) const + bool name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \ + p4##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ + arg_type arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const #define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description)\ template <typename p0##_type, typename p1##_type, typename p2##_type, \ @@ -1358,7 +1415,8 @@ ElementsAreArray(const T (&array)[N]) { const ::testing::internal::Interpolations& gmock_interp)\ : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \ p4(gmock_p4), p5(gmock_p5), gmock_interp_(gmock_interp) {}\ - virtual bool Matches(arg_type arg) const;\ + virtual bool MatchAndExplain(\ + arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ const ::testing::internal::Strings& gmock_printed_params = \ ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ @@ -1412,8 +1470,10 @@ ElementsAreArray(const T (&array)[N]) { typename p3##_type, typename p4##_type, typename p5##_type>\ template <typename arg_type>\ bool name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type>::\ - gmock_Impl<arg_type>::Matches(arg_type arg) const + p5##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ + arg_type arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const #define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description)\ template <typename p0##_type, typename p1##_type, typename p2##_type, \ @@ -1431,7 +1491,8 @@ ElementsAreArray(const T (&array)[N]) { : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \ p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \ gmock_interp_(gmock_interp) {}\ - virtual bool Matches(arg_type arg) const;\ + virtual bool MatchAndExplain(\ + arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ const ::testing::internal::Strings& gmock_printed_params = \ ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ @@ -1493,8 +1554,10 @@ ElementsAreArray(const T (&array)[N]) { typename p6##_type>\ template <typename arg_type>\ bool name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type, p6##_type>::\ - gmock_Impl<arg_type>::Matches(arg_type arg) const + p5##_type, p6##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ + arg_type arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const #define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description)\ template <typename p0##_type, typename p1##_type, typename p2##_type, \ @@ -1512,7 +1575,8 @@ ElementsAreArray(const T (&array)[N]) { : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \ p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \ gmock_interp_(gmock_interp) {}\ - virtual bool Matches(arg_type arg) const;\ + virtual bool MatchAndExplain(\ + arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ const ::testing::internal::Strings& gmock_printed_params = \ ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ @@ -1579,8 +1643,11 @@ ElementsAreArray(const T (&array)[N]) { typename p6##_type, typename p7##_type>\ template <typename arg_type>\ bool name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type, p6##_type, p7##_type>::\ - gmock_Impl<arg_type>::Matches(arg_type arg) const + p5##_type, p6##_type, \ + p7##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ + arg_type arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const #define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description)\ template <typename p0##_type, typename p1##_type, typename p2##_type, \ @@ -1598,7 +1665,8 @@ ElementsAreArray(const T (&array)[N]) { : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \ p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \ p8(gmock_p8), gmock_interp_(gmock_interp) {}\ - virtual bool Matches(arg_type arg) const;\ + virtual bool MatchAndExplain(\ + arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ const ::testing::internal::Strings& gmock_printed_params = \ ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ @@ -1668,8 +1736,11 @@ ElementsAreArray(const T (&array)[N]) { typename p6##_type, typename p7##_type, typename p8##_type>\ template <typename arg_type>\ bool name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type, p6##_type, p7##_type, p8##_type>::\ - gmock_Impl<arg_type>::Matches(arg_type arg) const + p5##_type, p6##_type, p7##_type, \ + p8##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ + arg_type arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const #define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description)\ template <typename p0##_type, typename p1##_type, typename p2##_type, \ @@ -1689,7 +1760,8 @@ ElementsAreArray(const T (&array)[N]) { : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \ p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \ p8(gmock_p8), p9(gmock_p9), gmock_interp_(gmock_interp) {}\ - virtual bool Matches(arg_type arg) const;\ + virtual bool MatchAndExplain(\ + arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ const ::testing::internal::Strings& gmock_printed_params = \ ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ @@ -1763,7 +1835,10 @@ ElementsAreArray(const T (&array)[N]) { typename p9##_type>\ template <typename arg_type>\ bool name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>::\ - gmock_Impl<arg_type>::Matches(arg_type arg) const + p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \ + p9##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ + arg_type arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const #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 8abbc0c..fb2bc35 100644 --- a/testing/gmock/include/gmock/gmock-generated-matchers.h.pump +++ b/testing/gmock/include/gmock/gmock-generated-matchers.h.pump @@ -116,8 +116,9 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> { 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 bool MatchAndExplain(ArgsTuple args, + MatchResultListener* listener) const { + return inner_matcher_.MatchAndExplain(GetSelectedArgs(args), listener); } virtual void DescribeTo(::std::ostream* os) const { @@ -130,11 +131,6 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> { 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); @@ -301,14 +297,19 @@ $$ // show up in the generated code. // The MATCHER* family of macros can be used in a namespace scope to -// define custom matchers easily. The syntax: +// define custom matchers easily. +// +// Basic Usage +// =========== +// +// The syntax // // MATCHER(name, description_string) { statements; } // -// will define a matcher with the given name that executes the -// statements, which must return a bool to indicate if the match -// succeeds. Inside the statements, you can refer to the value being -// matched by 'arg', and refer to its type by 'arg_type'. +// defines a matcher with the given name that executes the statements, +// which must return a bool to indicate if the match succeeds. Inside +// the statements, you can refer to the value being matched by 'arg', +// and refer to its type by 'arg_type'. // // The description string documents what the matcher does, and is used // to generate the failure message when the match fails. Since a @@ -341,6 +342,9 @@ $$ // show up in the generated code. // where the description "is even" is automatically calculated from the // matcher name IsEven. // +// Argument Type +// ============= +// // Note that the type of the value being matched (arg_type) is // determined by the context in which you use the matcher and is // supplied to you by the compiler, so you don't need to worry about @@ -351,6 +355,9 @@ $$ // show up in the generated code. // takes an int, 'arg_type' will be int; if it takes an unsigned long, // 'arg_type' will be unsigned long; and so on. // +// Parameterizing Matchers +// ======================= +// // Sometimes you'll want to parameterize the matcher. For that you // can use another macro: // @@ -381,6 +388,9 @@ $$ // show up in the generated code. // We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to // support multi-parameter matchers. // +// Describing Parameterized Matchers +// ================================= +// // When defining a parameterized matcher, you can use Python-style // interpolations in the description string to refer to the parameter // values. We support the following syntax currently: @@ -413,6 +423,9 @@ $$ // show up in the generated code. // // Expected: in closed range (4, 6) // +// Types of Matcher Parameters +// =========================== +// // For the purpose of typing, you can view // // MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } @@ -440,23 +453,44 @@ $$ // show up in the generated code. // matcher you will see the value of the referenced object but not its // address. // +// Explaining Match Results +// ======================== +// +// Sometimes the matcher description alone isn't enough to explain why +// the match has failed or succeeded. For example, when expecting a +// long string, it can be very helpful to also print the diff between +// the expected string and the actual one. To achieve that, you can +// optionally stream additional information to a special variable +// named result_listener, whose type is a pointer to class +// MatchResultListener: +// +// MATCHER_P(EqualsLongString, str, "") { +// if (arg == str) return true; +// +// *result_listener << "the difference: " +/// << DiffStrings(str, arg); +// return false; +// } +// +// Overloading Matchers +// ==================== +// // You can overload matchers with different numbers of parameters: // // MATCHER_P(Blah, a, description_string1) { ... } // MATCHER_P2(Blah, a, b, description_string2) { ... } // -// While it's tempting to always use the MATCHER* macros when defining -// a new matcher, you should also consider implementing -// MatcherInterface or using MakePolymorphicMatcher() instead, -// especially if you need to use the matcher a lot. While these -// approaches require more work, they give you more control on the -// types of the value being matched and the matcher parameters, which -// in general leads to better compiler error messages that pay off in -// the long run. They also allow overloading matchers based on -// parameter types (as opposed to just based on the number of -// parameters). +// Caveats +// ======= // -// CAVEAT: +// When defining a new matcher, you should also consider implementing +// MatcherInterface or using MakePolymorphicMatcher(). These +// approaches require more work than the MATCHER* macros, but also +// give you more control on the types of the value being matched and +// the matcher parameters, which may leads to better compiler error +// messages when the matcher is used wrong. They also allow +// overloading matchers based on parameter types (as opposed to just +// based on the number of parameters). // // MATCHER*() can only be used in a namespace scope. The reason is // that C++ doesn't yet allow function-local types to be used to @@ -464,7 +498,8 @@ $$ // show up in the generated code. // Once that's done, we'll consider supporting using MATCHER*() inside // a function. // -// MORE INFORMATION: +// More Information +// ================ // // To learn more about using these macros, please search for 'MATCHER' // on http://code.google.com/p/googlemock/wiki/CookBook. @@ -510,7 +545,8 @@ $var param_field_decls2 = [[$for j public:\ [[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\ $impl_inits {}\ - virtual bool Matches(arg_type arg) const;\ + virtual bool MatchAndExplain(\ + arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ const ::testing::internal::Strings& gmock_printed_params = \ ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ @@ -540,8 +576,10 @@ $var param_field_decls2 = [[$for j return $class_name$param_types($params);\ }\$template template <typename arg_type>\ - bool $class_name$param_types::\ - gmock_Impl<arg_type>::Matches(arg_type arg) const + bool $class_name$param_types::gmock_Impl<arg_type>::MatchAndExplain(\ + arg_type arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const ]] diff --git a/testing/gmock/include/gmock/gmock-matchers.h b/testing/gmock/include/gmock/gmock-matchers.h index 5f5a29f..9a1bab2 100644 --- a/testing/gmock/include/gmock/gmock-matchers.h +++ b/testing/gmock/include/gmock/gmock-matchers.h @@ -64,16 +64,74 @@ namespace testing { // ownership management as Matcher objects can now be copied like // plain values. +// MatchResultListener is an abstract class. Its << operator can be +// used by a matcher to explain why a value matches or doesn't match. +// +// TODO(wan@google.com): add method +// bool InterestedInWhy(bool result) const; +// to indicate whether the listener is interested in why the match +// result is 'result'. +class MatchResultListener { + public: + // Creates a listener object with the given underlying ostream. The + // listener does not own the ostream. + explicit MatchResultListener(::std::ostream* os) : stream_(os) {} + virtual ~MatchResultListener() = 0; // Makes this class abstract. + + // Streams x to the underlying ostream; does nothing if the ostream + // is NULL. + template <typename T> + MatchResultListener& operator<<(const T& x) { + if (stream_ != NULL) + *stream_ << x; + return *this; + } + + // Returns the underlying ostream. + ::std::ostream* stream() { return stream_; } + + // Returns true iff the listener is interested in an explanation of + // the match result. A matcher's MatchAndExplain() method can use + // this information to avoid generating the explanation when no one + // intends to hear it. + bool IsInterested() const { return stream_ != NULL; } + + private: + ::std::ostream* const stream_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener); +}; + +inline MatchResultListener::~MatchResultListener() { +} + // The implementation of a matcher. template <typename T> class MatcherInterface { public: virtual ~MatcherInterface() {} - // Returns true iff the matcher matches x. - virtual bool Matches(T x) const = 0; - - // Describes this matcher to an ostream. + // Returns true iff the matcher matches x; also explains the match + // result to 'listener', in the form of a non-restrictive relative + // clause ("which ...", "whose ...", etc) that describes x. For + // example, the MatchAndExplain() method of the Pointee(...) matcher + // should generate an explanation like "which points to ...". + // + // You should override this method when defining a new matcher. + // + // It's the responsibility of the caller (Google Mock) to guarantee + // that 'listener' is not NULL. This helps to simplify a matcher's + // implementation when it doesn't care about the performance, as it + // can talk to 'listener' without checking its validity first. + // However, in order to implement dummy listeners efficiently, + // listener->stream() may be NULL. + virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0; + + // Describes this matcher to an ostream. The function should print + // a verb phrase that describes the property a value matching this + // matcher should have. The subject of the verb phrase is the value + // being matched. For example, the DescribeTo() method of the Gt(7) + // matcher prints "is greater than 7". virtual void DescribeTo(::std::ostream* os) const = 0; // Describes the negation of this matcher to an ostream. For @@ -87,27 +145,62 @@ class MatcherInterface { DescribeTo(os); *os << ")"; } - - // Explains why x matches, or doesn't match, the matcher. Override - // this to provide any additional information that helps a user - // understand the match result. - virtual void ExplainMatchResultTo(T /* x */, ::std::ostream* /* os */) const { - // By default, nothing more needs to be explained, as Google Mock - // has already printed the value of x when this function is - // called. - } }; namespace internal { +// A match result listener that ignores the explanation. +class DummyMatchResultListener : public MatchResultListener { + public: + DummyMatchResultListener() : MatchResultListener(NULL) {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener); +}; + +// A match result listener that forwards the explanation to a given +// ostream. The difference between this and MatchResultListener is +// that the former is concrete. +class StreamMatchResultListener : public MatchResultListener { + public: + explicit StreamMatchResultListener(::std::ostream* os) + : MatchResultListener(os) {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener); +}; + +// A match result listener that stores the explanation in a string. +class StringMatchResultListener : public MatchResultListener { + public: + StringMatchResultListener() : MatchResultListener(&ss_) {} + + // Returns the explanation heard so far. + internal::string str() const { return ss_.str(); } + + private: + ::std::stringstream ss_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(StringMatchResultListener); +}; + // An internal class for implementing Matcher<T>, which will derive // from it. We put functionalities common to all Matcher<T> // specializations here to avoid code duplication. template <typename T> class MatcherBase { public: + // Returns true iff the matcher matches x; also explains the match + // result to 'listener'. + bool MatchAndExplain(T x, MatchResultListener* listener) const { + return impl_->MatchAndExplain(x, listener); + } + // Returns true iff this matcher matches x. - bool Matches(T x) const { return impl_->Matches(x); } + bool Matches(T x) const { + DummyMatchResultListener dummy; + return MatchAndExplain(x, &dummy); + } // Describes this matcher to an ostream. void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); } @@ -119,7 +212,8 @@ class MatcherBase { // Explains why x matches, or doesn't match, the matcher. void ExplainMatchResultTo(T x, ::std::ostream* os) const { - impl_->ExplainMatchResultTo(x, os); + StreamMatchResultListener listener(os); + MatchAndExplain(x, &listener); } protected: @@ -146,16 +240,6 @@ class MatcherBase { ::testing::internal::linked_ptr<const MatcherInterface<T> > impl_; }; -// The default implementation of ExplainMatchResultTo() for -// polymorphic matchers. -template <typename PolymorphicMatcherImpl, typename T> -inline void ExplainMatchResultTo(const PolymorphicMatcherImpl& /* impl */, - const T& /* x */, - ::std::ostream* /* os */) { - // By default, nothing more needs to be said, as Google Mock already - // prints the value of x elsewhere. -} - } // namespace internal // A Matcher<T> is a copyable and IMMUTABLE (except by assignment) @@ -220,19 +304,14 @@ class Matcher<internal::string> // polymorphic matcher (i.e. a matcher that can match values of more // than one type, e.g. Eq(n) and NotNull()). // -// To define a polymorphic matcher, a user first provides a Impl class -// that has a Matches() method, a DescribeTo() method, and a -// DescribeNegationTo() method. The Matches() method is usually a -// method template (such that it works with multiple types). Then the -// user creates the polymorphic matcher using -// MakePolymorphicMatcher(). To provide additional explanation to the -// match result, define a FREE function (or function template) +// To define a polymorphic matcher, a user should provide an Impl +// class that has a DescribeTo() method and a DescribeNegationTo() +// method, and define a member function (or member function template) // -// void ExplainMatchResultTo(const Impl& matcher, const Value& value, -// ::std::ostream* os); +// bool MatchAndExplain(const Value& value, +// MatchResultListener* listener) const; // -// in the SAME NAME SPACE where Impl is defined. See the definition -// of NotNull() for a complete example. +// See the definition of NotNull() for a complete example. template <class Impl> class PolymorphicMatcher { public: @@ -257,8 +336,6 @@ class PolymorphicMatcher { public: explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {} - virtual bool Matches(T x) const { return impl_.Matches(x); } - virtual void DescribeTo(::std::ostream* os) const { impl_.DescribeTo(os); } @@ -267,22 +344,8 @@ class PolymorphicMatcher { impl_.DescribeNegationTo(os); } - virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const { - using ::testing::internal::ExplainMatchResultTo; - - // C++ uses Argument-Dependent Look-up (aka Koenig Look-up) to - // resolve the call to ExplainMatchResultTo() here. This - // means that if there's a ExplainMatchResultTo() function - // defined in the name space where class Impl is defined, it - // will be picked by the compiler as the better match. - // Otherwise the default implementation of it in - // ::testing::internal will be picked. - // - // This look-up rule lets a writer of a polymorphic matcher - // customize the behavior of ExplainMatchResultTo() when he - // cares to. Nothing needs to be done by the writer if he - // doesn't need to customize it. - ExplainMatchResultTo(impl_, x, os); + virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { + return impl_.MatchAndExplain(x, listener); } private: @@ -390,16 +453,44 @@ Matcher<T> A(); // and MUST NOT BE USED IN USER CODE!!! namespace internal { -// Appends the explanation on the result of matcher.Matches(value) to -// os iff the explanation is not empty. -template <typename T> -void ExplainMatchResultAsNeededTo(const Matcher<T>& matcher, T value, - ::std::ostream* os) { - ::std::stringstream reason; - matcher.ExplainMatchResultTo(value, &reason); - const internal::string s = reason.str(); - if (s != "") { - *os << " (" << s << ")"; +// If the explanation is not empty, prints it to the listener. +// 'listener' must not be NULL. +inline void PrintIfNotEmpty( + const internal::string& explanation, MatchResultListener* listener) { + if (explanation != "") { + *listener << ", " << explanation; + } +} + +// Matches the value against the given matcher, prints the value and explains +// the match result to the listener. Returns the match result. +// 'listener' must not be NULL. +// Value cannot be passed by const reference, because some matchers take a +// non-const argument. +template <typename Value, typename T> +bool MatchPrintAndExplain(Value& value, const Matcher<T>& matcher, + MatchResultListener* listener) { + if (!listener->IsInterested()) { + // If the listener is not interested, we do not need to construct the + // inner explanation. + return matcher.Matches(value); + } + + StringMatchResultListener inner_listener; + const bool match = matcher.MatchAndExplain(value, &inner_listener); + + UniversalPrint(value, listener->stream()); + PrintIfNotEmpty(inner_listener.str(), listener); + + return match; +} + +// If the given string is not empty and os is not NULL, wraps the +// string inside a pair of parentheses and streams the result to os. +inline void StreamInParensAsNeeded(const internal::string& str, + ::std::ostream* os) { + if (!str.empty() && os != NULL) { + *os << " (" << str << ")"; } } @@ -439,7 +530,8 @@ class TuplePrefix { get<N - 1>(matchers); typedef typename tuple_element<N - 1, ValueTuple>::type Value; Value value = get<N - 1>(values); - if (!matcher.Matches(value)) { + StringMatchResultListener listener; + if (!matcher.MatchAndExplain(value, &listener)) { // TODO(wan): include in the message the name of the parameter // as used in MOCK_METHOD*() when possible. *os << " Expected arg #" << N - 1 << ": "; @@ -448,11 +540,12 @@ class TuplePrefix { // We remove the reference in type Value to prevent the // universal printer from printing the address of value, which // isn't interesting to the user most of the time. The - // matcher's ExplainMatchResultTo() method handles the case when + // matcher's MatchAndExplain() method handles the case when // the address is interesting. internal::UniversalPrinter<GMOCK_REMOVE_REFERENCE_(Value)>:: Print(value, os); - ExplainMatchResultAsNeededTo<Value>(matcher, value, os); + + StreamInParensAsNeeded(listener.str(), os); *os << "\n"; } } @@ -537,8 +630,8 @@ class MatcherCastImpl<T, Matcher<U> > { : source_matcher_(source_matcher) {} // We delegate the matching logic to the source matcher. - virtual bool Matches(T x) const { - return source_matcher_.Matches(static_cast<U>(x)); + virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { + return source_matcher_.MatchAndExplain(static_cast<U>(x), listener); } virtual void DescribeTo(::std::ostream* os) const { @@ -549,10 +642,6 @@ class MatcherCastImpl<T, Matcher<U> > { source_matcher_.DescribeNegationTo(os); } - virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const { - source_matcher_.ExplainMatchResultTo(static_cast<U>(x), os); - } - private: const Matcher<U> source_matcher_; @@ -572,7 +661,8 @@ class MatcherCastImpl<T, Matcher<T> > { template <typename T> class AnyMatcherImpl : public MatcherInterface<T> { public: - virtual bool Matches(T /* x */) const { return true; } + virtual bool MatchAndExplain( + T /* x */, MatchResultListener* /* listener */) const { return true; } virtual void DescribeTo(::std::ostream* os) const { *os << "is anything"; } virtual void DescribeNegationTo(::std::ostream* os) const { // This is mostly for completeness' safe, as it's not very useful @@ -618,7 +708,10 @@ class AnythingMatcher { class Impl : public MatcherInterface<Lhs> { \ public: \ explicit Impl(const Rhs& rhs) : rhs_(rhs) {} \ - virtual bool Matches(Lhs lhs) const { return lhs op rhs_; } \ + virtual bool MatchAndExplain(\ + Lhs lhs, MatchResultListener* /* listener */) const { \ + return lhs op rhs_; \ + } \ virtual void DescribeTo(::std::ostream* os) const { \ *os << "is " relation " "; \ UniversalPrinter<Rhs>::Print(rhs_, os); \ @@ -651,7 +744,10 @@ GMOCK_IMPLEMENT_COMPARISON_MATCHER_(Ne, !=, "not equal to"); class IsNullMatcher { public: template <typename Pointer> - bool Matches(const Pointer& p) const { return GetRawPointer(p) == NULL; } + bool MatchAndExplain(const Pointer& p, + MatchResultListener* /* listener */) const { + return GetRawPointer(p) == NULL; + } void DescribeTo(::std::ostream* os) const { *os << "is NULL"; } void DescribeNegationTo(::std::ostream* os) const { @@ -664,7 +760,10 @@ class IsNullMatcher { class NotNullMatcher { public: template <typename Pointer> - bool Matches(const Pointer& p) const { return GetRawPointer(p) != NULL; } + bool MatchAndExplain(const Pointer& p, + MatchResultListener* /* listener */) const { + return GetRawPointer(p) != NULL; + } void DescribeTo(::std::ostream* os) const { *os << "is not NULL"; } void DescribeNegationTo(::std::ostream* os) const { @@ -717,9 +816,13 @@ class RefMatcher<T&> { public: explicit Impl(Super& x) : object_(x) {} // NOLINT - // Matches() takes a Super& (as opposed to const Super&) in - // order to match the interface MatcherInterface<Super&>. - virtual bool Matches(Super& x) const { return &x == &object_; } // NOLINT + // MatchAndExplain() takes a Super& (as opposed to const Super&) + // in order to match the interface MatcherInterface<Super&>. + virtual bool MatchAndExplain( + Super& x, MatchResultListener* listener) const { + *listener << "is located @" << static_cast<const void*>(&x); + return &x == &object_; + } virtual void DescribeTo(::std::ostream* os) const { *os << "references the variable "; @@ -731,11 +834,6 @@ class RefMatcher<T&> { UniversalPrinter<Super&>::Print(object_, os); } - virtual void ExplainMatchResultTo(Super& x, // NOLINT - ::std::ostream* os) const { - *os << "is located @" << static_cast<const void*>(&x); - } - private: const Super& object_; @@ -794,14 +892,16 @@ class StrEqualityMatcher { // When expect_eq_ is true, returns true iff s is equal to string_; // otherwise returns true iff s is not equal to string_. - bool Matches(ConstCharPointer s) const { + bool MatchAndExplain(ConstCharPointer s, + MatchResultListener* listener) const { if (s == NULL) { return !expect_eq_; } - return Matches(StringType(s)); + return MatchAndExplain(StringType(s), listener); } - bool Matches(const StringType& s) const { + bool MatchAndExplain(const StringType& s, + MatchResultListener* /* listener */) const { const bool eq = case_sensitive_ ? s == string_ : CaseInsensitiveStringEquals(s, string_); return expect_eq_ == eq; @@ -849,11 +949,13 @@ class HasSubstrMatcher { // These overloaded methods allow HasSubstr(substring) to be used as a // Matcher<T> as long as T can be converted to string. Returns true // iff s contains substring_ as a substring. - bool Matches(ConstCharPointer s) const { - return s != NULL && Matches(StringType(s)); + bool MatchAndExplain(ConstCharPointer s, + MatchResultListener* listener) const { + return s != NULL && MatchAndExplain(StringType(s), listener); } - bool Matches(const StringType& s) const { + bool MatchAndExplain(const StringType& s, + MatchResultListener* /* listener */) const { return s.find(substring_) != StringType::npos; } @@ -888,11 +990,13 @@ class StartsWithMatcher { // These overloaded methods allow StartsWith(prefix) to be used as a // Matcher<T> as long as T can be converted to string. Returns true // iff s starts with prefix_. - bool Matches(ConstCharPointer s) const { - return s != NULL && Matches(StringType(s)); + bool MatchAndExplain(ConstCharPointer s, + MatchResultListener* listener) const { + return s != NULL && MatchAndExplain(StringType(s), listener); } - bool Matches(const StringType& s) const { + bool MatchAndExplain(const StringType& s, + MatchResultListener* /* listener */) const { return s.length() >= prefix_.length() && s.substr(0, prefix_.length()) == prefix_; } @@ -926,11 +1030,13 @@ class EndsWithMatcher { // These overloaded methods allow EndsWith(suffix) to be used as a // Matcher<T> as long as T can be converted to string. Returns true // iff s ends with suffix_. - bool Matches(ConstCharPointer s) const { - return s != NULL && Matches(StringType(s)); + bool MatchAndExplain(ConstCharPointer s, + MatchResultListener* listener) const { + return s != NULL && MatchAndExplain(StringType(s), listener); } - bool Matches(const StringType& s) const { + bool MatchAndExplain(const StringType& s, + MatchResultListener* /* listener */) const { return s.length() >= suffix_.length() && s.substr(s.length() - suffix_.length()) == suffix_; } @@ -951,8 +1057,6 @@ class EndsWithMatcher { GTEST_DISALLOW_ASSIGN_(EndsWithMatcher); }; -#if GMOCK_HAS_REGEX - // Implements polymorphic matchers MatchesRegex(regex) and // ContainsRegex(regex), which can be used as a Matcher<T> as long as // T can be converted to a string. @@ -965,11 +1069,13 @@ class MatchesRegexMatcher { // a Matcher<T> as long as T can be converted to string. Returns // true iff s matches regular expression regex. When full_match_ is // true, a full match is done; otherwise a partial match is done. - bool Matches(const char* s) const { - return s != NULL && Matches(internal::string(s)); + bool MatchAndExplain(const char* s, + MatchResultListener* listener) const { + return s != NULL && MatchAndExplain(internal::string(s), listener); } - bool Matches(const internal::string& s) const { + bool MatchAndExplain(const internal::string& s, + MatchResultListener* /* listener */) const { return full_match_ ? RE::FullMatch(s, *regex_) : RE::PartialMatch(s, *regex_); } @@ -993,8 +1099,6 @@ class MatchesRegexMatcher { GTEST_DISALLOW_ASSIGN_(MatchesRegexMatcher); }; -#endif // GMOCK_HAS_REGEX - // Implements a matcher that compares the two fields of a 2-tuple // using one of the ==, <=, <, etc, operators. The two fields being // compared don't have to have the same type. @@ -1017,7 +1121,9 @@ class MatchesRegexMatcher { template <typename T1, typename T2> \ class Impl : public MatcherInterface<const ::std::tr1::tuple<T1, T2>&> { \ public: \ - virtual bool Matches(const ::std::tr1::tuple<T1, T2>& args) const { \ + virtual bool MatchAndExplain( \ + const ::std::tr1::tuple<T1, T2>& args, \ + MatchResultListener* /* listener */) const { \ return ::std::tr1::get<0>(args) op ::std::tr1::get<1>(args); \ } \ virtual void DescribeTo(::std::ostream* os) const { \ @@ -1049,8 +1155,8 @@ class NotMatcherImpl : public MatcherInterface<T> { explicit NotMatcherImpl(const Matcher<T>& matcher) : matcher_(matcher) {} - virtual bool Matches(T x) const { - return !matcher_.Matches(x); + virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { + return !matcher_.MatchAndExplain(x, listener); } virtual void DescribeTo(::std::ostream* os) const { @@ -1061,10 +1167,6 @@ class NotMatcherImpl : public MatcherInterface<T> { matcher_.DescribeTo(os); } - virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const { - matcher_.ExplainMatchResultTo(x, os); - } - private: const Matcher<T> matcher_; @@ -1101,10 +1203,6 @@ class BothOfMatcherImpl : public MatcherInterface<T> { BothOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2) : matcher1_(matcher1), matcher2_(matcher2) {} - virtual bool Matches(T x) const { - return matcher1_.Matches(x) && matcher2_.Matches(x); - } - virtual void DescribeTo(::std::ostream* os) const { *os << "("; matcher1_.DescribeTo(os); @@ -1118,35 +1216,34 @@ class BothOfMatcherImpl : public MatcherInterface<T> { DescribeTo(os); } - virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const { - if (Matches(x)) { - // When both matcher1_ and matcher2_ match x, we need to - // explain why *both* of them match. - ::std::stringstream ss1; - matcher1_.ExplainMatchResultTo(x, &ss1); - const internal::string s1 = ss1.str(); + virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { + // If either matcher1_ or matcher2_ doesn't match x, we only need + // to explain why one of them fails. + StringMatchResultListener listener1; + if (!matcher1_.MatchAndExplain(x, &listener1)) { + *listener << listener1.str(); + return false; + } - ::std::stringstream ss2; - matcher2_.ExplainMatchResultTo(x, &ss2); - const internal::string s2 = ss2.str(); + StringMatchResultListener listener2; + if (!matcher2_.MatchAndExplain(x, &listener2)) { + *listener << listener2.str(); + return false; + } - if (s1 == "") { - *os << s2; - } else { - *os << s1; - if (s2 != "") { - *os << "; " << s2; - } - } + // Otherwise we need to explain why *both* of them match. + const internal::string s1 = listener1.str(); + const internal::string s2 = listener2.str(); + + if (s1 == "") { + *listener << s2; } else { - // Otherwise we only need to explain why *one* of them fails - // to match. - if (!matcher1_.Matches(x)) { - matcher1_.ExplainMatchResultTo(x, os); - } else { - matcher2_.ExplainMatchResultTo(x, os); + *listener << s1; + if (s2 != "") { + *listener << "; " << s2; } } + return true; } private: @@ -1190,10 +1287,6 @@ class EitherOfMatcherImpl : public MatcherInterface<T> { EitherOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2) : matcher1_(matcher1), matcher2_(matcher2) {} - virtual bool Matches(T x) const { - return matcher1_.Matches(x) || matcher2_.Matches(x); - } - virtual void DescribeTo(::std::ostream* os) const { *os << "("; matcher1_.DescribeTo(os); @@ -1207,34 +1300,34 @@ class EitherOfMatcherImpl : public MatcherInterface<T> { DescribeTo(os); } - virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const { - if (Matches(x)) { - // If either matcher1_ or matcher2_ matches x, we just need - // to explain why *one* of them matches. - if (matcher1_.Matches(x)) { - matcher1_.ExplainMatchResultTo(x, os); - } else { - matcher2_.ExplainMatchResultTo(x, os); - } - } else { - // Otherwise we need to explain why *neither* matches. - ::std::stringstream ss1; - matcher1_.ExplainMatchResultTo(x, &ss1); - const internal::string s1 = ss1.str(); + virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { + // If either matcher1_ or matcher2_ matches x, we just need to + // explain why *one* of them matches. + StringMatchResultListener listener1; + if (matcher1_.MatchAndExplain(x, &listener1)) { + *listener << listener1.str(); + return true; + } - ::std::stringstream ss2; - matcher2_.ExplainMatchResultTo(x, &ss2); - const internal::string s2 = ss2.str(); + StringMatchResultListener listener2; + if (matcher2_.MatchAndExplain(x, &listener2)) { + *listener << listener2.str(); + return true; + } - if (s1 == "") { - *os << s2; - } else { - *os << s1; - if (s2 != "") { - *os << "; " << s2; - } + // Otherwise we need to explain why *both* of them fail. + const internal::string s1 = listener1.str(); + const internal::string s2 = listener2.str(); + + if (s1 == "") { + *listener << s2; + } else { + *listener << s1; + if (s2 != "") { + *listener << "; " << s2; } } + return false; } private: @@ -1281,7 +1374,8 @@ class TrulyMatcher { // argument is passed by reference as the predicate may be // interested in the address of the argument. template <typename T> - bool Matches(T& x) const { // NOLINT + bool MatchAndExplain(T& x, // NOLINT + MatchResultListener* /* listener */) const { #if GTEST_OS_WINDOWS // MSVC warns about converting a value into bool (warning 4800). #pragma warning(push) // Saves the current warning state. @@ -1367,7 +1461,8 @@ class PredicateFormatterFromMatcher { // Matcher<const T&>(matcher_), as the latter won't compile when // matcher_ has type Matcher<T> (e.g. An<int>()). const Matcher<const T&> matcher = MatcherCast<const T&>(matcher_); - if (matcher.Matches(x)) { + StringMatchResultListener listener; + if (matcher.MatchAndExplain(x, &listener)) { return AssertionSuccess(); } else { ::std::stringstream ss; @@ -1376,7 +1471,7 @@ class PredicateFormatterFromMatcher { matcher.DescribeTo(&ss); ss << "\n Actual: "; UniversalPrinter<T>::Print(x, &ss); - ExplainMatchResultAsNeededTo<const T&>(matcher, x, &ss); + StreamInParensAsNeeded(listener.str(), &ss); return AssertionFailure(Message() << ss.str()); } } @@ -1417,7 +1512,8 @@ class FloatingEqMatcher { Impl(FloatType rhs, bool nan_eq_nan) : rhs_(rhs), nan_eq_nan_(nan_eq_nan) {} - virtual bool Matches(T value) const { + virtual bool MatchAndExplain(T value, + MatchResultListener* /* listener */) const { const FloatingPoint<FloatType> lhs(value), rhs(rhs_); // Compares NaNs first, if nan_eq_nan_ is true. @@ -1525,10 +1621,6 @@ class PointeeMatcher { explicit Impl(const InnerMatcher& matcher) : matcher_(MatcherCast<const Pointee&>(matcher)) {} - virtual bool Matches(Pointer p) const { - return GetRawPointer(p) != NULL && matcher_.Matches(*p); - } - virtual void DescribeTo(::std::ostream* os) const { *os << "points to a value that "; matcher_.DescribeTo(os); @@ -1539,17 +1631,13 @@ class PointeeMatcher { matcher_.DescribeTo(os); } - virtual void ExplainMatchResultTo(Pointer pointer, - ::std::ostream* os) const { + virtual bool MatchAndExplain(Pointer pointer, + MatchResultListener* listener) const { if (GetRawPointer(pointer) == NULL) - return; + return false; - ::std::stringstream ss; - matcher_.ExplainMatchResultTo(*pointer, &ss); - const internal::string s = ss.str(); - if (s != "") { - *os << "points to a value that " << s; - } + *listener << "which points to "; + return MatchPrintAndExplain(*pointer, matcher_, listener); } private: @@ -1572,64 +1660,52 @@ class FieldMatcher { const Matcher<const FieldType&>& matcher) : field_(field), matcher_(matcher) {} - // Returns true iff the inner matcher matches obj.field. - bool Matches(const Class& obj) const { - return matcher_.Matches(obj.*field_); - } - - // Returns true iff the inner matcher matches obj->field. - bool Matches(const Class* p) const { - return (p != NULL) && matcher_.Matches(p->*field_); - } - void DescribeTo(::std::ostream* os) const { - *os << "the given field "; + *os << "is an object whose given field "; matcher_.DescribeTo(os); } void DescribeNegationTo(::std::ostream* os) const { - *os << "the given field "; + *os << "is an object whose given field "; matcher_.DescribeNegationTo(os); } - // The first argument of ExplainMatchResultTo() is needed to help + template <typename T> + bool MatchAndExplain(const T& value, MatchResultListener* listener) const { + return MatchAndExplainImpl( + typename ::testing::internal:: + is_pointer<GMOCK_REMOVE_CONST_(T)>::type(), + value, listener); + } + + private: + // The first argument of MatchAndExplainImpl() is needed to help // Symbian's C++ compiler choose which overload to use. Its type is // true_type iff the Field() matcher is used to match a pointer. - void ExplainMatchResultTo(false_type /* is_not_pointer */, const Class& obj, - ::std::ostream* os) const { - ::std::stringstream ss; - matcher_.ExplainMatchResultTo(obj.*field_, &ss); - const internal::string s = ss.str(); - if (s != "") { - *os << "the given field " << s; - } + bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj, + MatchResultListener* listener) const { + *listener << "whose given field is "; + return MatchPrintAndExplain(obj.*field_, matcher_, listener); } - void ExplainMatchResultTo(true_type /* is_pointer */, const Class* p, - ::std::ostream* os) const { - if (p != NULL) { - // Since *p has a field, it must be a class/struct/union type - // and thus cannot be a pointer. Therefore we pass false_type() - // as the first argument. - ExplainMatchResultTo(false_type(), *p, os); - } + bool MatchAndExplainImpl(true_type /* is_pointer */, const Class* p, + MatchResultListener* listener) const { + if (p == NULL) + return false; + + *listener << "which points to an object "; + // Since *p has a field, it must be a class/struct/union type and + // thus cannot be a pointer. Therefore we pass false_type() as + // the first argument. + return MatchAndExplainImpl(false_type(), *p, listener); } - private: const FieldType Class::*field_; const Matcher<const FieldType&> matcher_; GTEST_DISALLOW_ASSIGN_(FieldMatcher); }; -// Explains the result of matching an object or pointer against a field matcher. -template <typename Class, typename FieldType, typename T> -void ExplainMatchResultTo(const FieldMatcher<Class, FieldType>& matcher, - const T& value, ::std::ostream* os) { - matcher.ExplainMatchResultTo( - typename ::testing::internal::is_pointer<T>::type(), value, os); -} - // Implements the Property() matcher for matching a property // (i.e. return value of a getter method) of an object. template <typename Class, typename PropertyType> @@ -1645,65 +1721,55 @@ class PropertyMatcher { const Matcher<RefToConstProperty>& matcher) : property_(property), matcher_(matcher) {} - // Returns true iff obj.property() matches the inner matcher. - bool Matches(const Class& obj) const { - return matcher_.Matches((obj.*property_)()); - } - - // Returns true iff p->property() matches the inner matcher. - bool Matches(const Class* p) const { - return (p != NULL) && matcher_.Matches((p->*property_)()); - } - void DescribeTo(::std::ostream* os) const { - *os << "the given property "; + *os << "is an object whose given property "; matcher_.DescribeTo(os); } void DescribeNegationTo(::std::ostream* os) const { - *os << "the given property "; + *os << "is an object whose given property "; matcher_.DescribeNegationTo(os); } - // The first argument of ExplainMatchResultTo() is needed to help + template <typename T> + bool MatchAndExplain(const T&value, MatchResultListener* listener) const { + return MatchAndExplainImpl( + typename ::testing::internal:: + is_pointer<GMOCK_REMOVE_CONST_(T)>::type(), + value, listener); + } + + private: + // The first argument of MatchAndExplainImpl() is needed to help // Symbian's C++ compiler choose which overload to use. Its type is // true_type iff the Property() matcher is used to match a pointer. - void ExplainMatchResultTo(false_type /* is_not_pointer */, const Class& obj, - ::std::ostream* os) const { - ::std::stringstream ss; - matcher_.ExplainMatchResultTo((obj.*property_)(), &ss); - const internal::string s = ss.str(); - if (s != "") { - *os << "the given property " << s; - } - } + bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj, + MatchResultListener* listener) const { + *listener << "whose given property is "; + // Cannot pass the return value (for example, int) to MatchPrintAndExplain, + // which takes a non-const reference as argument. + RefToConstProperty result = (obj.*property_)(); + return MatchPrintAndExplain(result, matcher_, listener); + } + + bool MatchAndExplainImpl(true_type /* is_pointer */, const Class* p, + MatchResultListener* listener) const { + if (p == NULL) + return false; - void ExplainMatchResultTo(true_type /* is_pointer */, const Class* p, - ::std::ostream* os) const { - if (p != NULL) { - // Since *p has a property method, it must be a - // class/struct/union type and thus cannot be a pointer. - // Therefore we pass false_type() as the first argument. - ExplainMatchResultTo(false_type(), *p, os); - } + *listener << "which points to an object "; + // Since *p has a property method, it must be a class/struct/union + // type and thus cannot be a pointer. Therefore we pass + // false_type() as the first argument. + return MatchAndExplainImpl(false_type(), *p, listener); } - private: PropertyType (Class::*property_)() const; const Matcher<RefToConstProperty> matcher_; GTEST_DISALLOW_ASSIGN_(PropertyMatcher); }; -// Explains the result of matching an object or pointer against a -// property matcher. -template <typename Class, typename PropertyType, typename T> -void ExplainMatchResultTo(const PropertyMatcher<Class, PropertyType>& matcher, - const T& value, ::std::ostream* os) { - matcher.ExplainMatchResultTo( - typename ::testing::internal::is_pointer<T>::type(), value, os); -} - // Type traits specifying various features of different functors for ResultOf. // The default template specifies features for functor objects. // Functor classes have to typedef argument_type and result_type @@ -1759,32 +1825,24 @@ class ResultOfMatcher { public: Impl(CallableStorageType callable, const Matcher<ResultType>& matcher) : callable_(callable), matcher_(matcher) {} - // Returns true iff callable_(obj) matches the inner matcher. - // The calling syntax is different for different types of callables - // so we abstract it in CallableTraits<Callable>::Invoke(). - virtual bool Matches(T obj) const { - return matcher_.Matches( - CallableTraits<Callable>::template Invoke<T>(callable_, obj)); - } virtual void DescribeTo(::std::ostream* os) const { - *os << "result of the given callable "; + *os << "is mapped by the given callable to a value that "; matcher_.DescribeTo(os); } virtual void DescribeNegationTo(::std::ostream* os) const { - *os << "result of the given callable "; + *os << "is mapped by the given callable to a value that "; matcher_.DescribeNegationTo(os); } - virtual void ExplainMatchResultTo(T obj, ::std::ostream* os) const { - ::std::stringstream ss; - matcher_.ExplainMatchResultTo( - CallableTraits<Callable>::template Invoke<T>(callable_, obj), - &ss); - const internal::string s = ss.str(); - if (s != "") - *os << "result of the given callable " << s; + virtual bool MatchAndExplain(T obj, MatchResultListener* listener) const { + *listener << "which is mapped by the given callable to "; + // Cannot pass the return value (for example, int) to + // MatchPrintAndExplain, which takes a non-const reference as argument. + ResultType result = + CallableTraits<Callable>::template Invoke<T>(callable_, obj); + return MatchPrintAndExplain(result, matcher_, listener); } private: @@ -1805,13 +1863,6 @@ class ResultOfMatcher { GTEST_DISALLOW_ASSIGN_(ResultOfMatcher); }; -// Explains the result of matching a value against a functor matcher. -template <typename T, typename Callable> -void ExplainMatchResultTo(const ResultOfMatcher<Callable>& matcher, - T obj, ::std::ostream* os) { - matcher.ExplainMatchResultTo(obj, os); -} - // Implements an equality matcher for any STL-style container whose elements // support ==. This matcher is like Eq(), but its failure explanations provide // more detailed information that is useful when the container is used as a set. @@ -1838,15 +1889,6 @@ class ContainerEqMatcher { 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<StlContainer>::Print(rhs_, os); @@ -1857,48 +1899,56 @@ class ContainerEqMatcher { } template <typename LhsContainer> - void ExplainMatchResultTo(const LhsContainer& lhs, - ::std::ostream* os) const { + bool MatchAndExplain(const LhsContainer& lhs, + MatchResultListener* listener) 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 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; + if (lhs_stl_container == rhs_) + return true; + + ::std::ostream* const os = listener->stream(); + if (os != NULL) { + // Something is different. Check for missing values first. + bool printed_header = false; + 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 LhsStlContainer::value_type>:: + Print(*it, os); } - UniversalPrinter<typename LhsStlContainer::value_type>::Print(*it, os); } - } - // Now check for extra values. - bool printed_header2 = false; - for (typename StlContainer::const_iterator it = rhs_.begin(); - it != rhs_.end(); ++it) { - 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; + // Now check for extra values. + bool printed_header2 = false; + for (typename StlContainer::const_iterator it = rhs_.begin(); + it != rhs_.end(); ++it) { + 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 StlContainer::value_type>::Print(*it, os); } - UniversalPrinter<typename StlContainer::value_type>::Print(*it, os); } } + + return false; } private: @@ -1907,13 +1957,6 @@ class ContainerEqMatcher { GTEST_DISALLOW_ASSIGN_(ContainerEqMatcher); }; -template <typename LhsContainer, typename Container> -void ExplainMatchResultTo(const ContainerEqMatcher<Container>& matcher, - 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> { @@ -1929,17 +1972,6 @@ class ContainsMatcherImpl : public MatcherInterface<Container> { : 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 "; @@ -1952,19 +1984,18 @@ class ContainsMatcherImpl : public MatcherInterface<Container> { inner_matcher_.DescribeTo(os); } - // Explains why 'container' matches, or doesn't match, this matcher. - virtual void ExplainMatchResultTo(Container container, - ::std::ostream* os) const { + virtual bool MatchAndExplain(Container container, + MatchResultListener* listener) 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) { + size_t i = 0; + for (typename StlContainer::const_iterator it = stl_container.begin(); + it != stl_container.end(); ++it, ++i) { if (inner_matcher_.Matches(*it)) { - *os << "element " << i << " matches"; - return; + *listener << "element " << i << " matches"; + return true; } } + return false; } private: @@ -2007,8 +2038,9 @@ class KeyMatcherImpl : public MatcherInterface<PairType> { } // Returns true iff 'key_value.first' (the key) matches the inner matcher. - virtual bool Matches(PairType key_value) const { - return inner_matcher_.Matches(key_value.first); + virtual bool MatchAndExplain(PairType key_value, + MatchResultListener* listener) const { + return inner_matcher_.MatchAndExplain(key_value.first, listener); } // Describes what this matcher does. @@ -2023,12 +2055,6 @@ class KeyMatcherImpl : public MatcherInterface<PairType> { inner_matcher_.DescribeTo(os); } - // Explains why 'key_value' matches, or doesn't match, this matcher. - virtual void ExplainMatchResultTo(PairType key_value, - ::std::ostream* os) const { - inner_matcher_.ExplainMatchResultTo(key_value.first, os); - } - private: const Matcher<const KeyType&> inner_matcher_; @@ -2069,13 +2095,6 @@ class PairMatcherImpl : public MatcherInterface<PairType> { testing::SafeMatcherCast<const SecondType&>(second_matcher)) { } - // Returns true iff 'a_pair.first' matches first_matcher and 'a_pair.second' - // matches second_matcher. - virtual bool Matches(PairType a_pair) const { - return first_matcher_.Matches(a_pair.first) && - second_matcher_.Matches(a_pair.second); - } - // Describes what this matcher does. virtual void DescribeTo(::std::ostream* os) const { *os << "has a first field that "; @@ -2092,31 +2111,54 @@ class PairMatcherImpl : public MatcherInterface<PairType> { second_matcher_.DescribeNegationTo(os); } - // Explains why 'a_pair' matches, or doesn't match, this matcher. - virtual void ExplainMatchResultTo(PairType a_pair, - ::std::ostream* os) const { - ::std::stringstream ss1; - first_matcher_.ExplainMatchResultTo(a_pair.first, &ss1); - internal::string s1 = ss1.str(); - if (s1 != "") { - s1 = "the first field " + s1; + // Returns true iff 'a_pair.first' matches first_matcher and 'a_pair.second' + // matches second_matcher. + virtual bool MatchAndExplain(PairType a_pair, + MatchResultListener* listener) const { + if (!listener->IsInterested()) { + // If the listener is not interested, we don't need to construct the + // explanation. + return first_matcher_.Matches(a_pair.first) && + second_matcher_.Matches(a_pair.second); } - - ::std::stringstream ss2; - second_matcher_.ExplainMatchResultTo(a_pair.second, &ss2); - internal::string s2 = ss2.str(); - if (s2 != "") { - s2 = "the second field " + s2; + StringMatchResultListener first_inner_listener; + if (!first_matcher_.MatchAndExplain(a_pair.first, + &first_inner_listener)) { + *listener << "whose first field does not match"; + PrintIfNotEmpty(first_inner_listener.str(), listener); + return false; } - - *os << s1; - if (s1 != "" && s2 != "") { - *os << ", and "; + StringMatchResultListener second_inner_listener; + if (!second_matcher_.MatchAndExplain(a_pair.second, + &second_inner_listener)) { + *listener << "whose second field does not match"; + PrintIfNotEmpty(second_inner_listener.str(), listener); + return false; } - *os << s2; + ExplainSuccess(first_inner_listener.str(), second_inner_listener.str(), + listener); + return true; } private: + void ExplainSuccess(const internal::string& first_explanation, + const internal::string& second_explanation, + MatchResultListener* listener) const { + *listener << "whose both fields match"; + if (first_explanation != "") { + *listener << ", where the first field is a value " << first_explanation; + } + if (second_explanation != "") { + *listener << ", "; + if (first_explanation != "") { + *listener << "and "; + } else { + *listener << "where "; + } + *listener << "the second field is a value " << second_explanation; + } + } + const Matcher<const FirstType&> first_matcher_; const Matcher<const SecondType&> second_matcher_; @@ -2165,21 +2207,6 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> { } } - // Returns true iff 'container' matches. - virtual bool Matches(Container container) const { - StlContainerReference stl_container = View::ConstReference(container); - if (stl_container.size() != count()) - return false; - - typename StlContainer::const_iterator it = stl_container.begin(); - for (size_t i = 0; i != count(); ++it, ++i) { - if (!matchers_[i].Matches(*it)) - return false; - } - - return true; - } - // Describes what this matcher does. virtual void DescribeTo(::std::ostream* os) const { if (count() == 0) { @@ -2216,63 +2243,54 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> { } } - // Explains why 'container' matches, or doesn't match, this matcher. - virtual void ExplainMatchResultTo(Container container, - ::std::ostream* os) const { + virtual bool MatchAndExplain(Container container, + MatchResultListener* listener) 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 StlContainer::const_iterator it = stl_container.begin(); - for (size_t i = 0; i != count(); ++it, ++i) { - ::std::stringstream ss; - matchers_[i].ExplainMatchResultTo(*it, &ss); - - const string s = ss.str(); - if (!s.empty()) { - if (reason_printed) { - *os << ",\n"; - } - *os << "element " << i << " " << s; - reason_printed = true; - } - } - } else { - // We need to explain why the container doesn't match. - 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 - // already prints the empty container. Otherwise we just need - // to show how many elements there actually are. - if (actual_count != 0) { - *os << "has " << Elements(actual_count); - } - return; + 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 already + // prints the empty container. Otherwise we just need to show + // how many elements there actually are. + if (actual_count != 0) { + *listener << "has " << Elements(actual_count); } + return false; + } - // 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 StlContainer::const_iterator it = stl_container.begin(); - for (size_t i = 0; i != count(); ++it, ++i) { - if (matchers_[i].Matches(*it)) { - continue; - } + typename StlContainer::const_iterator it = stl_container.begin(); + // explanations[i] is the explanation of the element at index i. + std::vector<internal::string> explanations(count()); + for (size_t i = 0; i != count(); ++it, ++i) { + StringMatchResultListener s; + if (matchers_[i].MatchAndExplain(*it, &s)) { + explanations[i] = s.str(); + } else { + // The container has the right size but the i-th element + // doesn't match its expectation. + *listener << "element " << i << " doesn't match"; - *os << "element " << i << " doesn't match"; + StreamInParensAsNeeded(s.str(), listener->stream()); + return false; + } + } + + // Every element matches its expectation. We need to explain why + // (the obvious ones can be skipped). - ::std::stringstream ss; - matchers_[i].ExplainMatchResultTo(*it, &ss); - const string s = ss.str(); - if (!s.empty()) { - *os << " (" << s << ")"; + bool reason_printed = false; + for (size_t i = 0; i != count(); ++i) { + const internal::string& s = explanations[i]; + if (!s.empty()) { + if (reason_printed) { + *listener << ",\n"; } - return; + *listener << "element " << i << " " << s; + reason_printed = true; } } + + return true; } private: @@ -2609,8 +2627,6 @@ inline PolymorphicMatcher<internal::EndsWithMatcher<internal::string> > suffix)); } -#ifdef GMOCK_HAS_REGEX - // Matches a string that fully matches regular expression 'regex'. // The matcher takes ownership of 'regex'. inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex( @@ -2633,8 +2649,6 @@ inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex( return ContainsRegex(new internal::RE(regex)); } -#endif // GMOCK_HAS_REGEX - #if GTEST_HAS_GLOBAL_WSTRING || GTEST_HAS_STD_WSTRING // Wide string matchers. @@ -2811,13 +2825,14 @@ 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< +inline PolymorphicMatcher<internal::ContainerEqMatcher< // NOLINT GMOCK_REMOVE_CONST_(Container)> > ContainerEq(const 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)); + return MakePolymorphicMatcher( + internal::ContainerEqMatcher<RawContainer>(rhs)); } // Matches an STL-style container or a native array that contains at @@ -2876,6 +2891,14 @@ inline bool Value(const T& value, M matcher) { return testing::Matches(matcher)(value); } +// Matches the value against the given matcher and explains the match +// result to listener. +template <typename T, typename M> +inline bool ExplainMatchResult( + M matcher, const T& value, MatchResultListener* listener) { + return SafeMatcherCast<const T&>(matcher).MatchAndExplain(value, listener); +} + // AllArgs(m) is a synonym of m. This is useful in // // EXPECT_CALL(foo, Bar(_, _)).With(AllArgs(Eq())); diff --git a/testing/gmock/include/gmock/gmock-printers.h b/testing/gmock/include/gmock/gmock-printers.h index cda3545..d1cd03c 100644 --- a/testing/gmock/include/gmock/gmock-printers.h +++ b/testing/gmock/include/gmock/gmock-printers.h @@ -57,18 +57,20 @@ // // We also provide some convenient wrappers: // -// // Prints a value as the given type to a string. -// string ::testing::internal::UniversalPrinter<T>::PrintToString(value); +// // Prints a value to a string. For a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// std::string ::testing::PrintToString(const T& value); // // // Prints a value tersely: for a reference type, the referenced -// // value (but not the address) is printed; for a (const) char +// // value (but not the address) is printed; for a (const or not) char // // pointer, the NUL-terminated string (but not the pointer) is // // 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. +// // pointer and the NUL-terminated string for a (const or not) char pointer. // void ::testing::internal::UniversalPrint(const T& value, ostream*); // // // Prints the fields of a tuple tersely to a string vector, one @@ -545,14 +547,6 @@ class UniversalPrinter { PrintTo(value, os); } - // A convenient wrapper for Print() that returns the print-out as a - // string. - static string PrintToString(const T& value) { - ::std::stringstream ss; - Print(value, &ss); - return ss.str(); - } - #ifdef _MSC_VER #pragma warning(pop) // Restores the warning state. #endif // _MSC_VER @@ -585,14 +579,6 @@ void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* 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]> { @@ -602,12 +588,6 @@ class UniversalPrinter<T[N]> { static void Print(const T (&a)[N], ::std::ostream* 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]) { - return UniversalPrintArrayToString(a, N); - } }; // Implements printing a reference type T&. @@ -630,14 +610,6 @@ class UniversalPrinter<T&> { UniversalPrinter<T>::Print(value, os); } - // A convenient wrapper for Print() that returns the print-out as a - // string. - static string PrintToString(const T& value) { - ::std::stringstream ss; - Print(value, &ss); - return ss.str(); - } - #ifdef _MSC_VER #pragma warning(pop) // Restores the warning state. #endif // _MSC_VER @@ -740,6 +712,14 @@ Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { } } // namespace internal + +template <typename T> +::std::string PrintToString(const T& value) { + ::std::stringstream ss; + internal::UniversalTersePrint(value, &ss); + return ss.str(); +} + } // namespace testing #endif // GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_ diff --git a/testing/gmock/include/gmock/gmock-spec-builders.h b/testing/gmock/include/gmock/gmock-spec-builders.h index 9aa0a9e..9b60f69 100644 --- a/testing/gmock/include/gmock/gmock-spec-builders.h +++ b/testing/gmock/include/gmock/gmock-spec-builders.h @@ -112,7 +112,7 @@ template <typename F> class FunctionMockerBase; // expectations when InSequence() is used, and thus affect which // expectation gets picked. Therefore, we sequence all mock function // calls to ensure the integrity of the mock objects' states. -extern Mutex g_gmock_mutex; +GTEST_DECLARE_STATIC_MUTEX_(g_gmock_mutex); // Abstract base class of FunctionMockerBase. This is the // type-agnostic part of the function mocker interface. Its pure @@ -1004,13 +1004,13 @@ class TypedExpectation : public ExpectationBase { if (!TupleMatches(matchers_, args)) { DescribeMatchFailureTupleTo(matchers_, args, os); } - if (!extra_matcher_.Matches(args)) { + StringMatchResultListener listener; + if (!extra_matcher_.MatchAndExplain(args, &listener)) { *os << " Expected args: "; extra_matcher_.DescribeTo(os); *os << "\n Actual: don't match"; - internal::ExplainMatchResultAsNeededTo<const ArgumentTuple&>( - extra_matcher_, args, os); + internal::StreamInParensAsNeeded(listener.str(), os); *os << "\n"; } } else if (!AllPrerequisitesAreSatisfied()) { diff --git a/testing/gmock/include/gmock/internal/gmock-port.h b/testing/gmock/include/gmock/internal/gmock-port.h index 27b67a5..30115f2 100644 --- a/testing/gmock/include/gmock/internal/gmock-port.h +++ b/testing/gmock/include/gmock/internal/gmock-port.h @@ -52,26 +52,8 @@ #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 { diff --git a/testing/gmock/run_tests.py b/testing/gmock/run_tests.py new file mode 100755 index 0000000..42dc14b --- /dev/null +++ b/testing/gmock/run_tests.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# +# 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. + +"""Runs the specified tests for Google Mock. + +This script requires Python 2.3 or higher. To learn the usage, run it +with -h. +""" + +__author__ = 'vladl@google.com (Vlad Losev)' + + +import os +import sys + +SCRIPT_DIR = os.path.dirname(__file__) or '.' + +# Path to the Google Test code this Google Mock will use. We assume the +# gtest/ directory is either a subdirectory (possibly via a symbolic link) +# of gmock/ or a sibling. +# +# isdir resolves symbolic links. +if os.path.isdir(os.path.join(SCRIPT_DIR, 'gtest/test')): + RUN_TESTS_UTIL_DIR = os.path.join(SCRIPT_DIR, 'gtest/test') +else: + RUN_TESTS_UTIL_DIR = os.path.join(SCRIPT_DIR, '../gtest/test') + +sys.path.append(RUN_TESTS_UTIL_DIR) +import run_tests_util + +def GetGmockBuildDir(injected_os, script_dir, config): + return injected_os.path.normpath(injected_os.path.join(script_dir, + 'scons/build', + config, + 'gmock/scons')) + + +def _Main(): + """Runs all tests for Google Mock.""" + + options, args = run_tests_util.ParseArgs('gtest') + test_runner = run_tests_util.TestRunner( + script_dir=SCRIPT_DIR, + build_dir_var_name='GMOCK_BUILD_DIR', + injected_build_dir_finder=GetGmockBuildDir) + tests = test_runner.GetTestsToRun(args, + options.configurations, + options.built_configurations) + if not tests: + sys.exit(1) # Incorrect parameters given, abort execution. + + sys.exit(test_runner.RunTests(tests[0], tests[1])) + +if __name__ == '__main__': + _Main() diff --git a/testing/gmock/src/gmock-internal-utils.cc b/testing/gmock/src/gmock-internal-utils.cc index 4c51ec0..cc51836 100644 --- a/testing/gmock/src/gmock-internal-utils.cc +++ b/testing/gmock/src/gmock-internal-utils.cc @@ -103,7 +103,7 @@ FailureReporterInterface* GetFailureReporter() { } // Protects global resources (stdout in particular) used by Log(). -static Mutex g_log_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX); +static GTEST_DEFINE_STATIC_MUTEX_(g_log_mutex); // Returns true iff a log with the given severity is visible according // to the --gmock_verbose flag. diff --git a/testing/gmock/src/gmock-spec-builders.cc b/testing/gmock/src/gmock-spec-builders.cc index 02a3227..dab1a2c 100644 --- a/testing/gmock/src/gmock-spec-builders.cc +++ b/testing/gmock/src/gmock-spec-builders.cc @@ -53,7 +53,7 @@ namespace internal { // Protects the mock object registry (in class Mock), all function // mockers, and all expectations. -Mutex g_gmock_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX); +GTEST_DEFINE_STATIC_MUTEX_(g_gmock_mutex); // Constructs an ExpectationBase object. ExpectationBase::ExpectationBase(const char* a_file, diff --git a/testing/gmock/test/gmock-generated-matchers_test.cc b/testing/gmock/test/gmock-generated-matchers_test.cc index 4141305..db2ffb2 100644 --- a/testing/gmock/test/gmock-generated-matchers_test.cc +++ b/testing/gmock/test/gmock-generated-matchers_test.cc @@ -68,6 +68,7 @@ using testing::Lt; using testing::MakeMatcher; using testing::Matcher; using testing::MatcherInterface; +using testing::MatchResultListener; using testing::Ne; using testing::Not; using testing::Pointee; @@ -136,6 +137,16 @@ TEST(ArgsTest, AcceptsDecreasingTemplateArgs) { EXPECT_THAT(t, Not(Args<2, 1>(Lt()))); } +// The MATCHER*() macros trigger warning C4100 (unreferenced formal +// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in +// the macro definition, as the warnings are generated when the macro +// is expanded and macro expansion cannot contain #pragma. Therefore +// we suppress them here. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4100) +#endif + MATCHER(SumIsZero, "") { return get<0>(arg) + get<1>(arg) + get<2>(arg) == 0; } @@ -167,9 +178,7 @@ TEST(ArgsTest, CanMatchTupleByReference) { // 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; + return testing::PrintToString(arg) == str; } TEST(ArgsTest, AcceptsTenTemplateArgs) { @@ -207,21 +216,22 @@ class GreaterThanMatcher : public MatcherInterface<int> { public: explicit GreaterThanMatcher(int rhs) : rhs_(rhs) {} - virtual bool Matches(int lhs) const { return lhs > rhs_; } - virtual void DescribeTo(::std::ostream* os) const { *os << "is greater than " << rhs_; } - virtual void ExplainMatchResultTo(int lhs, ::std::ostream* os) const { + virtual bool MatchAndExplain(int lhs, + MatchResultListener* listener) const { const int diff = lhs - rhs_; if (diff > 0) { - *os << "is " << diff << " more than " << rhs_; + *listener << "is " << diff << " more than " << rhs_; } else if (diff == 0) { - *os << "is the same as " << rhs_; + *listener << "is the same as " << rhs_; } else { - *os << "is " << -diff << " less than " << rhs_; + *listener << "is " << -diff << " less than " << rhs_; } + + return lhs > rhs_; } private: @@ -553,6 +563,44 @@ TEST(MatcherMacroTest, Works) { EXPECT_EQ("", Explain(m, 7)); } +// Tests explaining match result in a MATCHER* macro. + +MATCHER(IsEven2, "is even") { + if ((arg % 2) == 0) { + // Verifies that we can stream to result_listener, a listener + // supplied by the MATCHER macro implicitly. + *result_listener << "OK"; + return true; + } else { + *result_listener << "% 2 == " << (arg % 2); + return false; + } +} + +MATCHER_P2(EqSumOf, x, y, "") { + if (arg == (x + y)) { + *result_listener << "OK"; + return true; + } else { + // Verifies that we can stream to the underlying stream of + // result_listener. + if (result_listener->stream() != NULL) { + *result_listener->stream() << "diff == " << (x + y - arg); + } + return false; + } +} + +TEST(MatcherMacroTest, CanExplainMatchResult) { + const Matcher<int> m1 = IsEven2(); + EXPECT_EQ("OK", Explain(m1, 4)); + EXPECT_EQ("% 2 == 1", Explain(m1, 5)); + + const Matcher<int> m2 = EqSumOf(1, 2); + EXPECT_EQ("OK", Explain(m2, 3)); + EXPECT_EQ("diff == -1", Explain(m2, 4)); +} + // Tests that the description string supplied to MATCHER() must be // valid. @@ -1052,4 +1100,8 @@ TEST(ContainsTest, WorksForTwoDimensionalNativeArray) { EXPECT_THAT(a, Contains(Not(Contains(5)))); } +#ifdef _MSC_VER +#pragma warning(pop) +#endif + } // namespace diff --git a/testing/gmock/test/gmock-internal-utils_test.cc b/testing/gmock/test/gmock-internal-utils_test.cc index 7dd8311..fc5d9e5 100644 --- a/testing/gmock/test/gmock-internal-utils_test.cc +++ b/testing/gmock/test/gmock-internal-utils_test.cc @@ -538,8 +538,7 @@ TEST_F(LogIsVisibleTest, WorksWhenVerbosityIsWarning) { EXPECT_TRUE(LogIsVisible(WARNING)); } -// TODO(wan@google.com): find a way to re-enable these tests. -#if 0 +#if GTEST_HAS_STREAM_REDIRECTION_ // Tests the Log() function. @@ -549,16 +548,16 @@ void TestLogWithSeverity(const string& verbosity, LogSeverity severity, bool should_print) { const string old_flag = GMOCK_FLAG(verbose); GMOCK_FLAG(verbose) = verbosity; - CaptureTestStdout(); + CaptureStdout(); Log(severity, "Test log.\n", 0); if (should_print) { - EXPECT_PRED2(RE::FullMatch, - GetCapturedTestStdout(), - severity == WARNING ? - "\nGMOCK WARNING:\nTest log\\.\nStack trace:\n[\\s\\S]*" : - "\nTest log\\.\nStack trace:\n[\\s\\S]*"); + EXPECT_THAT(GetCapturedStdout().c_str(), + ContainsRegex( + severity == WARNING ? + "^\nGMOCK WARNING:\nTest log\\.\nStack trace:\n" : + "^\nTest log\\.\nStack trace:\n")); } else { - EXPECT_EQ("", GetCapturedTestStdout()); + EXPECT_STREQ("", GetCapturedStdout().c_str()); } GMOCK_FLAG(verbose) = old_flag; } @@ -567,18 +566,18 @@ void TestLogWithSeverity(const string& verbosity, LogSeverity severity, // Log() doesn't include the stack trace in the output. TEST(LogTest, NoStackTraceWhenStackFramesToSkipIsNegative) { GMOCK_FLAG(verbose) = kInfoVerbosity; - CaptureTestStdout(); + CaptureStdout(); Log(INFO, "Test log.\n", -1); - EXPECT_EQ("\nTest log.\n", GetCapturedTestStdout()); + EXPECT_STREQ("\nTest log.\n", GetCapturedStdout().c_str()); } // Tests that in opt mode, a positive stack_frames_to_skip argument is // treated as 0. TEST(LogTest, NoSkippingStackFrameInOptMode) { - CaptureTestStdout(); + CaptureStdout(); Log(WARNING, "Test log.\n", 100); - const string log = GetCapturedTestStdout(); -#ifdef NDEBUG + const String log = GetCapturedStdout(); +#if defined(NDEBUG) && GTEST_GOOGLE3_MODE_ // In opt mode, no stack frame should be skipped. EXPECT_THAT(log, ContainsRegex("\nGMOCK WARNING:\n" "Test log\\.\n" @@ -586,10 +585,10 @@ TEST(LogTest, NoSkippingStackFrameInOptMode) { ".+")); #else // In dbg mode, the stack frames should be skipped. - EXPECT_EQ("\nGMOCK WARNING:\n" - "Test log.\n" - "Stack trace:\n", log); -#endif // NDEBUG + EXPECT_STREQ("\nGMOCK WARNING:\n" + "Test log.\n" + "Stack trace:\n", log.c_str()); +#endif } // Tests that all logs are printed when the value of the @@ -620,7 +619,7 @@ TEST(LogTest, OnlyWarningsArePrintedWhenVerbosityIsInvalid) { TestLogWithSeverity("invalid", WARNING, true); } -#endif // 0 +#endif // GTEST_HAS_STREAM_REDIRECTION_ TEST(TypeTraitsTest, true_type) { EXPECT_TRUE(true_type::value); @@ -657,18 +656,17 @@ TEST(TypeTraitsTest, remove_reference) { EXPECT_TRUE((type_equals<double*, remove_reference<double*>::type>::value)); } -// TODO(wan@google.com): find a way to re-enable these tests. -#if 0 +#if GTEST_HAS_STREAM_REDIRECTION_ // Verifies that Log() behaves correctly for the given verbosity level // and log severity. -string GrabOutput(void(*logger)(), const char* verbosity) { +String GrabOutput(void(*logger)(), const char* verbosity) { const string saved_flag = GMOCK_FLAG(verbose); GMOCK_FLAG(verbose) = verbosity; - CaptureTestStdout(); + CaptureStdout(); logger(); GMOCK_FLAG(verbose) = saved_flag; - return GetCapturedTestStdout(); + return GetCapturedStdout(); } class DummyMock { @@ -692,13 +690,13 @@ TEST(ExpectCallTest, LogsWhenVerbosityIsInfo) { // Verifies that EXPECT_CALL doesn't log // if the --gmock_verbose flag is set to "warning". TEST(ExpectCallTest, DoesNotLogWhenVerbosityIsWarning) { - EXPECT_EQ("", GrabOutput(ExpectCallLogger, kWarningVerbosity)); + EXPECT_STREQ("", GrabOutput(ExpectCallLogger, kWarningVerbosity).c_str()); } // Verifies that EXPECT_CALL doesn't log // if the --gmock_verbose flag is set to "error". TEST(ExpectCallTest, DoesNotLogWhenVerbosityIsError) { - EXPECT_EQ("", GrabOutput(ExpectCallLogger, kErrorVerbosity)); + EXPECT_STREQ("", GrabOutput(ExpectCallLogger, kErrorVerbosity).c_str()); } void OnCallLogger() { @@ -715,13 +713,13 @@ TEST(OnCallTest, LogsWhenVerbosityIsInfo) { // Verifies that ON_CALL doesn't log // if the --gmock_verbose flag is set to "warning". TEST(OnCallTest, DoesNotLogWhenVerbosityIsWarning) { - EXPECT_EQ("", GrabOutput(OnCallLogger, kWarningVerbosity)); + EXPECT_STREQ("", GrabOutput(OnCallLogger, kWarningVerbosity).c_str()); } // Verifies that ON_CALL doesn't log if // the --gmock_verbose flag is set to "error". TEST(OnCallTest, DoesNotLogWhenVerbosityIsError) { - EXPECT_EQ("", GrabOutput(OnCallLogger, kErrorVerbosity)); + EXPECT_STREQ("", GrabOutput(OnCallLogger, kErrorVerbosity).c_str()); } void OnCallAnyArgumentLogger() { @@ -735,7 +733,7 @@ TEST(OnCallTest, LogsAnythingArgument) { HasSubstr("ON_CALL(mock, TestMethodArg(_)")); } -#endif // 0 +#endif // GTEST_HAS_STREAM_REDIRECTION_ // Tests ArrayEq(). diff --git a/testing/gmock/test/gmock-matchers_test.cc b/testing/gmock/test/gmock-matchers_test.cc index 907749d..5557983 100644 --- a/testing/gmock/test/gmock-matchers_test.cc +++ b/testing/gmock/test/gmock-matchers_test.cc @@ -37,6 +37,7 @@ #include <string.h> #include <functional> +#include <iostream> #include <list> #include <map> #include <set> @@ -88,6 +89,8 @@ using testing::Matcher; using testing::MatcherCast; using testing::MatcherInterface; using testing::Matches; +using testing::ExplainMatchResult; +using testing::MatchResultListener; using testing::NanSensitiveDoubleEq; using testing::NanSensitiveFloatEq; using testing::Ne; @@ -108,6 +111,7 @@ using testing::Truly; using testing::TypedEq; using testing::Value; using testing::_; +using testing::internal::DummyMatchResultListener; using testing::internal::FloatingEqMatcher; using testing::internal::FormatMatcherDescriptionSyntaxError; using testing::internal::GetParamIndex; @@ -115,8 +119,10 @@ using testing::internal::Interpolation; using testing::internal::Interpolations; using testing::internal::JoinAsTuple; using testing::internal::SkipPrefix; +using testing::internal::StreamMatchResultListener; using testing::internal::String; using testing::internal::Strings; +using testing::internal::StringMatchResultListener; using testing::internal::ValidateMatcherDescription; using testing::internal::kInvalidInterpolation; using testing::internal::kPercentInterpolation; @@ -125,32 +131,31 @@ using testing::internal::linked_ptr; using testing::internal::scoped_ptr; using testing::internal::string; -#ifdef GMOCK_HAS_REGEX using testing::ContainsRegex; using testing::MatchesRegex; using testing::internal::RE; -#endif // GMOCK_HAS_REGEX // For testing ExplainMatchResultTo(). class GreaterThanMatcher : public MatcherInterface<int> { public: explicit GreaterThanMatcher(int rhs) : rhs_(rhs) {} - virtual bool Matches(int lhs) const { return lhs > rhs_; } - virtual void DescribeTo(::std::ostream* os) const { *os << "is greater than " << rhs_; } - virtual void ExplainMatchResultTo(int lhs, ::std::ostream* os) const { + virtual bool MatchAndExplain(int lhs, + MatchResultListener* listener) const { const int diff = lhs - rhs_; if (diff > 0) { - *os << "is " << diff << " more than " << rhs_; + *listener << "which is " << diff << " more than " << rhs_; } else if (diff == 0) { - *os << "is the same as " << rhs_; + *listener << "which is the same as " << rhs_; } else { - *os << "is " << -diff << " less than " << rhs_; + *listener << "which is " << -diff << " less than " << rhs_; } + + return lhs > rhs_; } private: @@ -185,11 +190,39 @@ string Explain(const MatcherType& m, const Value& x) { return ss.str(); } +TEST(MatchResultListenerTest, StreamingWorks) { + StringMatchResultListener listener; + listener << "hi" << 5; + EXPECT_EQ("hi5", listener.str()); + + // Streaming shouldn't crash when the underlying ostream is NULL. + DummyMatchResultListener dummy; + dummy << "hi" << 5; +} + +TEST(MatchResultListenerTest, CanAccessUnderlyingStream) { + EXPECT_TRUE(DummyMatchResultListener().stream() == NULL); + EXPECT_TRUE(StreamMatchResultListener(NULL).stream() == NULL); + + EXPECT_EQ(&std::cout, StreamMatchResultListener(&std::cout).stream()); +} + +TEST(MatchResultListenerTest, IsInterestedWorks) { + EXPECT_TRUE(StringMatchResultListener().IsInterested()); + EXPECT_TRUE(StreamMatchResultListener(&std::cout).IsInterested()); + + EXPECT_FALSE(DummyMatchResultListener().IsInterested()); + EXPECT_FALSE(StreamMatchResultListener(NULL).IsInterested()); +} + // Makes sure that the MatcherInterface<T> interface doesn't // change. class EvenMatcherImpl : public MatcherInterface<int> { public: - virtual bool Matches(int x) const { return x % 2 == 0; } + virtual bool MatchAndExplain(int x, + MatchResultListener* /* listener */) const { + return x % 2 == 0; + } virtual void DescribeTo(::std::ostream* os) const { *os << "is an even number"; @@ -200,10 +233,40 @@ class EvenMatcherImpl : public MatcherInterface<int> { // two methods is optional. }; -TEST(MatcherInterfaceTest, CanBeImplemented) { +// Makes sure that the MatcherInterface API doesn't change. +TEST(MatcherInterfaceTest, CanBeImplementedUsingPublishedAPI) { EvenMatcherImpl m; } +// Tests implementing a monomorphic matcher using MatchAndExplain(). + +class NewEvenMatcherImpl : public MatcherInterface<int> { + public: + virtual bool MatchAndExplain(int x, MatchResultListener* listener) const { + const bool match = x % 2 == 0; + // Verifies that we can stream to a listener directly. + *listener << "value % " << 2; + if (listener->stream() != NULL) { + // Verifies that we can stream to a listener's underlying stream + // too. + *listener->stream() << " == " << (x % 2); + } + return match; + } + + virtual void DescribeTo(::std::ostream* os) const { + *os << "is an even number"; + } +}; + +TEST(MatcherInterfaceTest, CanBeImplementedUsingNewAPI) { + Matcher<int> m = MakeMatcher(new NewEvenMatcherImpl); + EXPECT_TRUE(m.Matches(2)); + EXPECT_FALSE(m.Matches(3)); + EXPECT_EQ("value % 2 == 0", Explain(m, 2)); + EXPECT_EQ("value % 2 == 1", Explain(m, 3)); +} + // Tests default-constructing a matcher. TEST(MatcherTest, CanBeDefaultConstructed) { Matcher<double> m; @@ -252,6 +315,18 @@ TEST(MatcherTest, CanDescribeItself) { Describe(Matcher<int>(new EvenMatcherImpl))); } +// Tests Matcher<T>::MatchAndExplain(). +TEST(MatcherTest, MatchAndExplain) { + Matcher<int> m = GreaterThan(0); + StringMatchResultListener listener1; + EXPECT_TRUE(m.MatchAndExplain(42, &listener1)); + EXPECT_EQ("which is 42 more than 0", listener1.str()); + + StringMatchResultListener listener2; + EXPECT_FALSE(m.MatchAndExplain(-9, &listener2)); + EXPECT_EQ("which is 9 less than 0", listener2.str()); +} + // Tests that a C-string literal can be implicitly converted to a // Matcher<string> or Matcher<const string&>. TEST(StringMatcherTest, CanBeImplicitlyConstructedFromCStringLiteral) { @@ -284,13 +359,14 @@ TEST(MakeMatcherTest, ConstructsMatcherFromMatcherInterface) { Matcher<int> m = MakeMatcher(dummy_impl); } -// Tests that MakePolymorphicMatcher() constructs a polymorphic -// matcher from its implementation. +// Tests that MakePolymorphicMatcher() can construct a polymorphic +// matcher from its implementation using the old API. const int bar = 1; class ReferencesBarOrIsZeroImpl { public: template <typename T> - bool Matches(const T& x) const { + bool MatchAndExplain(const T& x, + MatchResultListener* /* listener */) const { const void* p = &x; return p == &bar || x == 0; } @@ -308,7 +384,7 @@ PolymorphicMatcher<ReferencesBarOrIsZeroImpl> ReferencesBarOrIsZero() { return MakePolymorphicMatcher(ReferencesBarOrIsZeroImpl()); } -TEST(MakePolymorphicMatcherTest, ConstructsMatcherFromImpl) { +TEST(MakePolymorphicMatcherTest, ConstructsMatcherUsingOldAPI) { // Using a polymorphic matcher to match a reference type. Matcher<const int&> m1 = ReferencesBarOrIsZero(); EXPECT_TRUE(m1.Matches(0)); @@ -324,6 +400,57 @@ TEST(MakePolymorphicMatcherTest, ConstructsMatcherFromImpl) { EXPECT_EQ("bar or zero", Describe(m2)); } +// Tests implementing a polymorphic matcher using MatchAndExplain(). + +class PolymorphicIsEvenImpl { + public: + void DescribeTo(::std::ostream* os) const { *os << "is even"; } + + void DescribeNegationTo(::std::ostream* os) const { + *os << "is odd"; + } + + template <typename T> + bool MatchAndExplain(const T& x, MatchResultListener* listener) const { + // Verifies that we can stream to the listener directly. + *listener << "% " << 2; + if (listener->stream() != NULL) { + // Verifies that we can stream to the listener's underlying stream + // too. + *listener->stream() << " == " << (x % 2); + } + return (x % 2) == 0; + } +}; + +PolymorphicMatcher<PolymorphicIsEvenImpl> PolymorphicIsEven() { + return MakePolymorphicMatcher(PolymorphicIsEvenImpl()); +} + +TEST(MakePolymorphicMatcherTest, ConstructsMatcherUsingNewAPI) { + // Using PolymorphicIsEven() as a Matcher<int>. + const Matcher<int> m1 = PolymorphicIsEven(); + EXPECT_TRUE(m1.Matches(42)); + EXPECT_FALSE(m1.Matches(43)); + EXPECT_EQ("is even", Describe(m1)); + + const Matcher<int> not_m1 = Not(m1); + EXPECT_EQ("is odd", Describe(not_m1)); + + EXPECT_EQ("% 2 == 0", Explain(m1, 42)); + + // Using PolymorphicIsEven() as a Matcher<char>. + const Matcher<char> m2 = PolymorphicIsEven(); + EXPECT_TRUE(m2.Matches('\x42')); + EXPECT_FALSE(m2.Matches('\x43')); + EXPECT_EQ("is even", Describe(m2)); + + const Matcher<char> not_m2 = Not(m2); + EXPECT_EQ("is odd", Describe(not_m2)); + + EXPECT_EQ("% 2 == 0", Explain(m2, '\x42')); +} + // Tests that MatcherCast<T>(m) works when m is a polymorphic matcher. TEST(MatcherCastTest, FromPolymorphicMatcher) { Matcher<int> m = MatcherCast<int>(Eq(5)); @@ -1050,21 +1177,41 @@ TEST(PairTest, CanDescribeSelf) { } TEST(PairTest, CanExplainMatchResultTo) { - const Matcher<std::pair<int, int> > m0 = Pair(0, 0); - EXPECT_EQ("", Explain(m0, std::make_pair(25, 42))); - - const Matcher<std::pair<int, int> > m1 = Pair(GreaterThan(0), 0); - EXPECT_EQ("the first field is 25 more than 0", - Explain(m1, std::make_pair(25, 42))); - - const Matcher<std::pair<int, int> > m2 = Pair(0, GreaterThan(0)); - EXPECT_EQ("the second field is 42 more than 0", - Explain(m2, std::make_pair(25, 42))); - - const Matcher<std::pair<int, int> > m3 = Pair(GreaterThan(0), GreaterThan(0)); - EXPECT_EQ("the first field is 25 more than 0" - ", and the second field is 42 more than 0", - Explain(m3, std::make_pair(25, 42))); + // If neither field matches, Pair() should explain about the first + // field. + const Matcher<std::pair<int, int> > m = Pair(GreaterThan(0), GreaterThan(0)); + EXPECT_EQ("whose first field does not match, which is 1 less than 0", + Explain(m, std::make_pair(-1, -2))); + + // If the first field matches but the second doesn't, Pair() should + // explain about the second field. + EXPECT_EQ("whose second field does not match, which is 2 less than 0", + Explain(m, std::make_pair(1, -2))); + + // If the first field doesn't match but the second does, Pair() + // should explain about the first field. + EXPECT_EQ("whose first field does not match, which is 1 less than 0", + Explain(m, std::make_pair(-1, 2))); + + // If both fields match, Pair() should explain about them both. + EXPECT_EQ("whose both fields match, where the first field is a value " + "which is 1 more than 0, and the second field is a value " + "which is 2 more than 0", + Explain(m, std::make_pair(1, 2))); + + // If only the first match has an explanation, only this explanation should + // be printed. + const Matcher<std::pair<int, int> > explain_first = Pair(GreaterThan(0), 0); + EXPECT_EQ("whose both fields match, where the first field is a value " + "which is 1 more than 0", + Explain(explain_first, std::make_pair(1, 0))); + + // If only the second match has an explanation, only this explanation should + // be printed. + const Matcher<std::pair<int, int> > explain_second = Pair(0, GreaterThan(0)); + EXPECT_EQ("whose both fields match, where the second field is a value " + "which is 1 more than 0", + Explain(explain_second, std::make_pair(0, 1))); } TEST(PairTest, MatchesCorrectly) { @@ -1150,8 +1297,6 @@ TEST(EndsWithTest, CanDescribeSelf) { EXPECT_EQ("ends with \"Hi\"", Describe(m)); } -#ifdef GMOCK_HAS_REGEX - // Tests MatchesRegex(). TEST(MatchesRegexTest, MatchesStringMatchingGivenRegex) { @@ -1170,8 +1315,8 @@ TEST(MatchesRegexTest, CanDescribeSelf) { Matcher<const std::string> m1 = MatchesRegex(string("Hi.*")); EXPECT_EQ("matches regular expression \"Hi.*\"", Describe(m1)); - Matcher<const char*> m2 = MatchesRegex(new RE("[a-z].*")); - EXPECT_EQ("matches regular expression \"[a-z].*\"", Describe(m2)); + Matcher<const char*> m2 = MatchesRegex(new RE("a.*")); + EXPECT_EQ("matches regular expression \"a.*\"", Describe(m2)); } // Tests ContainsRegex(). @@ -1192,10 +1337,9 @@ TEST(ContainsRegexTest, CanDescribeSelf) { Matcher<const std::string> m1 = ContainsRegex("Hi.*"); EXPECT_EQ("contains regular expression \"Hi.*\"", Describe(m1)); - Matcher<const char*> m2 = ContainsRegex(new RE("[a-z].*")); - EXPECT_EQ("contains regular expression \"[a-z].*\"", Describe(m2)); + Matcher<const char*> m2 = ContainsRegex(new RE("a.*")); + EXPECT_EQ("contains regular expression \"a.*\"", Describe(m2)); } -#endif // GMOCK_HAS_REGEX // Tests for wide strings. #if GTEST_HAS_STD_WSTRING @@ -1949,6 +2093,36 @@ TEST(ValueTest, WorksWithMonomorphicMatcher) { EXPECT_FALSE(Value(1, ref_n)); } +TEST(ExplainMatchResultTest, WorksWithPolymorphicMatcher) { + StringMatchResultListener listener1; + EXPECT_TRUE(ExplainMatchResult(PolymorphicIsEven(), 42, &listener1)); + EXPECT_EQ("% 2 == 0", listener1.str()); + + StringMatchResultListener listener2; + EXPECT_FALSE(ExplainMatchResult(Ge(42), 1.5, &listener2)); + EXPECT_EQ("", listener2.str()); +} + +TEST(ExplainMatchResultTest, WorksWithMonomorphicMatcher) { + const Matcher<int> is_even = PolymorphicIsEven(); + StringMatchResultListener listener1; + EXPECT_TRUE(ExplainMatchResult(is_even, 42, &listener1)); + EXPECT_EQ("% 2 == 0", listener1.str()); + + const Matcher<const double&> is_zero = Eq(0); + StringMatchResultListener listener2; + EXPECT_FALSE(ExplainMatchResult(is_zero, 1.5, &listener2)); + EXPECT_EQ("", listener2.str()); +} + +MATCHER_P(Really, inner_matcher, "") { + return ExplainMatchResult(inner_matcher, arg, result_listener); +} + +TEST(ExplainMatchResultTest, WorksInsideMATCHER) { + EXPECT_THAT(0, Really(Eq(0))); +} + TEST(AllArgsTest, WorksForTuple) { EXPECT_THAT(make_tuple(1, 2L), AllArgs(Lt())); EXPECT_THAT(make_tuple(2L, 1), Not(AllArgs(Lt()))); @@ -2041,8 +2215,8 @@ TEST(MatcherAssertionTest, WorksForByRefArguments) { // ASSERT_THAT("hello", starts_with_he) fails to compile with Nokia's // Symbian compiler: it tries to compile // template<T, U> class MatcherCastImpl { ... -// virtual bool Matches(T x) const { -// return source_matcher_.Matches(static_cast<U>(x)); +// virtual bool MatchAndExplain(T x, ...) const { +// return source_matcher_.MatchAndExplain(static_cast<U>(x), ...); // with U == string and T == const char* // With ASSERT_THAT("hello"...) changed to ASSERT_THAT(string("hello") ... ) // the compiler silently crashes with no output. @@ -2385,7 +2559,14 @@ TEST(PointeeTest, CanExplainMatchResult) { const Matcher<int*> m2 = Pointee(GreaterThan(1)); int n = 3; - EXPECT_EQ("points to a value that is 2 more than 1", Explain(m2, &n)); + EXPECT_EQ("which points to 3, which is 2 more than 1", + Explain(m2, &n)); +} + +TEST(PointeeTest, AlwaysExplainsPointee) { + const Matcher<int*> m = Pointee(0); + int n = 42; + EXPECT_EQ("which points to 42", Explain(m, &n)); } // An uncopyable class. @@ -2512,8 +2693,9 @@ TEST(FieldTest, WorksForCompatibleMatcherType) { TEST(FieldTest, CanDescribeSelf) { Matcher<const AStruct&> m = Field(&AStruct::x, Ge(0)); - EXPECT_EQ("the given field is greater than or equal to 0", Describe(m)); - EXPECT_EQ("the given field is not greater than or equal to 0", + EXPECT_EQ("is an object whose given field is greater than or equal to 0", + Describe(m)); + EXPECT_EQ("is an object whose given field is not greater than or equal to 0", DescribeNegation(m)); } @@ -2523,10 +2705,10 @@ TEST(FieldTest, CanExplainMatchResult) { AStruct a; a.x = 1; - EXPECT_EQ("", Explain(m, a)); + EXPECT_EQ("whose given field is 1", Explain(m, a)); m = Field(&AStruct::x, GreaterThan(0)); - EXPECT_EQ("the given field is 1 more than 0", Explain(m, a)); + EXPECT_EQ("whose given field is 1, which is 1 more than 0", Explain(m, a)); } // Tests that Field() works when the argument is a pointer to const. @@ -2549,6 +2731,16 @@ TEST(FieldForPointerTest, WorksForPointerToNonConst) { EXPECT_FALSE(m.Matches(&a)); } +// Tests that Field() works when the argument is a reference to a const pointer. +TEST(FieldForPointerTest, WorksForReferenceToConstPointer) { + Matcher<AStruct* const&> m = Field(&AStruct::x, Ge(0)); + + AStruct a; + EXPECT_TRUE(m.Matches(&a)); + a.x = -1; + EXPECT_FALSE(m.Matches(&a)); +} + // Tests that Field() does not match the NULL pointer. TEST(FieldForPointerTest, DoesNotMatchNull) { Matcher<const AStruct*> m = Field(&AStruct::x, _); @@ -2572,8 +2764,9 @@ TEST(FieldForPointerTest, WorksForArgumentOfSubType) { TEST(FieldForPointerTest, CanDescribeSelf) { Matcher<const AStruct*> m = Field(&AStruct::x, Ge(0)); - EXPECT_EQ("the given field is greater than or equal to 0", Describe(m)); - EXPECT_EQ("the given field is not greater than or equal to 0", + EXPECT_EQ("is an object whose given field is greater than or equal to 0", + Describe(m)); + EXPECT_EQ("is an object whose given field is not greater than or equal to 0", DescribeNegation(m)); } @@ -2584,10 +2777,11 @@ TEST(FieldForPointerTest, CanExplainMatchResult) { AStruct a; a.x = 1; EXPECT_EQ("", Explain(m, static_cast<const AStruct*>(NULL))); - EXPECT_EQ("", Explain(m, &a)); + EXPECT_EQ("which points to an object whose given field is 1", Explain(m, &a)); m = Field(&AStruct::x, GreaterThan(0)); - EXPECT_EQ("the given field is 1 more than 0", Explain(m, &a)); + EXPECT_EQ("which points to an object whose given field is 1, " + "which is 1 more than 0", Explain(m, &a)); } // A user-defined class for testing Property(). @@ -2706,9 +2900,10 @@ TEST(PropertyTest, WorksForCompatibleMatcherType) { TEST(PropertyTest, CanDescribeSelf) { Matcher<const AClass&> m = Property(&AClass::n, Ge(0)); - EXPECT_EQ("the given property is greater than or equal to 0", Describe(m)); - EXPECT_EQ("the given property is not greater than or equal to 0", - DescribeNegation(m)); + EXPECT_EQ("is an object whose given property is greater than or equal to 0", + Describe(m)); + EXPECT_EQ("is an object whose given property " + "is not greater than or equal to 0", DescribeNegation(m)); } // Tests that Property() can explain the match result. @@ -2717,10 +2912,10 @@ TEST(PropertyTest, CanExplainMatchResult) { AClass a; a.set_n(1); - EXPECT_EQ("", Explain(m, a)); + EXPECT_EQ("whose given property is 1", Explain(m, a)); m = Property(&AClass::n, GreaterThan(0)); - EXPECT_EQ("the given property is 1 more than 0", Explain(m, a)); + EXPECT_EQ("whose given property is 1, which is 1 more than 0", Explain(m, a)); } // Tests that Property() works when the argument is a pointer to const. @@ -2747,6 +2942,19 @@ TEST(PropertyForPointerTest, WorksForPointerToNonConst) { EXPECT_FALSE(m.Matches(&a)); } +// Tests that Property() works when the argument is a reference to a +// const pointer. +TEST(PropertyForPointerTest, WorksForReferenceToConstPointer) { + Matcher<AClass* const&> m = Property(&AClass::s, StartsWith("hi")); + + AClass a; + a.set_s("hill"); + EXPECT_TRUE(m.Matches(&a)); + + a.set_s("hole"); + EXPECT_FALSE(m.Matches(&a)); +} + // Tests that Property() does not match the NULL pointer. TEST(PropertyForPointerTest, WorksForReferenceToNonConstProperty) { Matcher<const AClass*> m = Property(&AClass::x, _); @@ -2772,9 +2980,10 @@ TEST(PropertyForPointerTest, WorksForArgumentOfSubType) { TEST(PropertyForPointerTest, CanDescribeSelf) { Matcher<const AClass*> m = Property(&AClass::n, Ge(0)); - EXPECT_EQ("the given property is greater than or equal to 0", Describe(m)); - EXPECT_EQ("the given property is not greater than or equal to 0", - DescribeNegation(m)); + EXPECT_EQ("is an object whose given property is greater than or equal to 0", + Describe(m)); + EXPECT_EQ("is an object whose given property " + "is not greater than or equal to 0", DescribeNegation(m)); } // Tests that Property() can explain the result of matching a pointer. @@ -2784,10 +2993,12 @@ TEST(PropertyForPointerTest, CanExplainMatchResult) { AClass a; a.set_n(1); EXPECT_EQ("", Explain(m, static_cast<const AClass*>(NULL))); - EXPECT_EQ("", Explain(m, &a)); + EXPECT_EQ("which points to an object whose given property is 1", + Explain(m, &a)); m = Property(&AClass::n, GreaterThan(0)); - EXPECT_EQ("the given property is 1 more than 0", Explain(m, &a)); + EXPECT_EQ("which points to an object whose given property is 1, " + "which is 1 more than 0", Explain(m, &a)); } // Tests ResultOf. @@ -2807,10 +3018,10 @@ TEST(ResultOfTest, WorksForFunctionPointers) { TEST(ResultOfTest, CanDescribeItself) { Matcher<int> matcher = ResultOf(&IntToStringFunction, StrEq("foo")); - EXPECT_EQ("result of the given callable is equal to \"foo\"", - Describe(matcher)); - EXPECT_EQ("result of the given callable is not equal to \"foo\"", - DescribeNegation(matcher)); + EXPECT_EQ("is mapped by the given callable to a value that " + "is equal to \"foo\"", Describe(matcher)); + EXPECT_EQ("is mapped by the given callable to a value that " + "is not equal to \"foo\"", DescribeNegation(matcher)); } // Tests that ResultOf() can explain the match result. @@ -2818,11 +3029,12 @@ int IntFunction(int input) { return input == 42 ? 80 : 90; } TEST(ResultOfTest, CanExplainMatchResult) { Matcher<int> matcher = ResultOf(&IntFunction, Ge(85)); - EXPECT_EQ("", Explain(matcher, 36)); + EXPECT_EQ("which is mapped by the given callable to 90", + Explain(matcher, 36)); matcher = ResultOf(&IntFunction, GreaterThan(85)); - EXPECT_EQ("result of the given callable is 5 more than 85", - Explain(matcher, 36)); + EXPECT_EQ("which is mapped by the given callable to 90, " + "which is 5 more than 85", Explain(matcher, 36)); } // Tests that ResultOf(f, ...) compiles and works as expected when f(x) @@ -2958,8 +3170,11 @@ class DivisibleByImpl { public: explicit DivisibleByImpl(int a_divider) : divider_(a_divider) {} + // For testing using ExplainMatchResultTo() with polymorphic matchers. template <typename T> - bool Matches(const T& n) const { + bool MatchAndExplain(const T& n, MatchResultListener* listener) const { + *listener << "is " << (n % divider_) << " modulo " + << divider_; return (n % divider_) == 0; } @@ -2978,14 +3193,6 @@ class DivisibleByImpl { int divider_; }; -// For testing using ExplainMatchResultTo() with polymorphic matchers. -template <typename T> -void ExplainMatchResultTo(const DivisibleByImpl& impl, const T& n, - ::std::ostream* os) { - *os << "is " << (n % impl.divider()) << " modulo " - << impl.divider(); -} - PolymorphicMatcher<DivisibleByImpl> DivisibleBy(int n) { return MakePolymorphicMatcher(DivisibleByImpl(n)); } @@ -3025,7 +3232,7 @@ TEST(ExplainMatchResultTest, AllOf_True_True_2) { TEST(ExplainmatcherResultTest, MonomorphicMatcher) { const Matcher<int> m = GreaterThan(5); - EXPECT_EQ("is 1 more than 5", Explain(m, 6)); + EXPECT_EQ("which is 1 more than 5", Explain(m, 6)); } // The following two tests verify that values without a public copy @@ -3335,6 +3542,16 @@ TEST(ValidateMatcherDescriptionTest, ElementsAre()); } +// The MATCHER*() macros trigger warning C4100 (unreferenced formal +// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in +// the macro definition, as the warnings are generated when the macro +// is expanded and macro expansion cannot contain #pragma. Therefore +// we suppress them here. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4100) +#endif + // We use MATCHER_P3() to define a matcher for testing // ValidateMatcherDescription(); otherwise we'll end up with much // plumbing code. This is not circular as @@ -3345,6 +3562,10 @@ MATCHER_P3(EqInterpolation, start, end, index, "equals Interpolation%(*)s") { arg.param_index == index; } +#ifdef _MSC_VER +#pragma warning(pop) +#endif + TEST(ValidateMatcherDescriptionTest, AcceptsPercentInterpolation) { const char* params[] = { "foo", NULL }; const char* const desc = "one %%"; diff --git a/testing/gmock/test/gmock-nice-strict_test.cc b/testing/gmock/test/gmock-nice-strict_test.cc index 1d36e03..f6f278e 100644 --- a/testing/gmock/test/gmock-nice-strict_test.cc +++ b/testing/gmock/test/gmock-nice-strict_test.cc @@ -57,6 +57,11 @@ using testing::HasSubstr; using testing::NiceMock; using testing::StrictMock; +#if GTEST_HAS_STREAM_REDIRECTION_ +using testing::internal::CaptureStdout; +using testing::internal::GetCapturedStdout; +#endif // GTEST_HAS_STREAM_REDIRECTION_ + // Defines some mock classes needed by the tests. class Foo { @@ -102,17 +107,16 @@ class MockBar { GTEST_DISALLOW_COPY_AND_ASSIGN_(MockBar); }; -// TODO(wan@google.com): find a way to re-enable these tests. -#if 0 +#if GTEST_HAS_STREAM_REDIRECTION_ // Tests that a nice mock generates no warning for uninteresting calls. TEST(NiceMockTest, NoWarningForUninterestingCall) { NiceMock<MockFoo> nice_foo; - CaptureTestStdout(); + CaptureStdout(); nice_foo.DoThis(); nice_foo.DoThat(true); - EXPECT_EQ("", GetCapturedTestStdout()); + EXPECT_STREQ("", GetCapturedStdout().c_str()); } // Tests that a nice mock generates no warning for uninteresting calls @@ -123,9 +127,9 @@ TEST(NiceMockTest, NoWarningForUninterestingCallAfterDeath) { ON_CALL(*nice_foo, DoThis()) .WillByDefault(Invoke(nice_foo, &MockFoo::Delete)); - CaptureTestStdout(); + CaptureStdout(); nice_foo->DoThis(); - EXPECT_EQ("", GetCapturedTestStdout()); + EXPECT_STREQ("", GetCapturedStdout().c_str()); } // Tests that a nice mock generates informational logs for @@ -134,18 +138,18 @@ TEST(NiceMockTest, InfoForUninterestingCall) { NiceMock<MockFoo> nice_foo; GMOCK_FLAG(verbose) = "info"; - CaptureTestStdout(); + CaptureStdout(); nice_foo.DoThis(); - EXPECT_THAT(GetCapturedTestStdout(), + EXPECT_THAT(GetCapturedStdout(), HasSubstr("Uninteresting mock function call")); - CaptureTestStdout(); + CaptureStdout(); nice_foo.DoThat(true); - EXPECT_THAT(GetCapturedTestStdout(), + EXPECT_THAT(GetCapturedStdout(), HasSubstr("Uninteresting mock function call")); } -#endif // 0 +#endif // GTEST_HAS_STREAM_REDIRECTION_ // Tests that a nice mock allows expected calls. TEST(NiceMockTest, AllowsExpectedCall) { diff --git a/testing/gmock/test/gmock-printers_test.cc b/testing/gmock/test/gmock-printers_test.cc index 0553e9c..92c8413 100644 --- a/testing/gmock/test/gmock-printers_test.cc +++ b/testing/gmock/test/gmock-printers_test.cc @@ -153,6 +153,7 @@ using ::std::tr1::make_tuple; using ::std::tr1::tuple; using ::std::vector; using ::testing::ElementsAre; +using ::testing::PrintToString; using ::testing::StartsWith; using ::testing::internal::NativeArray; using ::testing::internal::Strings; @@ -1010,19 +1011,24 @@ TEST(PrintReferenceTest, HandlesMemberVariablePointer) { + " " + Print(sizeof(p)) + "-byte object ")); } -TEST(PrintToStringTest, WorksForNonReference) { - EXPECT_EQ("123", UniversalPrinter<int>::PrintToString(123)); +TEST(PrintToStringTest, WorksForScalar) { + EXPECT_EQ("123", PrintToString(123)); } -TEST(PrintToStringTest, WorksForReference) { - int n = 123; - EXPECT_EQ("@" + PrintPointer(&n) + " 123", - UniversalPrinter<const int&>::PrintToString(n)); +TEST(PrintToStringTest, WorksForPointerToConstChar) { + const char* p = "hello"; + EXPECT_EQ("\"hello\"", PrintToString(p)); +} + +TEST(PrintToStringTest, WorksForPointerToNonConstChar) { + char s[] = "hello"; + char* p = s; + EXPECT_EQ("\"hello\"", PrintToString(p)); } TEST(PrintToStringTest, WorksForArray) { int n[3] = { 1, 2, 3 }; - EXPECT_EQ("{ 1, 2, 3 }", UniversalPrinter<int[3]>::PrintToString(n)); + EXPECT_EQ("{ 1, 2, 3 }", PrintToString(n)); } TEST(UniversalTersePrintTest, WorksForNonReference) { diff --git a/testing/gmock/test/gmock-spec-builders_test.cc b/testing/gmock/test/gmock-spec-builders_test.cc index c1e7738..e5fc2ec 100644 --- a/testing/gmock/test/gmock-spec-builders_test.cc +++ b/testing/gmock/test/gmock-spec-builders_test.cc @@ -68,6 +68,7 @@ using testing::AtMost; using testing::Between; using testing::Cardinality; using testing::CardinalityInterface; +using testing::ContainsRegex; using testing::Const; using testing::DoAll; using testing::DoDefault; @@ -86,13 +87,20 @@ using testing::Mock; using testing::Ne; using testing::Return; using testing::Sequence; +using testing::internal::ExpectationTester; using testing::internal::g_gmock_mutex; using testing::internal::kErrorVerbosity; using testing::internal::kInfoVerbosity; using testing::internal::kWarningVerbosity; -using testing::internal::ExpectationTester; +using testing::internal::String; using testing::internal::string; +#if GTEST_HAS_STREAM_REDIRECTION_ +using testing::HasSubstr; +using testing::internal::CaptureStdout; +using testing::internal::GetCapturedStdout; +#endif // GTEST_HAS_STREAM_REDIRECTION_ + class Result {}; class MockA { @@ -510,13 +518,12 @@ TEST(ExpectCallSyntaxTest, DefaultCardinalityIsOnce) { }, "to be called once"); } -// TODO(wan@google.com): find a way to re-enable these tests. -#if 0 +#if GTEST_HAS_STREAM_REDIRECTION_ // Tests that Google Mock doesn't print a warning when the number of // WillOnce() is adequate. TEST(ExpectCallSyntaxTest, DoesNotWarnOnAdequateActionCount) { - CaptureTestStdout(); + CaptureStdout(); { MockB b; @@ -546,14 +553,13 @@ TEST(ExpectCallSyntaxTest, DoesNotWarnOnAdequateActionCount) { b.DoB(2); b.DoB(3); } - const string& output = GetCapturedTestStdout(); - EXPECT_EQ("", output); + EXPECT_STREQ("", GetCapturedStdout().c_str()); } // Tests that Google Mock warns on having too many actions in an // expectation compared to its cardinality. TEST(ExpectCallSyntaxTest, WarnsOnTooManyActions) { - CaptureTestStdout(); + CaptureStdout(); { MockB b; @@ -585,7 +591,7 @@ TEST(ExpectCallSyntaxTest, WarnsOnTooManyActions) { b.DoB(1); b.DoB(2); } - const string& output = GetCapturedTestStdout(); + const String output = GetCapturedStdout(); EXPECT_PRED_FORMAT2( IsSubstring, "Too many actions specified in EXPECT_CALL(b, DoB())...\n" @@ -625,9 +631,9 @@ TEST(ExpectCallSyntaxTest, WarnsOnTooFewActions) { .Times(Between(2, 3)) .WillOnce(Return(1)); - CaptureTestStdout(); + CaptureStdout(); b.DoB(); - const string& output = GetCapturedTestStdout(); + const String output = GetCapturedStdout(); EXPECT_PRED_FORMAT2( IsSubstring, "Too few actions specified in EXPECT_CALL(b, DoB())...\n" @@ -637,7 +643,7 @@ TEST(ExpectCallSyntaxTest, WarnsOnTooFewActions) { b.DoB(); } -#endif // 0 +#endif // GTEST_HAS_STREAM_REDIRECTION_ // Tests the semantics of ON_CALL(). @@ -791,8 +797,7 @@ TEST(ExpectCallTest, NthMatchTakesNthAction) { EXPECT_EQ(3, b.DoB()); } -// TODO(wan@google.com): find a way to re-enable these tests. -#if 0 +#if GTEST_HAS_STREAM_REDIRECTION_ // Tests that the default action is taken when the WillOnce(...) list is // exhausted and there is no WillRepeatedly(). @@ -805,29 +810,29 @@ TEST(ExpectCallTest, TakesDefaultActionWhenWillListIsExhausted) { .WillOnce(Return(1)) .WillOnce(Return(2)); - CaptureTestStdout(); + CaptureStdout(); EXPECT_EQ(0, b.DoB(1)); // Shouldn't generate a warning as the // expectation has no action clause at all. EXPECT_EQ(1, b.DoB()); EXPECT_EQ(2, b.DoB()); - const string& output1 = GetCapturedTestStdout(); - EXPECT_EQ("", output1); + const String output1 = GetCapturedStdout(); + EXPECT_STREQ("", output1.c_str()); - CaptureTestStdout(); + CaptureStdout(); EXPECT_EQ(0, b.DoB()); EXPECT_EQ(0, b.DoB()); - const string& output2 = GetCapturedTestStdout(); - EXPECT_PRED2(RE::PartialMatch, output2, - "Actions ran out\\.\n" - "Called 3 times, but only 2 WillOnce\\(\\)s are specified - " - "returning default value\\."); - EXPECT_PRED2(RE::PartialMatch, output2, - "Actions ran out\\.\n" - "Called 4 times, but only 2 WillOnce\\(\\)s are specified - " - "returning default value\\."); + const String output2 = GetCapturedStdout(); + EXPECT_THAT(output2.c_str(), + HasSubstr("Actions ran out in EXPECT_CALL(b, DoB())...\n" + "Called 3 times, but only 2 WillOnce()s are specified" + " - returning default value.")); + EXPECT_THAT(output2.c_str(), + HasSubstr("Actions ran out in EXPECT_CALL(b, DoB())...\n" + "Called 4 times, but only 2 WillOnce()s are specified" + " - returning default value.")); } -#endif // 0 +#endif // GTEST_HAS_STREAM_REDIRECTION_ // Tests that the WillRepeatedly() action is taken when the WillOnce(...) // list is exhausted. @@ -978,8 +983,6 @@ TEST(UnexpectedCallTest, UnmatchedArguments) { b.DoB(1); } -#ifdef GMOCK_HAS_REGEX - // Tests that Google Mock explains that an expectation with // unsatisfied pre-requisites doesn't match the call. TEST(UnexpectedCallTest, UnsatisifiedPrerequisites) { @@ -1010,31 +1013,33 @@ TEST(UnexpectedCallTest, UnsatisifiedPrerequisites) { // Verifies that the failure message contains the two unsatisfied // pre-requisites but not the satisfied one. - const char* const pattern = -#if GMOCK_USES_PCRE +#if GTEST_USES_PCRE + EXPECT_THAT(r.message(), ContainsRegex( // PCRE has trouble using (.|\n) to match any character, but // supports the (?s) prefix for using . to match any character. "(?s)the following immediate pre-requisites are not satisfied:\n" ".*: pre-requisite #0\n" - ".*: pre-requisite #1"; -#else + ".*: pre-requisite #1")); +#elif GTEST_USES_POSIX_RE + EXPECT_THAT(r.message(), ContainsRegex( // POSIX RE doesn't understand the (?s) prefix, but has no trouble // with (.|\n). "the following immediate pre-requisites are not satisfied:\n" "(.|\n)*: pre-requisite #0\n" - "(.|\n)*: pre-requisite #1"; -#endif // GMOCK_USES_PCRE + "(.|\n)*: pre-requisite #1")); +#else + // We can only use Google Test's own simple regex. + EXPECT_THAT(r.message(), ContainsRegex( + "the following immediate pre-requisites are not satisfied:")); + EXPECT_THAT(r.message(), ContainsRegex(": pre-requisite #0")); + EXPECT_THAT(r.message(), ContainsRegex(": pre-requisite #1")); +#endif // GTEST_USES_PCRE - EXPECT_TRUE( - ::testing::internal::RE::PartialMatch(r.message(), pattern)) - << " where the message is " << r.message(); b.DoB(1); b.DoB(3); b.DoB(4); } -#endif // GMOCK_HAS_REGEX - TEST(UndefinedReturnValueTest, ReturnValueIsMandatory) { MockA a; // TODO(wan@google.com): We should really verify the output message, @@ -1778,16 +1783,15 @@ class MockC { GTEST_DISALLOW_COPY_AND_ASSIGN_(MockC); }; -// TODO(wan@google.com): find a way to re-enable these tests. -#if 0 +#if GTEST_HAS_STREAM_REDIRECTION_ // Tests that an uninteresting mock function call generates a warning // containing the stack trace. TEST(FunctionCallMessageTest, UninterestingCallGeneratesFyiWithStackTrace) { MockC c; - CaptureTestStdout(); + CaptureStdout(); c.VoidMethod(false, 5, "Hi", NULL, Printable(), Unprintable()); - const string& output = GetCapturedTestStdout(); + const String output = GetCapturedStdout(); EXPECT_PRED_FORMAT2(IsSubstring, "GMOCK WARNING", output); EXPECT_PRED_FORMAT2(IsSubstring, "Stack trace:", output); #ifndef NDEBUG @@ -1796,14 +1800,14 @@ TEST(FunctionCallMessageTest, UninterestingCallGeneratesFyiWithStackTrace) { // Verifies that a void mock function's name appears in the stack // trace. - EXPECT_PRED_FORMAT2(IsSubstring, "::MockC::VoidMethod(", output); + EXPECT_PRED_FORMAT2(IsSubstring, "VoidMethod(", output); // Verifies that a non-void mock function's name appears in the // stack trace. - CaptureTestStdout(); + CaptureStdout(); c.NonVoidMethod(); - const string& output2 = GetCapturedTestStdout(); - EXPECT_PRED_FORMAT2(IsSubstring, "::MockC::NonVoidMethod(", output2); + const String output2 = GetCapturedStdout(); + EXPECT_PRED_FORMAT2(IsSubstring, "NonVoidMethod(", output2); #endif // NDEBUG } @@ -1812,26 +1816,27 @@ TEST(FunctionCallMessageTest, UninterestingCallGeneratesFyiWithStackTrace) { TEST(FunctionCallMessageTest, UninterestingCallPrintsArgumentsAndReturnValue) { // A non-void mock function. MockB b; - CaptureTestStdout(); + CaptureStdout(); b.DoB(); - const string& output1 = GetCapturedTestStdout(); + const String output1 = GetCapturedStdout(); EXPECT_PRED_FORMAT2( IsSubstring, "Uninteresting mock function call - returning default value.\n" " Function call: DoB()\n" - " Returns: 0\n", output1); + " Returns: 0\n", output1.c_str()); // Makes sure the return value is printed. // A void mock function. MockC c; - CaptureTestStdout(); + CaptureStdout(); c.VoidMethod(false, 5, "Hi", NULL, Printable(), Unprintable()); - const string& output2 = GetCapturedTestStdout(); - EXPECT_PRED2(RE::PartialMatch, output2, - "Uninteresting mock function call - returning directly\\.\n" - " Function call: VoidMethod" - "\\(false, 5, \"Hi\", NULL, @0x\\w+ " - "Printable, 4-byte object <0000 0000>\\)"); + const String output2 = GetCapturedStdout(); + EXPECT_THAT(output2.c_str(), + ContainsRegex( + "Uninteresting mock function call - returning directly\\.\n" + " Function call: VoidMethod" + "\\(false, 5, \"Hi\", NULL, @.+ " + "Printable, 4-byte object <0000 0000>\\)")); // A void function has no return value to print. } @@ -1843,18 +1848,21 @@ class GMockVerboseFlagTest : public testing::Test { // should_print is true, the output should match the given regex and // contain the given function name in the stack trace. When it's // false, the output should be empty.) - void VerifyOutput(const string& output, bool should_print, - const string& regex, + void VerifyOutput(const String& output, bool should_print, + const string& expected_substring, const string& function_name) { if (should_print) { - EXPECT_PRED2(RE::PartialMatch, output, regex); + EXPECT_THAT(output.c_str(), HasSubstr(expected_substring)); #ifndef NDEBUG // We check the stack trace content in dbg-mode only, as opt-mode // may inline the call we are interested in seeing. - EXPECT_PRED_FORMAT2(IsSubstring, function_name, output); + EXPECT_THAT(output.c_str(), HasSubstr(function_name)); +#else + // Suppresses 'unused function parameter' warnings. + static_cast<void>(function_name); #endif // NDEBUG } else { - EXPECT_EQ("", output); + EXPECT_STREQ("", output.c_str()); } } @@ -1866,27 +1874,27 @@ class GMockVerboseFlagTest : public testing::Test { .WillOnce(Return(true)); // A void-returning function. - CaptureTestStdout(); + CaptureStdout(); a.DoA(5); VerifyOutput( - GetCapturedTestStdout(), + GetCapturedStdout(), should_print, - "Expected mock function call\\.\n" - " Function call: DoA\\(5\\)\n" - "Stack trace:", - "MockA::DoA"); + "Mock function call matches EXPECT_CALL(a, DoA(5))...\n" + " Function call: DoA(5)\n" + "Stack trace:\n", + "DoA"); // A non-void-returning function. - CaptureTestStdout(); + CaptureStdout(); a.Binary(2, 1); VerifyOutput( - GetCapturedTestStdout(), + GetCapturedStdout(), should_print, - "Expected mock function call\\.\n" - " Function call: Binary\\(2, 1\\)\n" + "Mock function call matches EXPECT_CALL(a, Binary(_, 1))...\n" + " Function call: Binary(2, 1)\n" " Returns: true\n" - "Stack trace:", - "MockA::Binary"); + "Stack trace:\n", + "Binary"); } // Tests how the flag affects uninteresting calls. @@ -1894,31 +1902,29 @@ class GMockVerboseFlagTest : public testing::Test { MockA a; // A void-returning function. - CaptureTestStdout(); + CaptureStdout(); a.DoA(5); VerifyOutput( - GetCapturedTestStdout(), + GetCapturedStdout(), should_print, "\nGMOCK WARNING:\n" - "Uninteresting mock function call - returning directly\\.\n" - " Function call: DoA\\(5\\)\n" - "Stack trace:\n" - "[\\s\\S]*", - "MockA::DoA"); + "Uninteresting mock function call - returning directly.\n" + " Function call: DoA(5)\n" + "Stack trace:\n", + "DoA"); // A non-void-returning function. - CaptureTestStdout(); + CaptureStdout(); a.Binary(2, 1); VerifyOutput( - GetCapturedTestStdout(), + GetCapturedStdout(), should_print, "\nGMOCK WARNING:\n" - "Uninteresting mock function call - returning default value\\.\n" - " Function call: Binary\\(2, 1\\)\n" + "Uninteresting mock function call - returning default value.\n" + " Function call: Binary(2, 1)\n" " Returns: false\n" - "Stack trace:\n" - "[\\s\\S]*", - "MockA::Binary"); + "Stack trace:\n", + "Binary"); } }; @@ -1954,7 +1960,7 @@ TEST_F(GMockVerboseFlagTest, InvalidFlagIsTreatedAsWarning) { TestUninterestingCall(true); } -#endif // 0 +#endif // GTEST_HAS_STREAM_REDIRECTION_ // 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 diff --git a/testing/gmock/test/gmock_all_test.cc b/testing/gmock/test/gmock_all_test.cc new file mode 100644 index 0000000..7361259 --- /dev/null +++ b/testing/gmock/test/gmock_all_test.cc @@ -0,0 +1,49 @@ +// Copyright 2009, 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: wan@google.com (Zhanyong Wan) +// +// Tests for Google C++ Mocking Framework (Google Mock) +// +// Sometimes it's desirable to build most of Google Mock's own tests +// by compiling a single file. This file serves this purpose. +#include "test/gmock-actions_test.cc" +#include "test/gmock-cardinalities_test.cc" +#include "test/gmock-generated-actions_test.cc" +#include "test/gmock-generated-function-mockers_test.cc" +#include "test/gmock-generated-internal-utils_test.cc" +#include "test/gmock-generated-matchers_test.cc" +#include "test/gmock-internal-utils_test.cc" +#include "test/gmock-matchers_test.cc" +#include "test/gmock-more-actions_test.cc" +#include "test/gmock-nice-strict_test.cc" +#include "test/gmock-port_test.cc" +#include "test/gmock-printers_test.cc" +#include "test/gmock-spec-builders_test.cc" +#include "test/gmock_test.cc" diff --git a/testing/gmock/test/gmock_link_test.h b/testing/gmock/test/gmock_link_test.h index d963590..aa9aab3 100644 --- a/testing/gmock/test/gmock_link_test.h +++ b/testing/gmock/test/gmock_link_test.h @@ -185,10 +185,8 @@ using testing::SetErrnoAndReturn; using testing::Throw; #endif -#if GMOCK_HAS_REGEX using testing::ContainsRegex; using testing::MatchesRegex; -#endif class Interface { public: @@ -547,7 +545,6 @@ TEST(LinkTest, TestMatchersFloatingPoint) { .WillByDefault(Return()); } -#if GMOCK_HAS_REGEX // Tests the linkage of the ContainsRegex matcher. TEST(LinkTest, TestMatcherContainsRegex) { Mock mock; @@ -561,7 +558,6 @@ TEST(LinkTest, TestMatcherMatchesRegex) { ON_CALL(mock, VoidFromString(MatchesRegex(".*"))).WillByDefault(Return()); } -#endif // GMOCK_HAS_REGEX // Tests the linkage of the StartsWith, EndsWith, and HasSubstr matchers. TEST(LinkTest, TestMatchersSubstrings) { |