From e35fdd936d133bf8a48de140a3c666897588a053 Mon Sep 17 00:00:00 2001 From: shiqian Date: Wed, 10 Dec 2008 05:08:54 +0000 Subject: Initial drop of Google Mock. The files are incomplete and thus may not build correctly yet. --- src/gmock-all.cc | 43 ++++++ src/gmock-cardinalities.cc | 155 ++++++++++++++++++++ src/gmock-internal-utils.cc | 135 ++++++++++++++++++ src/gmock-matchers.cc | 61 ++++++++ src/gmock-printers.cc | 309 ++++++++++++++++++++++++++++++++++++++++ src/gmock-spec-builders.cc | 337 ++++++++++++++++++++++++++++++++++++++++++++ src/gmock.cc | 155 ++++++++++++++++++++ src/gmock_main.cc | 43 ++++++ 8 files changed, 1238 insertions(+) create mode 100644 src/gmock-all.cc create mode 100644 src/gmock-cardinalities.cc create mode 100644 src/gmock-internal-utils.cc create mode 100644 src/gmock-matchers.cc create mode 100644 src/gmock-printers.cc create mode 100644 src/gmock-spec-builders.cc create mode 100644 src/gmock.cc create mode 100644 src/gmock_main.cc (limited to 'src') diff --git a/src/gmock-all.cc b/src/gmock-all.cc new file mode 100644 index 00000000..a14c397d --- /dev/null +++ b/src/gmock-all.cc @@ -0,0 +1,43 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// Google C++ Mocking Framework (Google Mock) +// +// This file #includes all Google Mock implementation .cc files. The +// purpose is to allow a user to build Google Mock by compiling this +// file alone. + +#include "src/gmock-cardinalities.cc" +#include "src/gmock-internal-utils.cc" +#include "src/gmock-matchers.cc" +#include "src/gmock-printers.cc" +#include "src/gmock-spec-builders.cc" +#include "src/gmock.cc" diff --git a/src/gmock-cardinalities.cc b/src/gmock-cardinalities.cc new file mode 100644 index 00000000..07eed469 --- /dev/null +++ b/src/gmock-cardinalities.cc @@ -0,0 +1,155 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements cardinalities. + +#include + +#include +#include // NOLINT +#include +#include +#include +#include + +namespace testing { + +namespace { + +// Implements the Between(m, n) cardinality. +class BetweenCardinalityImpl : public CardinalityInterface { + public: + BetweenCardinalityImpl(int min, int max) + : min_(min >= 0 ? min : 0), + max_(max >= min_ ? max : min_) { + std::stringstream ss; + if (min < 0) { + ss << "The invocation lower bound must be >= 0, " + << "but is actually " << min << "."; + internal::Expect(false, __FILE__, __LINE__, ss.str()); + } else if (max < 0) { + ss << "The invocation upper bound must be >= 0, " + << "but is actually " << max << "."; + internal::Expect(false, __FILE__, __LINE__, ss.str()); + } else if (min > max) { + ss << "The invocation upper bound (" << max + << ") must be >= the invocation lower bound (" << min + << ")."; + internal::Expect(false, __FILE__, __LINE__, ss.str()); + } + } + + // Conservative estimate on the lower/upper bound of the number of + // calls allowed. + virtual int ConservativeLowerBound() const { return min_; } + virtual int ConservativeUpperBound() const { return max_; } + + virtual bool IsSatisfiedByCallCount(int call_count) const { + return min_ <= call_count && call_count <= max_ ; + } + + virtual bool IsSaturatedByCallCount(int call_count) const { + return call_count >= max_; + } + + virtual void DescribeTo(::std::ostream* os) const; + private: + const int min_; + const int max_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(BetweenCardinalityImpl); +}; + +// Formats "n times" in a human-friendly way. +inline internal::string FormatTimes(int n) { + if (n == 1) { + return "once"; + } else if (n == 2) { + return "twice"; + } else { + std::stringstream ss; + ss << n << " times"; + return ss.str(); + } +} + +// Describes the Between(m, n) cardinality in human-friendly text. +void BetweenCardinalityImpl::DescribeTo(::std::ostream* os) const { + if (min_ == 0) { + if (max_ == 0) { + *os << "never called"; + } else if (max_ == INT_MAX) { + *os << "called any number of times"; + } else { + *os << "called at most " << FormatTimes(max_); + } + } else if (min_ == max_) { + *os << "called " << FormatTimes(min_); + } else if (max_ == INT_MAX) { + *os << "called at least " << FormatTimes(min_); + } else { + // 0 < min_ < max_ < INT_MAX + *os << "called between " << min_ << " and " << max_ << " times"; + } +} + +} // Unnamed namespace + +// Describes the given call count to an ostream. +void Cardinality::DescribeActualCallCountTo(int actual_call_count, + ::std::ostream* os) { + if (actual_call_count > 0) { + *os << "called " << FormatTimes(actual_call_count); + } else { + *os << "never called"; + } +} + +// Creates a cardinality that allows at least n calls. +Cardinality AtLeast(int n) { return Between(n, INT_MAX); } + +// Creates a cardinality that allows at most n calls. +Cardinality AtMost(int n) { return Between(0, n); } + +// Creates a cardinality that allows any number of calls. +Cardinality AnyNumber() { return AtLeast(0); } + +// Creates a cardinality that allows between min and max calls. +Cardinality Between(int min, int max) { + return Cardinality(new BetweenCardinalityImpl(min, max)); +} + +// Creates a cardinality that allows exactly n calls. +Cardinality Exactly(int n) { return Between(n, n); } + +} // namespace testing diff --git a/src/gmock-internal-utils.cc b/src/gmock-internal-utils.cc new file mode 100644 index 00000000..58bc64e4 --- /dev/null +++ b/src/gmock-internal-utils.cc @@ -0,0 +1,135 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Mock - a framework for writing C++ mock classes. +// +// This file defines some utilities useful for implementing Google +// Mock. They are subject to change without notice, so please DO NOT +// USE THEM IN USER CODE. + +#include + +#include // NOLINT +#include +#include +#include +#include + +namespace testing { +namespace internal { + +// This class reports Google Mock failures as Google Test failures. A +// user can define another class in a similar fashion if he intends to +// use Google Mock with a testing framework other than Google Test. +class GoogleTestFailureReporter : public FailureReporterInterface { + public: + virtual void ReportFailure(FailureType type, const char* file, int line, + const string& message) { + AssertHelper(type == FATAL ? TPRT_FATAL_FAILURE : TPRT_NONFATAL_FAILURE, + file, line, message.c_str()) = Message(); + if (type == FATAL) { + abort(); + } + } +}; + +// Returns the global failure reporter. Will create a +// GoogleTestFailureReporter and return it the first time called. +FailureReporterInterface* GetFailureReporter() { + // Points to the global failure reporter used by Google Mock. gcc + // guarantees that the following use of failure_reporter is + // thread-safe. We may need to add additional synchronization to + // protect failure_reporter if we port Google Mock to other + // compilers. + static FailureReporterInterface* const failure_reporter = + new GoogleTestFailureReporter(); + return failure_reporter; +} + +// Protects global resources (stdout in particular) used by Log(). +static Mutex g_log_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX); + +// Prints the given message to stdout iff 'severity' >= the level +// specified by the --gmock_verbose flag. If stack_frames_to_skip >= +// 0, also prints the stack trace excluding the top +// stack_frames_to_skip frames. In opt mode, any positive +// stack_frames_to_skip is treated as 0, since we don't know which +// function calls will be inlined by the compiler and need to be +// conservative. +void Log(LogSeverity severity, const string& message, + int stack_frames_to_skip) { + if (GMOCK_FLAG(verbose) == kErrorVerbosity) { + // The user is not interested in logs. + return; + } else if (GMOCK_FLAG(verbose) != kInfoVerbosity) { + // The user is interested in warnings but not informational logs. + // Note that invalid values of GMOCK_FLAG(verbose) are treated as + // "warning", which is the default value of the flag. + if (severity == INFO) { + return; + } + } + + // Ensures that logs from different threads don't interleave. + MutexLock l(&g_log_mutex); + using ::std::cout; + if (severity == WARNING) { + // Prints a GMOCK WARNING marker to make the warnings easily searchable. + cout << "\nGMOCK WARNING:"; + } + // Pre-pends a new-line to message if it doesn't start with one. + if (message.empty() || message[0] != '\n') { + cout << "\n"; + } + cout << message; + if (stack_frames_to_skip >= 0) { +#ifdef NDEBUG + // In opt mode, we have to be conservative and skip no stack frame. + const int actual_to_skip = 0; +#else + // In dbg mode, we can do what the caller tell us to do (plus one + // for skipping this function's stack frame). + const int actual_to_skip = stack_frames_to_skip + 1; +#endif // NDEBUG + + // Appends a new-line to message if it doesn't end with one. + if (!message.empty() && *message.rbegin() != '\n') { + cout << "\n"; + } + cout << "Stack trace:\n" + << ::testing::internal::GetCurrentOsStackTraceExceptTop( + ::testing::UnitTest::GetInstance(), actual_to_skip); + } + cout << ::std::flush; +} + +} // namespace internal +} // namespace testing diff --git a/src/gmock-matchers.cc b/src/gmock-matchers.cc new file mode 100644 index 00000000..99fd3a2d --- /dev/null +++ b/src/gmock-matchers.cc @@ -0,0 +1,61 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements the Matcher and +// Matcher. + +#include + +namespace testing { + +// Constructs a matcher that matches a const string& whose value is +// equal to s. +Matcher::Matcher(const internal::string& s) { + *this = Eq(s); +} + +// Constructs a matcher that matches a const string& whose value is +// equal to s. +Matcher::Matcher(const char* s) { + *this = Eq(internal::string(s)); +} + +// Constructs a matcher that matches a string whose value is equal to s. +Matcher::Matcher(const internal::string& s) { *this = Eq(s); } + +// Constructs a matcher that matches a string whose value is equal to s. +Matcher::Matcher(const char* s) { + *this = Eq(internal::string(s)); +} + +} // namespace testing diff --git a/src/gmock-printers.cc b/src/gmock-printers.cc new file mode 100644 index 00000000..611d8659 --- /dev/null +++ b/src/gmock-printers.cc @@ -0,0 +1,309 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// It uses the << operator when possible, and prints the bytes in the +// object otherwise. A user can override its behavior for a class +// type Foo by defining either operator<<(::std::ostream&, const Foo&) +// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that +// defines Foo. + +#include +#include +#include +#include // NOLINT +#include +#include + +namespace testing { + +namespace { + +using ::std::ostream; + +#ifdef GTEST_OS_WINDOWS +#define snprintf _snprintf_s +#endif + +// Prints a segment of bytes in the given object. +void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, + size_t count, ostream* os) { + char text[5] = ""; + for (size_t i = 0; i != count; i++) { + const size_t j = start + i; + if (i != 0) { + // Organizes the bytes into groups of 2 for easy parsing by + // human. + if ((j % 2) == 0) { + *os << " "; + } + } + snprintf(text, sizeof(text), "%02X", obj_bytes[j]); + *os << text; + } +} + +// Prints the bytes in the given value to the given ostream. +void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, + ostream* os) { + // Tells the user how big the object is. + *os << count << "-byte object <"; + + const size_t kThreshold = 132; + const size_t kChunkSize = 64; + // If the object size is bigger than kThreshold, we'll have to omit + // some details by printing only the first and the last kChunkSize + // bytes. + // TODO(wan): let the user control the threshold using a flag. + if (count < kThreshold) { + PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); + } else { + PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os); + *os << " ... "; + // Rounds up to 2-byte boundary. + const size_t resume_pos = (count - kChunkSize + 1)/2*2; + PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os); + } + *os << ">"; +} + +} // namespace + +namespace internal2 { + +// Delegates to PrintBytesInObjectToImpl() to print the bytes in the +// given object. The delegation simplifies the implementation, which +// uses the << operator and thus is easier done outside of the +// ::testing::internal namespace, which contains a << operator that +// sometimes conflicts with the one in STL. +void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, + ostream* os) { + PrintBytesInObjectToImpl(obj_bytes, count, os); +} + +} // namespace internal2 + +namespace internal { + +// Prints a wide char as a char literal without the quotes, escaping it +// when necessary. +static void PrintAsWideCharLiteralTo(wchar_t c, ostream* os) { + switch (c) { + case L'\0': + *os << "\\0"; + break; + case L'\'': + *os << "\\'"; + break; + case L'\?': + *os << "\\?"; + break; + case L'\\': + *os << "\\\\"; + break; + case L'\a': + *os << "\\a"; + break; + case L'\b': + *os << "\\b"; + break; + case L'\f': + *os << "\\f"; + break; + case L'\n': + *os << "\\n"; + break; + case L'\r': + *os << "\\r"; + break; + case L'\t': + *os << "\\t"; + break; + case L'\v': + *os << "\\v"; + break; + default: + // isprint() takes an int and requires it to be either EOF or in + // the range [0, 255]. We check that c is in this range before calling it. + if ((c & 0xFF) == c && isprint(c)) { + *os << static_cast(c); + } else { + // Buffer size enough for the maximum number of digits and \0. + char text[2 * sizeof(unsigned long) + 1] = ""; + snprintf(text, sizeof(text), "%lX", static_cast(c)); + *os << "\\x" << text; + } + } +} + +// Prints a char as if it's part of a string literal, escaping it when +// necessary. +static void PrintAsWideStringLiteralTo(wchar_t c, ostream* os) { + switch (c) { + case L'\'': + *os << "'"; + break; + case L'"': + *os << "\\\""; + break; + default: + PrintAsWideCharLiteralTo(c, os); + } +} + +// Prints a char as a char literal without the quotes, escaping it +// when necessary. +static void PrintAsCharLiteralTo(char c, ostream* os) { + PrintAsWideCharLiteralTo(static_cast(c), os); +} + +// Prints a char as if it's part of a string literal, escaping it when +// necessary. +static void PrintAsStringLiteralTo(char c, ostream* os) { + PrintAsWideStringLiteralTo(static_cast(c), os); +} + +// Prints a char and its code. The '\0' char is printed as "'\\0'", +// other unprintable characters are also properly escaped using the +// standard C++ escape sequence. +void PrintCharTo(char c, int char_code, ostream* os) { + *os << "'"; + PrintAsCharLiteralTo(c, os); + *os << "'"; + if (c != '\0') + *os << " (" << char_code << ")"; +} + +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its decimal code (except for L'\0'). +// The L'\0' char is printed as "L'\\0'". The decimal code is printed +// as signed integer when wchar_t is implemented by the compiler +// as a signed type and is printed as an unsigned integer when wchar_t +// is implemented as an unsigned type. +void PrintTo(wchar_t wc, ostream* os) { + *os << "L'"; + PrintAsWideCharLiteralTo(wc, os); + *os << "'"; + if (wc != L'\0') { + // Type Int64 is used because it provides more storage than wchar_t thus + // when the compiler converts signed or unsigned implementation of wchar_t + // to Int64 it fills higher bits with either zeros or the sign bit + // passing it to operator <<() as either signed or unsigned integer. + *os << " (" << static_cast(wc) << ")"; + } +} + +// Prints the given array of characters to the ostream. +// The array starts at *begin, the length is len, it may include '\0' characters +// and may not be null-terminated. +static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) { + *os << "\""; + for (size_t index = 0; index < len; ++index) { + PrintAsStringLiteralTo(begin[index], os); + } + *os << "\""; +} + +// Prints the given array of wide characters to the ostream. +// The array starts at *begin, the length is len, it may include L'\0' +// characters and may not be null-terminated. +static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len, + ostream* os) { + *os << "L\""; + for (size_t index = 0; index < len; ++index) { + PrintAsWideStringLiteralTo(begin[index], os); + } + *os << "\""; +} + +// Prints the given C string to the ostream. +void PrintTo(const char* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << implicit_cast(s) << " pointing to "; + PrintCharsAsStringTo(s, strlen(s), os); + } +} + +// MSVC compiler can be configured to define whar_t as a typedef +// of unsigned short. Defining an overload for const wchar_t* in that case +// would cause pointers to unsigned shorts be printed as wide strings, +// possibly accessing more memory than intended and causing invalid +// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when +// wchar_t is implemented as a native type. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Prints the given wide C string to the ostream. +void PrintTo(const wchar_t* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << implicit_cast(s) << " pointing to "; + PrintWideCharsAsStringTo(s, wcslen(s), os); + } +} +#endif // wchar_t is native + +// Prints a ::string object. +#if GTEST_HAS_GLOBAL_STRING +void PrintStringTo(const ::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +#if GTEST_HAS_STD_STRING +void PrintStringTo(const ::std::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_STD_STRING + +// Prints a ::wstring object. +#if GTEST_HAS_GLOBAL_WSTRING +void PrintWideStringTo(const ::wstring& s, ostream* os) { + PrintWideCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +void PrintWideStringTo(const ::std::wstring& s, ostream* os) { + PrintWideCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_STD_WSTRING + +} // namespace internal + +} // namespace testing diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc new file mode 100644 index 00000000..353bb2df --- /dev/null +++ b/src/gmock-spec-builders.cc @@ -0,0 +1,337 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements the spec builder syntax (ON_CALL and +// EXPECT_CALL). + +#include + +#include +#include + +namespace testing { +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); + +// Constructs an ExpectationBase object. +ExpectationBase::ExpectationBase(const char* file, int line) + : file_(file), + line_(line), + cardinality_specified_(false), + cardinality_(Exactly(1)), + call_count_(0), + retired_(false) { +} + +// Destructs an ExpectationBase object. +ExpectationBase::~ExpectationBase() {} + +// Explicitly specifies the cardinality of this expectation. Used by +// the subclasses to implement the .Times() clause. +void ExpectationBase::SpecifyCardinality(const Cardinality& cardinality) { + cardinality_specified_ = true; + cardinality_ = cardinality; +} + +// Retires all pre-requisites of this expectation. +void ExpectationBase::RetireAllPreRequisites() { + if (is_retired()) { + // We can take this short-cut as we never retire an expectation + // until we have retired all its pre-requisites. + return; + } + + for (ExpectationBaseSet::const_iterator it = + immediate_prerequisites_.begin(); + it != immediate_prerequisites_.end(); + ++it) { + ExpectationBase* const prerequisite = (*it).get(); + if (!prerequisite->is_retired()) { + prerequisite->RetireAllPreRequisites(); + prerequisite->Retire(); + } + } +} + +// Returns true iff all pre-requisites of this expectation have been +// satisfied. +// L >= g_gmock_mutex +bool ExpectationBase::AllPrerequisitesAreSatisfied() const { + g_gmock_mutex.AssertHeld(); + for (ExpectationBaseSet::const_iterator it = immediate_prerequisites_.begin(); + it != immediate_prerequisites_.end(); ++it) { + if (!(*it)->IsSatisfied() || + !(*it)->AllPrerequisitesAreSatisfied()) + return false; + } + return true; +} + +// Adds unsatisfied pre-requisites of this expectation to 'result'. +// L >= g_gmock_mutex +void ExpectationBase::FindUnsatisfiedPrerequisites( + ExpectationBaseSet* result) const { + g_gmock_mutex.AssertHeld(); + for (ExpectationBaseSet::const_iterator it = immediate_prerequisites_.begin(); + it != immediate_prerequisites_.end(); ++it) { + if ((*it)->IsSatisfied()) { + // If *it is satisfied and has a call count of 0, some of its + // pre-requisites may not be satisfied yet. + if ((*it)->call_count_ == 0) { + (*it)->FindUnsatisfiedPrerequisites(result); + } + } else { + // Now that we know *it is unsatisfied, we are not so interested + // in whether its pre-requisites are satisfied. Therefore we + // don't recursively call FindUnsatisfiedPrerequisites() here. + result->insert(*it); + } + } +} + +// Points to the implicit sequence introduced by a living InSequence +// object (if any) in the current thread or NULL. +ThreadLocal g_gmock_implicit_sequence; + +// Reports an uninteresting call (whose description is in msg) in the +// manner specified by 'reaction'. +void ReportUninterestingCall(CallReaction reaction, const string& msg) { + switch (reaction) { + case ALLOW: + Log(INFO, msg, 4); + break; + case WARN: + Log(WARNING, msg, 4); + break; + default: // FAIL + Expect(false, NULL, -1, msg); + } +} + +} // namespace internal + +// Class Mock. + +namespace { + +typedef std::set FunctionMockers; +typedef std::map MockObjectRegistry; + +// Maps a mock object to the set of mock methods it owns. Protected +// by g_gmock_mutex. +MockObjectRegistry g_mock_object_registry; + +// Maps a mock object to the reaction Google Mock should have when an +// uninteresting method is called. Protected by g_gmock_mutex. +std::map g_uninteresting_call_reaction; + +// Sets the reaction Google Mock should have when an uninteresting +// method of the given mock object is called. +// L < g_gmock_mutex +void SetReactionOnUninterestingCalls(const void* mock_obj, + internal::CallReaction reaction) { + internal::MutexLock l(&internal::g_gmock_mutex); + g_uninteresting_call_reaction[mock_obj] = reaction; +} + +} // namespace + +// Tells Google Mock to allow uninteresting calls on the given mock +// object. +// L < g_gmock_mutex +void Mock::AllowUninterestingCalls(const void* mock_obj) { + SetReactionOnUninterestingCalls(mock_obj, internal::ALLOW); +} + +// Tells Google Mock to warn the user about uninteresting calls on the +// given mock object. +// L < g_gmock_mutex +void Mock::WarnUninterestingCalls(const void* mock_obj) { + SetReactionOnUninterestingCalls(mock_obj, internal::WARN); +} + +// Tells Google Mock to fail uninteresting calls on the given mock +// object. +// L < g_gmock_mutex +void Mock::FailUninterestingCalls(const void* mock_obj) { + SetReactionOnUninterestingCalls(mock_obj, internal::FAIL); +} + +// Tells Google Mock the given mock object is being destroyed and its +// entry in the call-reaction table should be removed. +// L < g_gmock_mutex +void Mock::UnregisterCallReaction(const void* mock_obj) { + internal::MutexLock l(&internal::g_gmock_mutex); + g_uninteresting_call_reaction.erase(mock_obj); +} + +// Returns the reaction Google Mock will have on uninteresting calls +// made on the given mock object. +// L < g_gmock_mutex +internal::CallReaction Mock::GetReactionOnUninterestingCalls( + const void* mock_obj) { + internal::MutexLock l(&internal::g_gmock_mutex); + return (g_uninteresting_call_reaction.count(mock_obj) == 0) ? + internal::WARN : g_uninteresting_call_reaction[mock_obj]; +} + +// Verifies and clears all expectations on the given mock object. If +// the expectations aren't satisfied, generates one or more Google +// Test non-fatal failures and returns false. +// L < g_gmock_mutex +bool Mock::VerifyAndClearExpectations(void* mock_obj) { + internal::MutexLock l(&internal::g_gmock_mutex); + return VerifyAndClearExpectationsLocked(mock_obj); +} + +// Verifies all expectations on the given mock object and clears its +// default actions and expectations. Returns true iff the +// verification was successful. +// L < g_gmock_mutex +bool Mock::VerifyAndClear(void* mock_obj) { + internal::MutexLock l(&internal::g_gmock_mutex); + ClearDefaultActionsLocked(mock_obj); + return VerifyAndClearExpectationsLocked(mock_obj); +} + +// Verifies and clears all expectations on the given mock object. If +// the expectations aren't satisfied, generates one or more Google +// Test non-fatal failures and returns false. +// L >= g_gmock_mutex +bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj) { + internal::g_gmock_mutex.AssertHeld(); + if (g_mock_object_registry.count(mock_obj) == 0) { + // No EXPECT_CALL() was set on the given mock object. + return true; + } + + // Verifies and clears the expectations on each mock method in the + // given mock object. + bool expectations_met = true; + FunctionMockers& mockers = g_mock_object_registry[mock_obj]; + for (FunctionMockers::const_iterator it = mockers.begin(); + it != mockers.end(); ++it) { + if (!(*it)->VerifyAndClearExpectationsLocked()) { + expectations_met = false; + } + } + + // We don't clear the content of mockers, as they may still be + // needed by ClearDefaultActionsLocked(). + return expectations_met; +} + +// Registers a mock object and a mock method it owns. +// L < g_gmock_mutex +void Mock::Register(const void* mock_obj, + internal::UntypedFunctionMockerBase* mocker) { + internal::MutexLock l(&internal::g_gmock_mutex); + g_mock_object_registry[mock_obj].insert(mocker); +} + +// Unregisters a mock method; removes the owning mock object from the +// registry when the last mock method associated with it has been +// unregistered. This is called only in the destructor of +// FunctionMockerBase. +// L >= g_gmock_mutex +void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker) { + internal::g_gmock_mutex.AssertHeld(); + for (MockObjectRegistry::iterator it = g_mock_object_registry.begin(); + it != g_mock_object_registry.end(); ++it) { + FunctionMockers& mockers = it->second; + if (mockers.erase(mocker) > 0) { + // mocker was in mockers and has been just removed. + if (mockers.empty()) { + g_mock_object_registry.erase(it); + } + return; + } + } +} + +// Clears all ON_CALL()s set on the given mock object. +// L >= g_gmock_mutex +void Mock::ClearDefaultActionsLocked(void* mock_obj) { + internal::g_gmock_mutex.AssertHeld(); + + if (g_mock_object_registry.count(mock_obj) == 0) { + // No ON_CALL() was set on the given mock object. + return; + } + + // Clears the default actions for each mock method in the given mock + // object. + FunctionMockers& mockers = g_mock_object_registry[mock_obj]; + for (FunctionMockers::const_iterator it = mockers.begin(); + it != mockers.end(); ++it) { + (*it)->ClearDefaultActionsLocked(); + } + + // We don't clear the content of mockers, as they may still be + // needed by VerifyAndClearExpectationsLocked(). +} + +// Adds an expectation to a sequence. +void Sequence::AddExpectation( + const internal::linked_ptr& expectation) const { + if (*last_expectation_ != expectation) { + if (*last_expectation_ != NULL) { + expectation->immediate_prerequisites_.insert(*last_expectation_); + } + *last_expectation_ = expectation; + } +} + +// Creates the implicit sequence if there isn't one. +InSequence::InSequence() { + if (internal::g_gmock_implicit_sequence.get() == NULL) { + internal::g_gmock_implicit_sequence.set(new Sequence); + sequence_created_ = true; + } else { + sequence_created_ = false; + } +} + +// Deletes the implicit sequence if it was created by the constructor +// of this object. +InSequence::~InSequence() { + if (sequence_created_) { + delete internal::g_gmock_implicit_sequence.get(); + internal::g_gmock_implicit_sequence.set(NULL); + } +} + +} // namespace testing diff --git a/src/gmock.cc b/src/gmock.cc new file mode 100644 index 00000000..b2f3d59d --- /dev/null +++ b/src/gmock.cc @@ -0,0 +1,155 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +#include +#include + +namespace testing { + +GMOCK_DEFINE_string(verbose, internal::kWarningVerbosity, + "Controls how verbose Google Mock's output is." + " Valid values:\n" + " info - prints all messages.\n" + " warning - prints warnings and errors.\n" + " error - prints errors only."); + +namespace internal { + +// Parses a string as a command line flag. The string should have the +// format "--gmock_flag=value". When def_optional is true, the +// "=value" part can be omitted. +// +// Returns the value of the flag, or NULL if the parsing failed. +static const char* ParseGoogleMockFlagValue(const char* str, + const char* flag, + bool def_optional) { + // str and flag must not be NULL. + if (str == NULL || flag == NULL) return NULL; + + // The flag must start with "--gmock_". + const String flag_str = String::Format("--gmock_%s", flag); + const size_t flag_len = flag_str.GetLength(); + if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL; + + // Skips the flag name. + const char* flag_end = str + flag_len; + + // When def_optional is true, it's OK to not have a "=value" part. + if (def_optional && (flag_end[0] == '\0')) { + return flag_end; + } + + // If def_optional is true and there are more characters after the + // flag name, or if def_optional is false, there must be a '=' after + // the flag name. + if (flag_end[0] != '=') return NULL; + + // Returns the string after "=". + return flag_end + 1; +} + +// Parses a string for a Google Mock string flag, in the form of +// "--gmock_flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +static bool ParseGoogleMockStringFlag(const char* str, const char* flag, + String* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseGoogleMockFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Sets *value to the value of the flag. + *value = value_str; + return true; +} + +// The internal implementation of InitGoogleMock(). +// +// The type parameter CharType can be instantiated to either char or +// wchar_t. +template +void InitGoogleMockImpl(int* argc, CharType** argv) { + // Makes sure Google Test is initialized. InitGoogleTest() is + // idempotent, so it's fine if the user has already called it. + InitGoogleTest(argc, argv); + if (*argc <= 0) return; + + for (int i = 1; i != *argc; i++) { + const String arg_string = StreamableToString(argv[i]); + const char* const arg = arg_string.c_str(); + + // Do we see a Google Mock flag? + if (ParseGoogleMockStringFlag(arg, "verbose", &GMOCK_FLAG(verbose))) { + // Yes. Shift the remainder of the argv list left by one. Note + // that argv has (*argc + 1) elements, the last one always being + // NULL. The following loop moves the trailing NULL element as + // well. + for (int j = i; j != *argc; j++) { + argv[j] = argv[j + 1]; + } + + // Decrements the argument count. + (*argc)--; + + // We also need to decrement the iterator as we just removed + // an element. + i--; + } + } +} + +} // namespace internal + +// Initializes Google Mock. This must be called before running the +// tests. In particular, it parses a command line for the flags that +// Google Mock recognizes. Whenever a Google Mock flag is seen, it is +// removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Mock flag variables are +// updated. +// +// Since Google Test is needed for Google Mock to work, this function +// also initializes Google Test and parses its flags, if that hasn't +// been done. +void InitGoogleMock(int* argc, char** argv) { + internal::InitGoogleMockImpl(argc, argv); +} + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +void InitGoogleMock(int* argc, wchar_t** argv) { + internal::InitGoogleMockImpl(argc, argv); +} + +} // namespace testing diff --git a/src/gmock_main.cc b/src/gmock_main.cc new file mode 100644 index 00000000..a97e9532 --- /dev/null +++ b/src/gmock_main.cc @@ -0,0 +1,43 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +#include +#include +#include + +int main(int argc, char **argv) { + std::cout << "Running main() from gmock_main.cc\n"; + // Since Google Mock depends on Google Test, InitGoogleMock() is + // also responsible for initializing Google Test. Therefore there's + // no need for calling testing::InitGoogleTest() separately. + testing::InitGoogleMock(&argc, argv); + return RUN_ALL_TESTS(); +} -- cgit v1.2.3 From ce198ff8997775d63b802615ee0cea5886ab82ab Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Thu, 12 Feb 2009 01:34:27 +0000 Subject: Implements the MATCHER* macros. --- src/gmock-internal-utils.cc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src') diff --git a/src/gmock-internal-utils.cc b/src/gmock-internal-utils.cc index 58bc64e4..735abce5 100644 --- a/src/gmock-internal-utils.cc +++ b/src/gmock-internal-utils.cc @@ -37,6 +37,7 @@ #include +#include #include // NOLINT #include #include @@ -46,6 +47,29 @@ namespace testing { namespace internal { +// Converts an identifier name to a space-separated list of lower-case +// words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is +// treated as one word. For example, both "FooBar123" and +// "foo_bar_123" are converted to "foo bar 123". +string ConvertIdentifierNameToWords(const char* id_name) { + string result; + char prev_char = '\0'; + for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) { + // We don't care about the current locale as the input is + // guaranteed to be a valid C++ identifier name. + const bool starts_new_word = isupper(*p) || + (!isalpha(prev_char) && islower(*p)) || + (!isdigit(prev_char) && isdigit(*p)); + + if (isalnum(*p)) { + if (starts_new_word && result != "") + result += ' '; + result += tolower(*p); + } + } + return result; +} + // This class reports Google Mock failures as Google Test failures. A // user can define another class in a similar fashion if he intends to // use Google Mock with a testing framework other than Google Test. -- cgit v1.2.3 From e0d051ea64dd5f32d5b6af9831747d1acb2a9c40 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Thu, 19 Feb 2009 00:33:37 +0000 Subject: Makes sure all internal macros are named GMOCK_*_. No functionality is changed. --- src/gmock.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/gmock.cc b/src/gmock.cc index b2f3d59d..c017917d 100644 --- a/src/gmock.cc +++ b/src/gmock.cc @@ -34,12 +34,12 @@ namespace testing { -GMOCK_DEFINE_string(verbose, internal::kWarningVerbosity, - "Controls how verbose Google Mock's output is." - " Valid values:\n" - " info - prints all messages.\n" - " warning - prints warnings and errors.\n" - " error - prints errors only."); +GMOCK_DEFINE_string_(verbose, internal::kWarningVerbosity, + "Controls how verbose Google Mock's output is." + " Valid values:\n" + " info - prints all messages.\n" + " warning - prints warnings and errors.\n" + " error - prints errors only."); namespace internal { -- cgit v1.2.3 From 4a5330d3d6e582248dbcf602f70048dc72cc8182 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Thu, 19 Feb 2009 00:36:44 +0000 Subject: Implements custom description string for MATCHER*. --- src/gmock-matchers.cc | 145 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 143 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gmock-matchers.cc b/src/gmock-matchers.cc index 99fd3a2d..79b525d3 100644 --- a/src/gmock-matchers.cc +++ b/src/gmock-matchers.cc @@ -31,10 +31,15 @@ // Google Mock - a framework for writing C++ mock classes. // -// This file implements the Matcher and -// Matcher. +// This file implements Matcher, Matcher, and +// utilities for defining matchers. #include +#include + +#include +#include +#include namespace testing { @@ -58,4 +63,140 @@ Matcher::Matcher(const char* s) { *this = Eq(internal::string(s)); } +namespace internal { + +// Utilities for validating and formatting description strings in the +// MATCHER*() macros. + +// Returns the 0-based index of the given parameter in the +// NULL-terminated parameter array; if the parameter is "*", returns +// kTupleInterpolation; if it's not found in the list, returns +// kInvalidInterpolation. +int GetParamIndex(const char* param_names[], const string& param_name) { + if (param_name == "*") + return kTupleInterpolation; + + for (int i = 0; param_names[i] != NULL; i++) { + if (param_name == param_names[i]) + return i; + } + return kInvalidInterpolation; +} + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +bool SkipPrefix(const char* prefix, const char** pstr) { + const size_t prefix_len = strlen(prefix); + if (strncmp(*pstr, prefix, prefix_len) == 0) { + *pstr += prefix_len; + return true; + } + return false; +} + +// Helper function used by ValidateMatcherDescription() to format +// error messages. +string FormatMatcherDescriptionSyntaxError(const char* description, + const char* error_pos) { + ::std::stringstream ss; + ss << "Syntax error at index " << (error_pos - description) + << " in matcher description \"" << description << "\": "; + return ss.str(); +} + +// Parses a matcher description string and returns a vector of +// interpolations that appear in the string; generates non-fatal +// failures iff 'description' is an invalid matcher description. +// 'param_names' is a NULL-terminated array of parameter names in the +// order they appear in the MATCHER_P*() parameter list. +Interpolations ValidateMatcherDescription( + const char* param_names[], const char* description) { + Interpolations interps; + for (const char* p = description; *p != '\0';) { + if (SkipPrefix("%%", &p)) { + interps.push_back(Interpolation(p - 2, p, kPercentInterpolation)); + } else if (SkipPrefix("%(", &p)) { + const char* const q = strstr(p, ")s"); + if (q == NULL) { + // TODO(wan@google.com): change the source file location in + // the failure to point to where the MATCHER*() macro is used. + ADD_FAILURE() << FormatMatcherDescriptionSyntaxError(description, p - 2) + << "an interpolation must end with \")s\", " + << "but \"" << (p - 2) << "\" does not."; + } else { + const string param_name(p, q); + const int param_index = GetParamIndex(param_names, param_name); + if (param_index == kInvalidInterpolation) { + ADD_FAILURE() << FormatMatcherDescriptionSyntaxError(description, p) + << "\"" << param_name + << "\" is an invalid parameter name."; + } else { + interps.push_back(Interpolation(p - 2, q + 2, param_index)); + p = q + 2; + } + } + } else { + EXPECT_NE(*p, '%') << FormatMatcherDescriptionSyntaxError(description, p) + << "use \"%%\" instead of \"%\" to print \"%\"."; + ++p; + } + } + return interps; +} + +// Joins a vector of strings as if they are fields of a tuple; returns +// the joined string. +string JoinAsTuple(const Strings& fields) { + switch (fields.size()) { + case 0: + return ""; + case 1: + return fields[0]; + default: + string result = "(" + fields[0]; + for (size_t i = 1; i < fields.size(); i++) { + result += ", "; + result += fields[i]; + } + result += ")"; + return result; + } +} + +// Returns the actual matcher description, given the matcher name, +// user-supplied description template string, interpolations in the +// string, and the printed values of the matcher parameters. +string FormatMatcherDescription( + const char* matcher_name, const char* description, + const Interpolations& interp, const Strings& param_values) { + string result; + if (*description == '\0') { + // When the user supplies an empty description, we calculate one + // from the matcher name. + result = ConvertIdentifierNameToWords(matcher_name); + if (param_values.size() >= 1) + result += " " + JoinAsTuple(param_values); + } else { + // The end position of the last interpolation. + const char* last_interp_end = description; + for (size_t i = 0; i < interp.size(); i++) { + result.append(last_interp_end, interp[i].start_pos); + const int param_index = interp[i].param_index; + if (param_index == kTupleInterpolation) { + result += JoinAsTuple(param_values); + } else if (param_index == kPercentInterpolation) { + result += '%'; + } else if (param_index != kInvalidInterpolation) { + result += param_values[param_index]; + } + last_interp_end = interp[i].end_pos; + } + result += last_interp_end; + } + + return result; +} + +} // namespace internal } // namespace testing -- cgit v1.2.3 From 652540a278e56528e576f9ea77515f386698a326 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Mon, 23 Feb 2009 23:37:29 +0000 Subject: Cleans up macro definitions. --- src/gmock-printers.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gmock-printers.cc b/src/gmock-printers.cc index 611d8659..495717dc 100644 --- a/src/gmock-printers.cc +++ b/src/gmock-printers.cc @@ -55,7 +55,7 @@ namespace { using ::std::ostream; -#ifdef GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS #define snprintf _snprintf_s #endif -- cgit v1.2.3 From 5b5d62f19019a398167df1f1b59279e049bf24ce Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Wed, 11 Mar 2009 23:37:56 +0000 Subject: Makes the code compile on Windows CE. --- src/gmock-printers.cc | 12 ++++++++---- src/gmock_main.cc | 13 ++++++++++++- 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/gmock-printers.cc b/src/gmock-printers.cc index 495717dc..e6d4001a 100644 --- a/src/gmock-printers.cc +++ b/src/gmock-printers.cc @@ -55,7 +55,9 @@ namespace { using ::std::ostream; -#if GTEST_OS_WINDOWS +#ifdef _WIN32_WCE +#define snprintf _snprintf +#elif GTEST_OS_WINDOWS #define snprintf _snprintf_s #endif @@ -157,9 +159,11 @@ static void PrintAsWideCharLiteralTo(wchar_t c, ostream* os) { *os << "\\v"; break; default: - // isprint() takes an int and requires it to be either EOF or in - // the range [0, 255]. We check that c is in this range before calling it. - if ((c & 0xFF) == c && isprint(c)) { + // Checks whether c is printable or not. Printable characters are in + // the range [0x20,0x7E]. + // We test the value of c directly instead of calling isprint(), as + // isprint() is buggy on Windows mobile. + if (0x20 <= c && c <= 0x7E) { *os << static_cast(c); } else { // Buffer size enough for the maximum number of digits and \0. diff --git a/src/gmock_main.cc b/src/gmock_main.cc index a97e9532..85689d5d 100644 --- a/src/gmock_main.cc +++ b/src/gmock_main.cc @@ -33,7 +33,18 @@ #include #include -int main(int argc, char **argv) { +// MS C++ compiler/linker has a bug on Windows (not on Windows CE), which +// causes a link error when _tmain is defined in a static library and UNICODE +// is enabled. For this reason instead of _tmain, main function is used on +// Windows. See the following link to track the current status of this bug: +// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=394464 // NOLINT +#ifdef _WIN32_WCE +#include // NOLINT + +int _tmain(int argc, TCHAR** argv) { +#else +int main(int argc, char** argv) { +#endif // _WIN32_WCE std::cout << "Running main() from gmock_main.cc\n"; // Since Google Mock depends on Google Test, InitGoogleMock() is // also responsible for initializing Google Test. Therefore there's -- cgit v1.2.3 From df35a763b9d98d7040a00fc1e5cffe91a80ba9e0 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Wed, 22 Apr 2009 22:25:31 +0000 Subject: Implements --gmock_catch_leaked_mocks and Mock::AllowLeak. --- src/gmock-spec-builders.cc | 124 ++++++++++++++++++++++++++++++++++++++++----- src/gmock.cc | 31 +++++++++++- 2 files changed, 142 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index 353bb2df..2bb72954 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -36,9 +36,17 @@ #include +#include +#include // NOLINT +#include #include +#include #include +#if GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC +#include // NOLINT +#endif + namespace testing { namespace internal { @@ -148,10 +156,77 @@ void ReportUninterestingCall(CallReaction reaction, const string& msg) { namespace { typedef std::set FunctionMockers; -typedef std::map MockObjectRegistry; -// Maps a mock object to the set of mock methods it owns. Protected -// by g_gmock_mutex. +// The current state of a mock object. Such information is needed for +// detecting leaked mock objects and explicitly verifying a mock's +// expectations. +struct MockObjectState { + MockObjectState() + : first_used_file(NULL), first_used_line(-1), leakable(false) {} + + // Where in the source file an ON_CALL or EXPECT_CALL is first + // invoked on this mock object. + const char* first_used_file; + int first_used_line; + bool leakable; // true iff it's OK to leak the object. + FunctionMockers function_mockers; // All registered methods of the object. +}; + +// A global registry holding the state of all mock objects that are +// alive. A mock object is added to this registry the first time +// Mock::AllowLeak(), ON_CALL(), or EXPECT_CALL() is called on it. It +// is removed from the registry in the mock object's destructor. +class MockObjectRegistry { + public: + // Maps a mock object (identified by its address) to its state. + typedef std::map StateMap; + + // This destructor will be called when a program exits, after all + // tests in it have been run. By then, there should be no mock + // object alive. Therefore we report any living object as test + // failure, unless the user explicitly asked us to ignore it. + ~MockObjectRegistry() { + using ::std::cout; + + if (!GMOCK_FLAG(catch_leaked_mocks)) + return; + + int leaked_count = 0; + for (StateMap::const_iterator it = states_.begin(); it != states_.end(); + ++it) { + if (it->second.leakable) // The user said it's fine to leak this object. + continue; + + // TODO(wan@google.com): Print the type of the leaked object. + // This can help the user identify the leaked object. + cout << "\n"; + const MockObjectState& state = it->second; + internal::FormatFileLocation( + state.first_used_file, state.first_used_line, &cout); + cout << " ERROR: this mock object should be deleted but never is. " + << "Its address is @" << it->first << "."; + leaked_count++; + } + if (leaked_count > 0) { + cout << "\nERROR: " << leaked_count + << " leaked mock " << (leaked_count == 1 ? "object" : "objects") + << " found at program exit.\n"; + cout.flush(); + ::std::cerr.flush(); + // RUN_ALL_TESTS() has already returned when this destructor is + // called. Therefore we cannot use the normal Google Test + // failure reporting mechanism. + _exit(1); // We cannot call exit() as it is not reentrant and + // may already have been called. + } + } + + StateMap& states() { return states_; } + private: + StateMap states_; +}; + +// Protected by g_gmock_mutex. MockObjectRegistry g_mock_object_registry; // Maps a mock object to the reaction Google Mock should have when an @@ -208,6 +283,14 @@ internal::CallReaction Mock::GetReactionOnUninterestingCalls( internal::WARN : g_uninteresting_call_reaction[mock_obj]; } +// Tells Google Mock to ignore mock_obj when checking for leaked mock +// objects. +// L < g_gmock_mutex +void Mock::AllowLeak(const void* mock_obj) { + internal::MutexLock l(&internal::g_gmock_mutex); + g_mock_object_registry.states()[mock_obj].leakable = true; +} + // Verifies and clears all expectations on the given mock object. If // the expectations aren't satisfied, generates one or more Google // Test non-fatal failures and returns false. @@ -233,7 +316,7 @@ bool Mock::VerifyAndClear(void* mock_obj) { // L >= g_gmock_mutex bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj) { internal::g_gmock_mutex.AssertHeld(); - if (g_mock_object_registry.count(mock_obj) == 0) { + if (g_mock_object_registry.states().count(mock_obj) == 0) { // No EXPECT_CALL() was set on the given mock object. return true; } @@ -241,7 +324,8 @@ bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj) { // Verifies and clears the expectations on each mock method in the // given mock object. bool expectations_met = true; - FunctionMockers& mockers = g_mock_object_registry[mock_obj]; + FunctionMockers& mockers = + g_mock_object_registry.states()[mock_obj].function_mockers; for (FunctionMockers::const_iterator it = mockers.begin(); it != mockers.end(); ++it) { if (!(*it)->VerifyAndClearExpectationsLocked()) { @@ -259,7 +343,21 @@ bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj) { void Mock::Register(const void* mock_obj, internal::UntypedFunctionMockerBase* mocker) { internal::MutexLock l(&internal::g_gmock_mutex); - g_mock_object_registry[mock_obj].insert(mocker); + g_mock_object_registry.states()[mock_obj].function_mockers.insert(mocker); +} + +// Tells Google Mock where in the source code mock_obj is used in an +// ON_CALL or EXPECT_CALL. In case mock_obj is leaked, this +// information helps the user identify which object it is. +// L < g_gmock_mutex +void Mock::RegisterUseByOnCallOrExpectCall( + const void* mock_obj, const char* file, int line) { + internal::MutexLock l(&internal::g_gmock_mutex); + MockObjectState& state = g_mock_object_registry.states()[mock_obj]; + if (state.first_used_file == NULL) { + state.first_used_file = file; + state.first_used_line = line; + } } // Unregisters a mock method; removes the owning mock object from the @@ -269,13 +367,14 @@ void Mock::Register(const void* mock_obj, // L >= g_gmock_mutex void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker) { internal::g_gmock_mutex.AssertHeld(); - for (MockObjectRegistry::iterator it = g_mock_object_registry.begin(); - it != g_mock_object_registry.end(); ++it) { - FunctionMockers& mockers = it->second; + for (MockObjectRegistry::StateMap::iterator it = + g_mock_object_registry.states().begin(); + it != g_mock_object_registry.states().end(); ++it) { + FunctionMockers& mockers = it->second.function_mockers; if (mockers.erase(mocker) > 0) { // mocker was in mockers and has been just removed. if (mockers.empty()) { - g_mock_object_registry.erase(it); + g_mock_object_registry.states().erase(it); } return; } @@ -287,14 +386,15 @@ void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker) { void Mock::ClearDefaultActionsLocked(void* mock_obj) { internal::g_gmock_mutex.AssertHeld(); - if (g_mock_object_registry.count(mock_obj) == 0) { + if (g_mock_object_registry.states().count(mock_obj) == 0) { // No ON_CALL() was set on the given mock object. return; } // Clears the default actions for each mock method in the given mock // object. - FunctionMockers& mockers = g_mock_object_registry[mock_obj]; + FunctionMockers& mockers = + g_mock_object_registry.states()[mock_obj].function_mockers; for (FunctionMockers::const_iterator it = mockers.begin(); it != mockers.end(); ++it) { (*it)->ClearDefaultActionsLocked(); diff --git a/src/gmock.cc b/src/gmock.cc index c017917d..dc9d3d22 100644 --- a/src/gmock.cc +++ b/src/gmock.cc @@ -34,6 +34,15 @@ namespace testing { +// TODO(wan@google.com): support using environment variables to +// control the flag values, like what Google Test does. + +// TODO(wan@google.com): change the default value to true after people +// have a chance to fix their leaked mocks. +GMOCK_DEFINE_bool_(catch_leaked_mocks, false, + "true iff Google Mock should report leaked mock objects " + "as failures."); + GMOCK_DEFINE_string_(verbose, internal::kWarningVerbosity, "Controls how verbose Google Mock's output is." " Valid values:\n" @@ -76,6 +85,24 @@ static const char* ParseGoogleMockFlagValue(const char* str, return flag_end + 1; } +// Parses a string for a Google Mock bool flag, in the form of +// "--gmock_flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +static bool ParseGoogleMockBoolFlag(const char* str, const char* flag, + bool* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseGoogleMockFlagValue(str, flag, true); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Converts the string value to a bool. + *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F'); + return true; +} + // Parses a string for a Google Mock string flag, in the form of // "--gmock_flag=value". // @@ -110,7 +137,9 @@ void InitGoogleMockImpl(int* argc, CharType** argv) { const char* const arg = arg_string.c_str(); // Do we see a Google Mock flag? - if (ParseGoogleMockStringFlag(arg, "verbose", &GMOCK_FLAG(verbose))) { + if (ParseGoogleMockBoolFlag(arg, "catch_leaked_mocks", + &GMOCK_FLAG(catch_leaked_mocks)) || + ParseGoogleMockStringFlag(arg, "verbose", &GMOCK_FLAG(verbose))) { // Yes. Shift the remainder of the argv list left by one. Note // that argv has (*argc + 1) elements, the last one always being // NULL. The following loop moves the trailing NULL element as -- cgit v1.2.3 From bf0d0a44812f97449d7401d0eeb8da954f76ba2a Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Wed, 29 Apr 2009 23:52:29 +0000 Subject: Turns --gmock_catch_leaked_mocks on by default. --- src/gmock.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/gmock.cc b/src/gmock.cc index dc9d3d22..caafb015 100644 --- a/src/gmock.cc +++ b/src/gmock.cc @@ -37,9 +37,7 @@ namespace testing { // TODO(wan@google.com): support using environment variables to // control the flag values, like what Google Test does. -// TODO(wan@google.com): change the default value to true after people -// have a chance to fix their leaked mocks. -GMOCK_DEFINE_bool_(catch_leaked_mocks, false, +GMOCK_DEFINE_bool_(catch_leaked_mocks, true, "true iff Google Mock should report leaked mock objects " "as failures."); -- cgit v1.2.3 From e7bb5ededa4df6ec430c1e84154bc01bf84d4ecc Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Tue, 5 May 2009 23:14:47 +0000 Subject: Improves the error message for leaked mocks to include the test name (by Zhanyong Wan). --- src/gmock-spec-builders.cc | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index 2bb72954..65a74b81 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -168,6 +168,8 @@ struct MockObjectState { // invoked on this mock object. const char* first_used_file; int first_used_line; + ::std::string first_used_test_case; + ::std::string first_used_test; bool leakable; // true iff it's OK to leak the object. FunctionMockers function_mockers; // All registered methods of the object. }; @@ -203,8 +205,13 @@ class MockObjectRegistry { const MockObjectState& state = it->second; internal::FormatFileLocation( state.first_used_file, state.first_used_line, &cout); - cout << " ERROR: this mock object should be deleted but never is. " - << "Its address is @" << it->first << "."; + cout << " ERROR: this mock object"; + if (state.first_used_test != "") { + cout << " (used in test " << state.first_used_test_case << "." + << state.first_used_test << ")"; + } + cout << " should be deleted but never is. Its address is @" + << it->first << "."; leaked_count++; } if (leaked_count > 0) { @@ -357,6 +364,15 @@ void Mock::RegisterUseByOnCallOrExpectCall( if (state.first_used_file == NULL) { state.first_used_file = file; state.first_used_line = line; + const TestInfo* const test_info = + UnitTest::GetInstance()->current_test_info(); + if (test_info != NULL) { + // TODO(wan@google.com): record the test case name when the + // ON_CALL or EXPECT_CALL is invoked from SetUpTestCase() or + // TearDownTestCase(). + state.first_used_test_case = test_info->test_case_name(); + state.first_used_test = test_info->name(); + } } } -- cgit v1.2.3 From 9413f2ff615ae1b933580576183d316c4cb6376c Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Fri, 29 May 2009 19:50:06 +0000 Subject: Avoids unnecessary printing of call into to internal buffers; Made the universal value printer safer when printing char[]; Removed duplicated code in InvokeWith; Improved gmock_doctor.py. --- src/gmock-internal-utils.cc | 27 +++++++++++++++++---------- src/gmock-printers.cc | 5 +++++ src/gmock-spec-builders.cc | 4 ++-- 3 files changed, 24 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/gmock-internal-utils.cc b/src/gmock-internal-utils.cc index 735abce5..ce17d715 100644 --- a/src/gmock-internal-utils.cc +++ b/src/gmock-internal-utils.cc @@ -101,6 +101,22 @@ FailureReporterInterface* GetFailureReporter() { // Protects global resources (stdout in particular) used by Log(). static Mutex g_log_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX); +// Returns true iff a log with the given severity is visible according +// to the --gmock_verbose flag. +bool LogIsVisible(LogSeverity severity) { + if (GMOCK_FLAG(verbose) == kInfoVerbosity) { + // Always show the log if --gmock_verbose=info. + return true; + } else if (GMOCK_FLAG(verbose) == kErrorVerbosity) { + // Always hide it if --gmock_verbose=error. + return false; + } else { + // If --gmock_verbose is neither "info" nor "error", we treat it + // as "warning" (its default value). + return severity == WARNING; + } +} + // Prints the given message to stdout iff 'severity' >= the level // specified by the --gmock_verbose flag. If stack_frames_to_skip >= // 0, also prints the stack trace excluding the top @@ -110,17 +126,8 @@ static Mutex g_log_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX); // conservative. void Log(LogSeverity severity, const string& message, int stack_frames_to_skip) { - if (GMOCK_FLAG(verbose) == kErrorVerbosity) { - // The user is not interested in logs. + if (!LogIsVisible(severity)) return; - } else if (GMOCK_FLAG(verbose) != kInfoVerbosity) { - // The user is interested in warnings but not informational logs. - // Note that invalid values of GMOCK_FLAG(verbose) are treated as - // "warning", which is the default value of the flag. - if (severity == INFO) { - return; - } - } // Ensures that logs from different threads don't interleave. MutexLock l(&g_log_mutex); diff --git a/src/gmock-printers.cc b/src/gmock-printers.cc index e6d4001a..922a7b2d 100644 --- a/src/gmock-printers.cc +++ b/src/gmock-printers.cc @@ -242,6 +242,11 @@ static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) { *os << "\""; } +// Prints a (const) char array of 'len' elements, starting at address 'begin'. +void UniversalPrintArray(const char* begin, size_t len, ostream* os) { + PrintCharsAsStringTo(begin, len, os); +} + // Prints the given array of wide characters to the ostream. // The array starts at *begin, the length is len, it may include L'\0' // characters and may not be null-terminated. diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index 65a74b81..465e4d63 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -139,10 +139,10 @@ ThreadLocal g_gmock_implicit_sequence; void ReportUninterestingCall(CallReaction reaction, const string& msg) { switch (reaction) { case ALLOW: - Log(INFO, msg, 4); + Log(INFO, msg, 3); break; case WARN: - Log(WARNING, msg, 4); + Log(WARNING, msg, 3); break; default: // FAIL Expect(false, NULL, -1, msg); -- cgit v1.2.3 From bf55085d456e3ee55eb234c98c435e54d0a2d5aa Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Tue, 9 Jun 2009 06:09:53 +0000 Subject: Implements .With() as a synonym of .WithArguments(); implements AllArgs(m) as a synonym of m; relies on gtest-port to #include tuple; fixes a compatibility with Symbian. --- src/gmock-internal-utils.cc | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/gmock-internal-utils.cc b/src/gmock-internal-utils.cc index ce17d715..0e693c70 100644 --- a/src/gmock-internal-utils.cc +++ b/src/gmock-internal-utils.cc @@ -131,16 +131,19 @@ void Log(LogSeverity severity, const string& message, // Ensures that logs from different threads don't interleave. MutexLock l(&g_log_mutex); - using ::std::cout; + + // "using ::std::cout;" doesn't work with Symbian's STLport, where cout is a + // macro. + if (severity == WARNING) { // Prints a GMOCK WARNING marker to make the warnings easily searchable. - cout << "\nGMOCK WARNING:"; + std::cout << "\nGMOCK WARNING:"; } // Pre-pends a new-line to message if it doesn't start with one. if (message.empty() || message[0] != '\n') { - cout << "\n"; + std::cout << "\n"; } - cout << message; + std::cout << message; if (stack_frames_to_skip >= 0) { #ifdef NDEBUG // In opt mode, we have to be conservative and skip no stack frame. @@ -153,13 +156,13 @@ void Log(LogSeverity severity, const string& message, // Appends a new-line to message if it doesn't end with one. if (!message.empty() && *message.rbegin() != '\n') { - cout << "\n"; + std::cout << "\n"; } - cout << "Stack trace:\n" + std::cout << "Stack trace:\n" << ::testing::internal::GetCurrentOsStackTraceExceptTop( ::testing::UnitTest::GetInstance(), actual_to_skip); } - cout << ::std::flush; + std::cout << ::std::flush; } } // namespace internal -- cgit v1.2.3 From 41b9b0b5614588d252d565646ae43e9607d46502 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Wed, 1 Jul 2009 19:04:51 +0000 Subject: Implements Expectation, ExpectationSet, and After for specifying expectation orders. --- src/gmock-spec-builders.cc | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index 465e4d63..00d16918 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -82,11 +82,9 @@ void ExpectationBase::RetireAllPreRequisites() { return; } - for (ExpectationBaseSet::const_iterator it = - immediate_prerequisites_.begin(); - it != immediate_prerequisites_.end(); - ++it) { - ExpectationBase* const prerequisite = (*it).get(); + for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin(); + it != immediate_prerequisites_.end(); ++it) { + ExpectationBase* const prerequisite = it->expectation_base().get(); if (!prerequisite->is_retired()) { prerequisite->RetireAllPreRequisites(); prerequisite->Retire(); @@ -99,10 +97,10 @@ void ExpectationBase::RetireAllPreRequisites() { // L >= g_gmock_mutex bool ExpectationBase::AllPrerequisitesAreSatisfied() const { g_gmock_mutex.AssertHeld(); - for (ExpectationBaseSet::const_iterator it = immediate_prerequisites_.begin(); + for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin(); it != immediate_prerequisites_.end(); ++it) { - if (!(*it)->IsSatisfied() || - !(*it)->AllPrerequisitesAreSatisfied()) + if (!(it->expectation_base()->IsSatisfied()) || + !(it->expectation_base()->AllPrerequisitesAreSatisfied())) return false; } return true; @@ -111,21 +109,21 @@ bool ExpectationBase::AllPrerequisitesAreSatisfied() const { // Adds unsatisfied pre-requisites of this expectation to 'result'. // L >= g_gmock_mutex void ExpectationBase::FindUnsatisfiedPrerequisites( - ExpectationBaseSet* result) const { + ExpectationSet* result) const { g_gmock_mutex.AssertHeld(); - for (ExpectationBaseSet::const_iterator it = immediate_prerequisites_.begin(); + for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin(); it != immediate_prerequisites_.end(); ++it) { - if ((*it)->IsSatisfied()) { + if (it->expectation_base()->IsSatisfied()) { // If *it is satisfied and has a call count of 0, some of its // pre-requisites may not be satisfied yet. - if ((*it)->call_count_ == 0) { - (*it)->FindUnsatisfiedPrerequisites(result); + if (it->expectation_base()->call_count_ == 0) { + it->expectation_base()->FindUnsatisfiedPrerequisites(result); } } else { // Now that we know *it is unsatisfied, we are not so interested // in whether its pre-requisites are satisfied. Therefore we // don't recursively call FindUnsatisfiedPrerequisites() here. - result->insert(*it); + *result += *it; } } } @@ -421,11 +419,11 @@ void Mock::ClearDefaultActionsLocked(void* mock_obj) { } // Adds an expectation to a sequence. -void Sequence::AddExpectation( - const internal::linked_ptr& expectation) const { +void Sequence::AddExpectation(const Expectation& expectation) const { if (*last_expectation_ != expectation) { - if (*last_expectation_ != NULL) { - expectation->immediate_prerequisites_.insert(*last_expectation_); + if (last_expectation_->expectation_base() != NULL) { + expectation.expectation_base()->immediate_prerequisites_ + += *last_expectation_; } *last_expectation_ = expectation; } -- cgit v1.2.3 From 9571b28675a5a602ed3c8a7acf270d03aca69c96 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Fri, 7 Aug 2009 07:15:56 +0000 Subject: Removes duplicated definition of SetArgumentPointee (by Vlad Losev); Makes gmock compilable on platforms that don't have ::abort() (by Acadeli Checa); Fixes compatibility with Symbian's STLport (by Acadeli Checa). --- src/gmock-internal-utils.cc | 2 +- src/gmock-spec-builders.cc | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/gmock-internal-utils.cc b/src/gmock-internal-utils.cc index 0e693c70..e72e019b 100644 --- a/src/gmock-internal-utils.cc +++ b/src/gmock-internal-utils.cc @@ -80,7 +80,7 @@ class GoogleTestFailureReporter : public FailureReporterInterface { AssertHelper(type == FATAL ? TPRT_FATAL_FAILURE : TPRT_NONFATAL_FAILURE, file, line, message.c_str()) = Message(); if (type == FATAL) { - abort(); + posix::Abort(); } } }; diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index 00d16918..94ba24bb 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -186,7 +186,9 @@ class MockObjectRegistry { // object alive. Therefore we report any living object as test // failure, unless the user explicitly asked us to ignore it. ~MockObjectRegistry() { - using ::std::cout; + + // "using ::std::cout;" doesn't work with Symbian's STLport, where cout is + // a macro. if (!GMOCK_FLAG(catch_leaked_mocks)) return; @@ -199,24 +201,24 @@ class MockObjectRegistry { // TODO(wan@google.com): Print the type of the leaked object. // This can help the user identify the leaked object. - cout << "\n"; + std::cout << "\n"; const MockObjectState& state = it->second; internal::FormatFileLocation( - state.first_used_file, state.first_used_line, &cout); - cout << " ERROR: this mock object"; + state.first_used_file, state.first_used_line, &std::cout); + std::cout << " ERROR: this mock object"; if (state.first_used_test != "") { - cout << " (used in test " << state.first_used_test_case << "." + std::cout << " (used in test " << state.first_used_test_case << "." << state.first_used_test << ")"; } - cout << " should be deleted but never is. Its address is @" + std::cout << " should be deleted but never is. Its address is @" << it->first << "."; leaked_count++; } if (leaked_count > 0) { - cout << "\nERROR: " << leaked_count + std::cout << "\nERROR: " << leaked_count << " leaked mock " << (leaked_count == 1 ? "object" : "objects") << " found at program exit.\n"; - cout.flush(); + std::cout.flush(); ::std::cerr.flush(); // RUN_ALL_TESTS() has already returned when this destructor is // called. Therefore we cannot use the normal Google Test -- cgit v1.2.3 From 2b43a9ecd16edc1ec55429967e0f2de1aaf8e8bb Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Mon, 31 Aug 2009 23:51:23 +0000 Subject: Adds mutable_impl() and impl() to PolymorphicMatcher (by Zhanyong Wan); Enables gMock to compile with VC 7.1 (by Vlad Losev). --- src/gmock-printers.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gmock-printers.cc b/src/gmock-printers.cc index 922a7b2d..0473dba1 100644 --- a/src/gmock-printers.cc +++ b/src/gmock-printers.cc @@ -55,10 +55,12 @@ namespace { using ::std::ostream; -#ifdef _WIN32_WCE +#ifdef _WIN32_WCE // Windows CE does not define _snprintf_s. #define snprintf _snprintf -#elif GTEST_OS_WINDOWS +#elif _MSC_VER >= 1400 // VC 8.0 and later deprecate snprintf and _snprintf. #define snprintf _snprintf_s +#elif _MSC_VER +#define snprintf _snprintf #endif // Prints a segment of bytes in the given object. -- cgit v1.2.3 From 46642857b18abae8537317f944569ef552e2d301 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Tue, 1 Sep 2009 19:10:50 +0000 Subject: Depends on gtest r300, which allows String to contain NUL. --- src/gmock.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gmock.cc b/src/gmock.cc index caafb015..f487265d 100644 --- a/src/gmock.cc +++ b/src/gmock.cc @@ -63,7 +63,7 @@ static const char* ParseGoogleMockFlagValue(const char* str, // The flag must start with "--gmock_". const String flag_str = String::Format("--gmock_%s", flag); - const size_t flag_len = flag_str.GetLength(); + const size_t flag_len = flag_str.length(); if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL; // Skips the flag name. -- cgit v1.2.3 From f5e1ce5b9237edbc2e524ae9ebcb2452dc842937 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Wed, 16 Sep 2009 07:02:02 +0000 Subject: Adds new matcher Pair(). Replaces GMOCK_CHECK_ with GTEST_CHECK_ (by Vlad Losev). --- src/gmock-spec-builders.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index 94ba24bb..72558658 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -203,8 +203,8 @@ class MockObjectRegistry { // This can help the user identify the leaked object. std::cout << "\n"; const MockObjectState& state = it->second; - internal::FormatFileLocation( - state.first_used_file, state.first_used_line, &std::cout); + std::cout << internal::FormatFileLocation(state.first_used_file, + state.first_used_line); std::cout << " ERROR: this mock object"; if (state.first_used_test != "") { std::cout << " (used in test " << state.first_used_test_case << "." -- cgit v1.2.3 From bbd6e105e786dd6d4e1fdd6b1467f969121bcca3 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Fri, 18 Sep 2009 18:17:19 +0000 Subject: Picks up gtest r314. --- src/gmock-internal-utils.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gmock-internal-utils.cc b/src/gmock-internal-utils.cc index e72e019b..196ec74b 100644 --- a/src/gmock-internal-utils.cc +++ b/src/gmock-internal-utils.cc @@ -77,8 +77,12 @@ class GoogleTestFailureReporter : public FailureReporterInterface { public: virtual void ReportFailure(FailureType type, const char* file, int line, const string& message) { - AssertHelper(type == FATAL ? TPRT_FATAL_FAILURE : TPRT_NONFATAL_FAILURE, - file, line, message.c_str()) = Message(); + AssertHelper(type == FATAL ? + TestPartResult::kFatalFailure : + TestPartResult::kNonFatalFailure, + file, + line, + message.c_str()) = Message(); if (type == FATAL) { posix::Abort(); } -- cgit v1.2.3 From f7af24c7de14ccb10a24909a6f3440a763cb1164 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Thu, 24 Sep 2009 21:17:24 +0000 Subject: Simplifies gmock code using gtest's OS-indicating macros. --- src/gmock-printers.cc | 4 ++-- src/gmock_main.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/gmock-printers.cc b/src/gmock-printers.cc index 0473dba1..8efba782 100644 --- a/src/gmock-printers.cc +++ b/src/gmock-printers.cc @@ -55,13 +55,13 @@ namespace { using ::std::ostream; -#ifdef _WIN32_WCE // Windows CE does not define _snprintf_s. +#if GTEST_OS_WINDOWS_MOBILE // Windows CE does not define _snprintf_s. #define snprintf _snprintf #elif _MSC_VER >= 1400 // VC 8.0 and later deprecate snprintf and _snprintf. #define snprintf _snprintf_s #elif _MSC_VER #define snprintf _snprintf -#endif +#endif // GTEST_OS_WINDOWS_MOBILE // Prints a segment of bytes in the given object. void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, diff --git a/src/gmock_main.cc b/src/gmock_main.cc index 85689d5d..0a3071bf 100644 --- a/src/gmock_main.cc +++ b/src/gmock_main.cc @@ -38,13 +38,13 @@ // is enabled. For this reason instead of _tmain, main function is used on // Windows. See the following link to track the current status of this bug: // http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=394464 // NOLINT -#ifdef _WIN32_WCE +#if GTEST_OS_WINDOWS_MOBILE #include // NOLINT int _tmain(int argc, TCHAR** argv) { #else int main(int argc, char** argv) { -#endif // _WIN32_WCE +#endif // GTEST_OS_WINDOWS_MOBILE std::cout << "Running main() from gmock_main.cc\n"; // Since Google Mock depends on Google Test, InitGoogleMock() is // also responsible for initializing Google Test. Therefore there's -- cgit v1.2.3 From 7c95d8346e9c62e9d6d7e8202fbcfb34c4404db9 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Thu, 1 Oct 2009 21:56:16 +0000 Subject: Works around a Symbian compiler bug that causes memory leak (by Mika Raento). --- src/gmock-spec-builders.cc | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index 72558658..6cc94ddd 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -420,6 +420,14 @@ void Mock::ClearDefaultActionsLocked(void* mock_obj) { // needed by VerifyAndClearExpectationsLocked(). } +Expectation::Expectation() {} + +Expectation::Expectation( + const internal::linked_ptr& expectation_base) + : expectation_base_(expectation_base) {} + +Expectation::~Expectation() {} + // Adds an expectation to a sequence. void Sequence::AddExpectation(const Expectation& expectation) const { if (*last_expectation_ != expectation) { -- cgit v1.2.3 From 6c54a5e1f91e033fa937be5d647ce43dee597ad8 Mon Sep 17 00:00:00 2001 From: vladlosev Date: Wed, 21 Oct 2009 06:15:34 +0000 Subject: Enables more verbose output for expectations (by Sverre Sundsdal); Fixes information loss warning when compiled by VC8.0 with /Wp64; Skips two tests on Windows Mobile that don't work there. --- src/gmock-spec-builders.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index 6cc94ddd..edd60fec 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -40,6 +40,7 @@ #include // NOLINT #include #include +#include #include #include @@ -55,9 +56,12 @@ namespace internal { Mutex g_gmock_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX); // Constructs an ExpectationBase object. -ExpectationBase::ExpectationBase(const char* file, int line) +ExpectationBase::ExpectationBase(const char* file, + int line, + const string& source_text) : file_(file), line_(line), + source_text_(source_text), cardinality_specified_(false), cardinality_(Exactly(1)), call_count_(0), -- cgit v1.2.3 From 4910d29e1e1eed4f6946871168a234be5b490163 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Tue, 10 Nov 2009 19:16:27 +0000 Subject: Makes gmock-all.cc catch errors in fuse_gmock.py. --- src/gmock-all.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/gmock-all.cc b/src/gmock-all.cc index a14c397d..c9223fce 100644 --- a/src/gmock-all.cc +++ b/src/gmock-all.cc @@ -35,6 +35,11 @@ // purpose is to allow a user to build Google Mock by compiling this // file alone. +// This line ensures that gmock.h can be compiled on its own, even +// when it's fused. +#include + +// The following lines pull in the real gmock *.cc files. #include "src/gmock-cardinalities.cc" #include "src/gmock-internal-utils.cc" #include "src/gmock-matchers.cc" -- cgit v1.2.3 From f6d6a22b8eea931b49a8c33de3092d4623ed0d41 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Tue, 1 Dec 2009 19:42:25 +0000 Subject: Fixes Cygwin compatibility (by Vlad Losev); Improves Python tests (by Vlad Losev); Fixes ambiguous call to implicit_cast; Uses gtest's SkipPrefix() instead gmock's own (by Vlad Losev). --- src/gmock-matchers.cc | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'src') diff --git a/src/gmock-matchers.cc b/src/gmock-matchers.cc index 79b525d3..0abca708 100644 --- a/src/gmock-matchers.cc +++ b/src/gmock-matchers.cc @@ -83,18 +83,6 @@ int GetParamIndex(const char* param_names[], const string& param_name) { return kInvalidInterpolation; } -// If *pstr starts with the given prefix, modifies *pstr to be right -// past the prefix and returns true; otherwise leaves *pstr unchanged -// and returns false. None of pstr, *pstr, and prefix can be NULL. -bool SkipPrefix(const char* prefix, const char** pstr) { - const size_t prefix_len = strlen(prefix); - if (strncmp(*pstr, prefix, prefix_len) == 0) { - *pstr += prefix_len; - return true; - } - return false; -} - // Helper function used by ValidateMatcherDescription() to format // error messages. string FormatMatcherDescriptionSyntaxError(const char* description, -- cgit v1.2.3 From 39bf784f839a9ffeb5f2d943435783633c5c0a6d Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Wed, 16 Dec 2009 23:36:08 +0000 Subject: Removes uses of GTEST_HAS_STD_STRING. --- src/gmock-printers.cc | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/gmock-printers.cc b/src/gmock-printers.cc index 8efba782..fd7d3055 100644 --- a/src/gmock-printers.cc +++ b/src/gmock-printers.cc @@ -296,11 +296,9 @@ void PrintStringTo(const ::string& s, ostream* os) { } #endif // GTEST_HAS_GLOBAL_STRING -#if GTEST_HAS_STD_STRING void PrintStringTo(const ::std::string& s, ostream* os) { PrintCharsAsStringTo(s.data(), s.size(), os); } -#endif // GTEST_HAS_STD_STRING // Prints a ::wstring object. #if GTEST_HAS_GLOBAL_WSTRING -- cgit v1.2.3 From 32de5f53763125925e078498250f7e73a88de9ed Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Wed, 23 Dec 2009 00:13:23 +0000 Subject: Fixes a slew of compiler warnings and turns on "warning as error" in the scons build. --- src/gmock-internal-utils.cc | 2 +- src/gmock-spec-builders.cc | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/gmock-internal-utils.cc b/src/gmock-internal-utils.cc index 196ec74b..4c51ec00 100644 --- a/src/gmock-internal-utils.cc +++ b/src/gmock-internal-utils.cc @@ -64,7 +64,7 @@ string ConvertIdentifierNameToWords(const char* id_name) { if (isalnum(*p)) { if (starts_new_word && result != "") result += ' '; - result += tolower(*p); + result += static_cast(tolower(*p)); } } return result; diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index edd60fec..02a3227f 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -56,12 +56,12 @@ namespace internal { Mutex g_gmock_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX); // Constructs an ExpectationBase object. -ExpectationBase::ExpectationBase(const char* file, - int line, - const string& source_text) - : file_(file), - line_(line), - source_text_(source_text), +ExpectationBase::ExpectationBase(const char* a_file, + int a_line, + const string& a_source_text) + : file_(a_file), + line_(a_line), + source_text_(a_source_text), cardinality_specified_(false), cardinality_(Exactly(1)), call_count_(0), @@ -73,9 +73,9 @@ ExpectationBase::~ExpectationBase() {} // Explicitly specifies the cardinality of this expectation. Used by // the subclasses to implement the .Times() clause. -void ExpectationBase::SpecifyCardinality(const Cardinality& cardinality) { +void ExpectationBase::SpecifyCardinality(const Cardinality& a_cardinality) { cardinality_specified_ = true; - cardinality_ = cardinality; + cardinality_ = a_cardinality; } // Retires all pre-requisites of this expectation. @@ -427,8 +427,8 @@ void Mock::ClearDefaultActionsLocked(void* mock_obj) { Expectation::Expectation() {} Expectation::Expectation( - const internal::linked_ptr& expectation_base) - : expectation_base_(expectation_base) {} + const internal::linked_ptr& an_expectation_base) + : expectation_base_(an_expectation_base) {} Expectation::~Expectation() {} -- cgit v1.2.3 From 5905ba00fe78e522f7253e837ded3ddb5b946934 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Wed, 24 Feb 2010 17:21:37 +0000 Subject: Adds threading support (by Vlad Losev); updates the version number (by Zhanyong Wan); adds release notes for 1.5.0 (by Vlad Losev). --- src/gmock-internal-utils.cc | 2 +- src/gmock-spec-builders.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gmock-internal-utils.cc b/src/gmock-internal-utils.cc index 4c51ec00..cc51836b 100644 --- a/src/gmock-internal-utils.cc +++ b/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/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index 02a3227f..dab1a2c9 100644 --- a/src/gmock-spec-builders.cc +++ b/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, -- cgit v1.2.3 From 02f7106557fde1f1075dc53d65ef1f7a11851f93 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Mon, 10 May 2010 17:14:29 +0000 Subject: Moves the universal printer from gmock to gtest (by Vlad Losev). --- src/gmock-all.cc | 1 - src/gmock-printers.cc | 318 -------------------------------------------------- 2 files changed, 319 deletions(-) delete mode 100644 src/gmock-printers.cc (limited to 'src') diff --git a/src/gmock-all.cc b/src/gmock-all.cc index c9223fce..76118d88 100644 --- a/src/gmock-all.cc +++ b/src/gmock-all.cc @@ -43,6 +43,5 @@ #include "src/gmock-cardinalities.cc" #include "src/gmock-internal-utils.cc" #include "src/gmock-matchers.cc" -#include "src/gmock-printers.cc" #include "src/gmock-spec-builders.cc" #include "src/gmock.cc" diff --git a/src/gmock-printers.cc b/src/gmock-printers.cc deleted file mode 100644 index fd7d3055..00000000 --- a/src/gmock-printers.cc +++ /dev/null @@ -1,318 +0,0 @@ -// Copyright 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) - -// Google Mock - a framework for writing C++ mock classes. -// -// This file implements a universal value printer that can print a -// value of any type T: -// -// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); -// -// It uses the << operator when possible, and prints the bytes in the -// object otherwise. A user can override its behavior for a class -// type Foo by defining either operator<<(::std::ostream&, const Foo&) -// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that -// defines Foo. - -#include -#include -#include -#include // NOLINT -#include -#include - -namespace testing { - -namespace { - -using ::std::ostream; - -#if GTEST_OS_WINDOWS_MOBILE // Windows CE does not define _snprintf_s. -#define snprintf _snprintf -#elif _MSC_VER >= 1400 // VC 8.0 and later deprecate snprintf and _snprintf. -#define snprintf _snprintf_s -#elif _MSC_VER -#define snprintf _snprintf -#endif // GTEST_OS_WINDOWS_MOBILE - -// Prints a segment of bytes in the given object. -void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, - size_t count, ostream* os) { - char text[5] = ""; - for (size_t i = 0; i != count; i++) { - const size_t j = start + i; - if (i != 0) { - // Organizes the bytes into groups of 2 for easy parsing by - // human. - if ((j % 2) == 0) { - *os << " "; - } - } - snprintf(text, sizeof(text), "%02X", obj_bytes[j]); - *os << text; - } -} - -// Prints the bytes in the given value to the given ostream. -void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, - ostream* os) { - // Tells the user how big the object is. - *os << count << "-byte object <"; - - const size_t kThreshold = 132; - const size_t kChunkSize = 64; - // If the object size is bigger than kThreshold, we'll have to omit - // some details by printing only the first and the last kChunkSize - // bytes. - // TODO(wan): let the user control the threshold using a flag. - if (count < kThreshold) { - PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); - } else { - PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os); - *os << " ... "; - // Rounds up to 2-byte boundary. - const size_t resume_pos = (count - kChunkSize + 1)/2*2; - PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os); - } - *os << ">"; -} - -} // namespace - -namespace internal2 { - -// Delegates to PrintBytesInObjectToImpl() to print the bytes in the -// given object. The delegation simplifies the implementation, which -// uses the << operator and thus is easier done outside of the -// ::testing::internal namespace, which contains a << operator that -// sometimes conflicts with the one in STL. -void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, - ostream* os) { - PrintBytesInObjectToImpl(obj_bytes, count, os); -} - -} // namespace internal2 - -namespace internal { - -// Prints a wide char as a char literal without the quotes, escaping it -// when necessary. -static void PrintAsWideCharLiteralTo(wchar_t c, ostream* os) { - switch (c) { - case L'\0': - *os << "\\0"; - break; - case L'\'': - *os << "\\'"; - break; - case L'\?': - *os << "\\?"; - break; - case L'\\': - *os << "\\\\"; - break; - case L'\a': - *os << "\\a"; - break; - case L'\b': - *os << "\\b"; - break; - case L'\f': - *os << "\\f"; - break; - case L'\n': - *os << "\\n"; - break; - case L'\r': - *os << "\\r"; - break; - case L'\t': - *os << "\\t"; - break; - case L'\v': - *os << "\\v"; - break; - default: - // Checks whether c is printable or not. Printable characters are in - // the range [0x20,0x7E]. - // We test the value of c directly instead of calling isprint(), as - // isprint() is buggy on Windows mobile. - if (0x20 <= c && c <= 0x7E) { - *os << static_cast(c); - } else { - // Buffer size enough for the maximum number of digits and \0. - char text[2 * sizeof(unsigned long) + 1] = ""; - snprintf(text, sizeof(text), "%lX", static_cast(c)); - *os << "\\x" << text; - } - } -} - -// Prints a char as if it's part of a string literal, escaping it when -// necessary. -static void PrintAsWideStringLiteralTo(wchar_t c, ostream* os) { - switch (c) { - case L'\'': - *os << "'"; - break; - case L'"': - *os << "\\\""; - break; - default: - PrintAsWideCharLiteralTo(c, os); - } -} - -// Prints a char as a char literal without the quotes, escaping it -// when necessary. -static void PrintAsCharLiteralTo(char c, ostream* os) { - PrintAsWideCharLiteralTo(static_cast(c), os); -} - -// Prints a char as if it's part of a string literal, escaping it when -// necessary. -static void PrintAsStringLiteralTo(char c, ostream* os) { - PrintAsWideStringLiteralTo(static_cast(c), os); -} - -// Prints a char and its code. The '\0' char is printed as "'\\0'", -// other unprintable characters are also properly escaped using the -// standard C++ escape sequence. -void PrintCharTo(char c, int char_code, ostream* os) { - *os << "'"; - PrintAsCharLiteralTo(c, os); - *os << "'"; - if (c != '\0') - *os << " (" << char_code << ")"; -} - -// Prints a wchar_t as a symbol if it is printable or as its internal -// code otherwise and also as its decimal code (except for L'\0'). -// The L'\0' char is printed as "L'\\0'". The decimal code is printed -// as signed integer when wchar_t is implemented by the compiler -// as a signed type and is printed as an unsigned integer when wchar_t -// is implemented as an unsigned type. -void PrintTo(wchar_t wc, ostream* os) { - *os << "L'"; - PrintAsWideCharLiteralTo(wc, os); - *os << "'"; - if (wc != L'\0') { - // Type Int64 is used because it provides more storage than wchar_t thus - // when the compiler converts signed or unsigned implementation of wchar_t - // to Int64 it fills higher bits with either zeros or the sign bit - // passing it to operator <<() as either signed or unsigned integer. - *os << " (" << static_cast(wc) << ")"; - } -} - -// Prints the given array of characters to the ostream. -// The array starts at *begin, the length is len, it may include '\0' characters -// and may not be null-terminated. -static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) { - *os << "\""; - for (size_t index = 0; index < len; ++index) { - PrintAsStringLiteralTo(begin[index], os); - } - *os << "\""; -} - -// Prints a (const) char array of 'len' elements, starting at address 'begin'. -void UniversalPrintArray(const char* begin, size_t len, ostream* os) { - PrintCharsAsStringTo(begin, len, os); -} - -// Prints the given array of wide characters to the ostream. -// The array starts at *begin, the length is len, it may include L'\0' -// characters and may not be null-terminated. -static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len, - ostream* os) { - *os << "L\""; - for (size_t index = 0; index < len; ++index) { - PrintAsWideStringLiteralTo(begin[index], os); - } - *os << "\""; -} - -// Prints the given C string to the ostream. -void PrintTo(const char* s, ostream* os) { - if (s == NULL) { - *os << "NULL"; - } else { - *os << implicit_cast(s) << " pointing to "; - PrintCharsAsStringTo(s, strlen(s), os); - } -} - -// MSVC compiler can be configured to define whar_t as a typedef -// of unsigned short. Defining an overload for const wchar_t* in that case -// would cause pointers to unsigned shorts be printed as wide strings, -// possibly accessing more memory than intended and causing invalid -// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when -// wchar_t is implemented as a native type. -#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) -// Prints the given wide C string to the ostream. -void PrintTo(const wchar_t* s, ostream* os) { - if (s == NULL) { - *os << "NULL"; - } else { - *os << implicit_cast(s) << " pointing to "; - PrintWideCharsAsStringTo(s, wcslen(s), os); - } -} -#endif // wchar_t is native - -// Prints a ::string object. -#if GTEST_HAS_GLOBAL_STRING -void PrintStringTo(const ::string& s, ostream* os) { - PrintCharsAsStringTo(s.data(), s.size(), os); -} -#endif // GTEST_HAS_GLOBAL_STRING - -void PrintStringTo(const ::std::string& s, ostream* os) { - PrintCharsAsStringTo(s.data(), s.size(), os); -} - -// Prints a ::wstring object. -#if GTEST_HAS_GLOBAL_WSTRING -void PrintWideStringTo(const ::wstring& s, ostream* os) { - PrintWideCharsAsStringTo(s.data(), s.size(), os); -} -#endif // GTEST_HAS_GLOBAL_WSTRING - -#if GTEST_HAS_STD_WSTRING -void PrintWideStringTo(const ::std::wstring& s, ostream* os) { - PrintWideCharsAsStringTo(s.data(), s.size(), os); -} -#endif // GTEST_HAS_STD_WSTRING - -} // namespace internal - -} // namespace testing -- cgit v1.2.3 From b4140808f98ff09c43ca1ddaa8ff13bc47cd0089 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Tue, 8 Jun 2010 22:53:57 +0000 Subject: Replaces Python-style interpolation with arbitrary C++ string expression in MATCHER* descriptions. --- src/gmock-matchers.cc | 111 +++++--------------------------------------------- 1 file changed, 11 insertions(+), 100 deletions(-) (limited to 'src') diff --git a/src/gmock-matchers.cc b/src/gmock-matchers.cc index 0abca708..89007d9f 100644 --- a/src/gmock-matchers.cc +++ b/src/gmock-matchers.cc @@ -65,74 +65,6 @@ Matcher::Matcher(const char* s) { namespace internal { -// Utilities for validating and formatting description strings in the -// MATCHER*() macros. - -// Returns the 0-based index of the given parameter in the -// NULL-terminated parameter array; if the parameter is "*", returns -// kTupleInterpolation; if it's not found in the list, returns -// kInvalidInterpolation. -int GetParamIndex(const char* param_names[], const string& param_name) { - if (param_name == "*") - return kTupleInterpolation; - - for (int i = 0; param_names[i] != NULL; i++) { - if (param_name == param_names[i]) - return i; - } - return kInvalidInterpolation; -} - -// Helper function used by ValidateMatcherDescription() to format -// error messages. -string FormatMatcherDescriptionSyntaxError(const char* description, - const char* error_pos) { - ::std::stringstream ss; - ss << "Syntax error at index " << (error_pos - description) - << " in matcher description \"" << description << "\": "; - return ss.str(); -} - -// Parses a matcher description string and returns a vector of -// interpolations that appear in the string; generates non-fatal -// failures iff 'description' is an invalid matcher description. -// 'param_names' is a NULL-terminated array of parameter names in the -// order they appear in the MATCHER_P*() parameter list. -Interpolations ValidateMatcherDescription( - const char* param_names[], const char* description) { - Interpolations interps; - for (const char* p = description; *p != '\0';) { - if (SkipPrefix("%%", &p)) { - interps.push_back(Interpolation(p - 2, p, kPercentInterpolation)); - } else if (SkipPrefix("%(", &p)) { - const char* const q = strstr(p, ")s"); - if (q == NULL) { - // TODO(wan@google.com): change the source file location in - // the failure to point to where the MATCHER*() macro is used. - ADD_FAILURE() << FormatMatcherDescriptionSyntaxError(description, p - 2) - << "an interpolation must end with \")s\", " - << "but \"" << (p - 2) << "\" does not."; - } else { - const string param_name(p, q); - const int param_index = GetParamIndex(param_names, param_name); - if (param_index == kInvalidInterpolation) { - ADD_FAILURE() << FormatMatcherDescriptionSyntaxError(description, p) - << "\"" << param_name - << "\" is an invalid parameter name."; - } else { - interps.push_back(Interpolation(p - 2, q + 2, param_index)); - p = q + 2; - } - } - } else { - EXPECT_NE(*p, '%') << FormatMatcherDescriptionSyntaxError(description, p) - << "use \"%%\" instead of \"%\" to print \"%\"."; - ++p; - } - } - return interps; -} - // Joins a vector of strings as if they are fields of a tuple; returns // the joined string. string JoinAsTuple(const Strings& fields) { @@ -152,38 +84,17 @@ string JoinAsTuple(const Strings& fields) { } } -// Returns the actual matcher description, given the matcher name, -// user-supplied description template string, interpolations in the -// string, and the printed values of the matcher parameters. -string FormatMatcherDescription( - const char* matcher_name, const char* description, - const Interpolations& interp, const Strings& param_values) { - string result; - if (*description == '\0') { - // When the user supplies an empty description, we calculate one - // from the matcher name. - result = ConvertIdentifierNameToWords(matcher_name); - if (param_values.size() >= 1) - result += " " + JoinAsTuple(param_values); - } else { - // The end position of the last interpolation. - const char* last_interp_end = description; - for (size_t i = 0; i < interp.size(); i++) { - result.append(last_interp_end, interp[i].start_pos); - const int param_index = interp[i].param_index; - if (param_index == kTupleInterpolation) { - result += JoinAsTuple(param_values); - } else if (param_index == kPercentInterpolation) { - result += '%'; - } else if (param_index != kInvalidInterpolation) { - result += param_values[param_index]; - } - last_interp_end = interp[i].end_pos; - } - result += last_interp_end; - } - - return result; +// Returns the description for a matcher defined using the MATCHER*() +// macro where the user-supplied description string is "", if +// 'negation' is false; otherwise returns the description of the +// negation of the matcher. 'param_values' contains a list of strings +// that are the print-out of the matcher's parameters. +string FormatMatcherDescription(bool negation, const char* matcher_name, + const Strings& param_values) { + string result = ConvertIdentifierNameToWords(matcher_name); + if (param_values.size() >= 1) + result += " " + JoinAsTuple(param_values); + return negation ? "not (" + result + ")" : result; } } // namespace internal -- cgit v1.2.3 From 2516f60da9073f3b04c0bbfc37d3aefffe11767e Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Tue, 31 Aug 2010 18:28:02 +0000 Subject: Publishes GTEST_HAS_STREAM_REDIRECTION (by Vlad Losev); casts char to unsigned char before calling isspace() etc to avoid undefined behavior (by Zhanyong Wan); fixes the VC projects (by Fredrik Roubert). --- src/gmock-internal-utils.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/gmock-internal-utils.cc b/src/gmock-internal-utils.cc index cc51836b..9debe187 100644 --- a/src/gmock-internal-utils.cc +++ b/src/gmock-internal-utils.cc @@ -57,14 +57,14 @@ string ConvertIdentifierNameToWords(const char* id_name) { for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) { // We don't care about the current locale as the input is // guaranteed to be a valid C++ identifier name. - const bool starts_new_word = isupper(*p) || - (!isalpha(prev_char) && islower(*p)) || - (!isdigit(prev_char) && isdigit(*p)); + const bool starts_new_word = IsUpper(*p) || + (!IsAlpha(prev_char) && IsLower(*p)) || + (!IsDigit(prev_char) && IsDigit(*p)); - if (isalnum(*p)) { + if (IsAlNum(*p)) { if (starts_new_word && result != "") result += ' '; - result += static_cast(tolower(*p)); + result += ToLower(*p); } } return result; -- cgit v1.2.3 From 53e08c44dd34857ba57581d7c5774d6c96a8d0e1 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Tue, 14 Sep 2010 05:38:21 +0000 Subject: Include gtest and gmock headers as user headers instead of system headers. --- src/gmock-all.cc | 2 +- src/gmock-cardinalities.cc | 6 +++--- src/gmock-internal-utils.cc | 8 ++++---- src/gmock-matchers.cc | 4 ++-- src/gmock-spec-builders.cc | 6 +++--- src/gmock.cc | 4 ++-- src/gmock_main.cc | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/gmock-all.cc b/src/gmock-all.cc index 76118d88..7aebce7a 100644 --- a/src/gmock-all.cc +++ b/src/gmock-all.cc @@ -37,7 +37,7 @@ // This line ensures that gmock.h can be compiled on its own, even // when it's fused. -#include +#include "gmock/gmock.h" // The following lines pull in the real gmock *.cc files. #include "src/gmock-cardinalities.cc" diff --git a/src/gmock-cardinalities.cc b/src/gmock-cardinalities.cc index 07eed469..1a7902b4 100644 --- a/src/gmock-cardinalities.cc +++ b/src/gmock-cardinalities.cc @@ -33,14 +33,14 @@ // // This file implements cardinalities. -#include +#include "gmock/gmock-cardinalities.h" #include #include // NOLINT #include #include -#include -#include +#include "gmock/internal/gmock-internal-utils.h" +#include "gtest/gtest.h" namespace testing { diff --git a/src/gmock-internal-utils.cc b/src/gmock-internal-utils.cc index 9debe187..dd38132a 100644 --- a/src/gmock-internal-utils.cc +++ b/src/gmock-internal-utils.cc @@ -35,14 +35,14 @@ // Mock. They are subject to change without notice, so please DO NOT // USE THEM IN USER CODE. -#include +#include "gmock/internal/gmock-internal-utils.h" #include #include // NOLINT #include -#include -#include -#include +#include "gmock/gmock.h" +#include "gmock/internal/gmock-port.h" +#include "gtest/gtest.h" namespace testing { namespace internal { diff --git a/src/gmock-matchers.cc b/src/gmock-matchers.cc index 89007d9f..a5e6824d 100644 --- a/src/gmock-matchers.cc +++ b/src/gmock-matchers.cc @@ -34,8 +34,8 @@ // This file implements Matcher, Matcher, and // utilities for defining matchers. -#include -#include +#include "gmock/gmock-matchers.h" +#include "gmock/gmock-generated-matchers.h" #include #include diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index dab1a2c9..0d40d9cd 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -34,15 +34,15 @@ // This file implements the spec builder syntax (ON_CALL and // EXPECT_CALL). -#include +#include "gmock/gmock-spec-builders.h" #include #include // NOLINT #include #include #include -#include -#include +#include "gmock/gmock.h" +#include "gtest/gtest.h" #if GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC #include // NOLINT diff --git a/src/gmock.cc b/src/gmock.cc index f487265d..700bcb2e 100644 --- a/src/gmock.cc +++ b/src/gmock.cc @@ -29,8 +29,8 @@ // // Author: wan@google.com (Zhanyong Wan) -#include -#include +#include "gmock/gmock.h" +#include "gmock/internal/gmock-port.h" namespace testing { diff --git a/src/gmock_main.cc b/src/gmock_main.cc index 0a3071bf..3725ae72 100644 --- a/src/gmock_main.cc +++ b/src/gmock_main.cc @@ -30,8 +30,8 @@ // Author: wan@google.com (Zhanyong Wan) #include -#include -#include +#include "gmock/gmock.h" +#include "gtest/gtest.h" // MS C++ compiler/linker has a bug on Windows (not on Windows CE), which // causes a link error when _tmain is defined in a static library and UNICODE -- cgit v1.2.3 From ed6c9277bb12f2808bb812ae8f91492dac9517b4 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Wed, 23 Feb 2011 19:39:27 +0000 Subject: Makes Google Mock compile much faster and use much less memory; reviewed by Nico Weber. This fixes issue 68. --- src/gmock-spec-builders.cc | 338 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 335 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index 0d40d9cd..a99caef2 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -55,6 +55,15 @@ namespace internal { // mockers, and all expectations. GTEST_DEFINE_STATIC_MUTEX_(g_gmock_mutex); +// Logs a message including file and line number information. +void LogWithLocation(testing::internal::LogSeverity severity, + const char* file, int line, + const string& message) { + ::std::ostringstream s; + s << file << ":" << line << ": " << message << ::std::endl; + Log(severity, s.str(), 0); +} + // Constructs an ExpectationBase object. ExpectationBase::ExpectationBase(const char* a_file, int a_line, @@ -65,8 +74,12 @@ ExpectationBase::ExpectationBase(const char* a_file, cardinality_specified_(false), cardinality_(Exactly(1)), call_count_(0), - retired_(false) { -} + retired_(false), + extra_matcher_specified_(false), + repeated_action_specified_(false), + retires_on_saturation_(false), + last_clause_(kNone), + action_count_checked_(false) {} // Destructs an ExpectationBase object. ExpectationBase::~ExpectationBase() {} @@ -132,6 +145,99 @@ void ExpectationBase::FindUnsatisfiedPrerequisites( } } +// Describes how many times a function call matching this +// expectation has occurred. +// L >= g_gmock_mutex +void ExpectationBase::DescribeCallCountTo(::std::ostream* os) const { + g_gmock_mutex.AssertHeld(); + + // Describes how many times the function is expected to be called. + *os << " Expected: to be "; + cardinality().DescribeTo(os); + *os << "\n Actual: "; + Cardinality::DescribeActualCallCountTo(call_count(), os); + + // Describes the state of the expectation (e.g. is it satisfied? + // is it active?). + *os << " - " << (IsOverSaturated() ? "over-saturated" : + IsSaturated() ? "saturated" : + IsSatisfied() ? "satisfied" : "unsatisfied") + << " and " + << (is_retired() ? "retired" : "active"); +} + +// Checks the action count (i.e. the number of WillOnce() and +// WillRepeatedly() clauses) against the cardinality if this hasn't +// been done before. Prints a warning if there are too many or too +// few actions. +// L < mutex_ +void ExpectationBase::CheckActionCountIfNotDone() const { + bool should_check = false; + { + MutexLock l(&mutex_); + if (!action_count_checked_) { + action_count_checked_ = true; + should_check = true; + } + } + + if (should_check) { + if (!cardinality_specified_) { + // The cardinality was inferred - no need to check the action + // count against it. + return; + } + + // The cardinality was explicitly specified. + const int action_count = static_cast(untyped_actions_.size()); + const int upper_bound = cardinality().ConservativeUpperBound(); + const int lower_bound = cardinality().ConservativeLowerBound(); + bool too_many; // True if there are too many actions, or false + // if there are too few. + if (action_count > upper_bound || + (action_count == upper_bound && repeated_action_specified_)) { + too_many = true; + } else if (0 < action_count && action_count < lower_bound && + !repeated_action_specified_) { + too_many = false; + } else { + return; + } + + ::std::stringstream ss; + DescribeLocationTo(&ss); + ss << "Too " << (too_many ? "many" : "few") + << " actions specified in " << source_text() << "...\n" + << "Expected to be "; + cardinality().DescribeTo(&ss); + ss << ", but has " << (too_many ? "" : "only ") + << action_count << " WillOnce()" + << (action_count == 1 ? "" : "s"); + if (repeated_action_specified_) { + ss << " and a WillRepeatedly()"; + } + ss << "."; + Log(WARNING, ss.str(), -1); // -1 means "don't print stack trace". + } +} + +// Implements the .Times() clause. +void ExpectationBase::UntypedTimes(const Cardinality& a_cardinality) { + if (last_clause_ == kTimes) { + ExpectSpecProperty(false, + ".Times() cannot appear " + "more than once in an EXPECT_CALL()."); + } else { + ExpectSpecProperty(last_clause_ < kTimes, + ".Times() cannot appear after " + ".InSequence(), .WillOnce(), .WillRepeatedly(), " + "or .RetiresOnSaturation()."); + } + last_clause_ = kTimes; + + SpecifyCardinality(a_cardinality); +} + // Points to the implicit sequence introduced by a living InSequence // object (if any) in the current thread or NULL. ThreadLocal g_gmock_implicit_sequence; @@ -151,6 +257,233 @@ void ReportUninterestingCall(CallReaction reaction, const string& msg) { } } +UntypedFunctionMockerBase::UntypedFunctionMockerBase() + : mock_obj_(NULL), name_("") {} + +UntypedFunctionMockerBase::~UntypedFunctionMockerBase() {} + +// Sets the mock object this mock method belongs to, and registers +// this information in the global mock registry. Will be called +// whenever an EXPECT_CALL() or ON_CALL() is executed on this mock +// method. +// L < g_gmock_mutex +void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj) { + { + MutexLock l(&g_gmock_mutex); + mock_obj_ = mock_obj; + } + Mock::Register(mock_obj, this); +} + +// Sets the mock object this mock method belongs to, and sets the name +// of the mock function. Will be called upon each invocation of this +// mock function. +// L < g_gmock_mutex +void UntypedFunctionMockerBase::SetOwnerAndName( + const void* mock_obj, const char* name) { + // We protect name_ under g_gmock_mutex in case this mock function + // is called from two threads concurrently. + MutexLock l(&g_gmock_mutex); + mock_obj_ = mock_obj; + name_ = name; +} + +// Returns the name of the function being mocked. Must be called +// after RegisterOwner() or SetOwnerAndName() has been called. +// L < g_gmock_mutex +const void* UntypedFunctionMockerBase::MockObject() const { + const void* mock_obj; + { + // We protect mock_obj_ under g_gmock_mutex in case this mock + // function is called from two threads concurrently. + MutexLock l(&g_gmock_mutex); + Assert(mock_obj_ != NULL, __FILE__, __LINE__, + "MockObject() must not be called before RegisterOwner() or " + "SetOwnerAndName() has been called."); + mock_obj = mock_obj_; + } + return mock_obj; +} + +// Returns the name of this mock method. Must be called after +// SetOwnerAndName() has been called. +// L < g_gmock_mutex +const char* UntypedFunctionMockerBase::Name() const { + const char* name; + { + // We protect name_ under g_gmock_mutex in case this mock + // function is called from two threads concurrently. + MutexLock l(&g_gmock_mutex); + Assert(name_ != NULL, __FILE__, __LINE__, + "Name() must not be called before SetOwnerAndName() has " + "been called."); + name = name_; + } + return name; +} + +// Calculates the result of invoking this mock function with the given +// arguments, prints it, and returns it. The caller is responsible +// for deleting the result. +// L < g_gmock_mutex +const UntypedActionResultHolderBase* +UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) { + if (untyped_expectations_.size() == 0) { + // No expectation is set on this mock method - we have an + // uninteresting call. + + // We must get Google Mock's reaction on uninteresting calls + // made on this mock object BEFORE performing the action, + // because the action may DELETE the mock object and make the + // following expression meaningless. + const CallReaction reaction = + Mock::GetReactionOnUninterestingCalls(MockObject()); + + // True iff we need to print this call's arguments and return + // value. This definition must be kept in sync with + // the behavior of ReportUninterestingCall(). + const bool need_to_report_uninteresting_call = + // If the user allows this uninteresting call, we print it + // only when he wants informational messages. + reaction == ALLOW ? LogIsVisible(INFO) : + // If the user wants this to be a warning, we print it only + // when he wants to see warnings. + reaction == WARN ? LogIsVisible(WARNING) : + // Otherwise, the user wants this to be an error, and we + // should always print detailed information in the error. + true; + + if (!need_to_report_uninteresting_call) { + // Perform the action without printing the call information. + return this->UntypedPerformDefaultAction(untyped_args, ""); + } + + // Warns about the uninteresting call. + ::std::stringstream ss; + this->UntypedDescribeUninterestingCall(untyped_args, &ss); + + // Calculates the function result. + const UntypedActionResultHolderBase* const result = + this->UntypedPerformDefaultAction(untyped_args, ss.str()); + + // Prints the function result. + if (result != NULL) + result->PrintAsActionResult(&ss); + + ReportUninterestingCall(reaction, ss.str()); + return result; + } + + bool is_excessive = false; + ::std::stringstream ss; + ::std::stringstream why; + ::std::stringstream loc; + const void* untyped_action = NULL; + + // The UntypedFindMatchingExpectation() function acquires and + // releases g_gmock_mutex. + const ExpectationBase* const untyped_expectation = + this->UntypedFindMatchingExpectation( + untyped_args, &untyped_action, &is_excessive, + &ss, &why); + const bool found = untyped_expectation != NULL; + + // True iff we need to print the call's arguments and return value. + // This definition must be kept in sync with the uses of Expect() + // and Log() in this function. + const bool need_to_report_call = !found || is_excessive || LogIsVisible(INFO); + if (!need_to_report_call) { + // Perform the action without printing the call information. + return + untyped_action == NULL ? + this->UntypedPerformDefaultAction(untyped_args, "") : + this->UntypedPerformAction(untyped_action, untyped_args); + } + + ss << " Function call: " << Name(); + this->UntypedPrintArgs(untyped_args, &ss); + + // In case the action deletes a piece of the expectation, we + // generate the message beforehand. + if (found && !is_excessive) { + untyped_expectation->DescribeLocationTo(&loc); + } + + const UntypedActionResultHolderBase* const result = + untyped_action == NULL ? + this->UntypedPerformDefaultAction(untyped_args, ss.str()) : + this->UntypedPerformAction(untyped_action, untyped_args); + if (result != NULL) + result->PrintAsActionResult(&ss); + ss << "\n" << why.str(); + + if (!found) { + // No expectation matches this call - reports a failure. + Expect(false, NULL, -1, ss.str()); + } else if (is_excessive) { + // We had an upper-bound violation and the failure message is in ss. + Expect(false, untyped_expectation->file(), + untyped_expectation->line(), ss.str()); + } else { + // We had an expected call and the matching expectation is + // described in ss. + Log(INFO, loc.str() + ss.str(), 2); + } + + return result; +} + +// Returns an Expectation object that references and co-owns exp, +// which must be an expectation on this mock function. +Expectation UntypedFunctionMockerBase::GetHandleOf(ExpectationBase* exp) { + for (UntypedExpectations::const_iterator it = + untyped_expectations_.begin(); + it != untyped_expectations_.end(); ++it) { + if (it->get() == exp) { + return Expectation(*it); + } + } + + Assert(false, __FILE__, __LINE__, "Cannot find expectation."); + return Expectation(); + // The above statement is just to make the code compile, and will + // never be executed. +} + +// Verifies that all expectations on this mock function have been +// satisfied. Reports one or more Google Test non-fatal failures +// and returns false if not. +// L >= g_gmock_mutex +bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked() { + g_gmock_mutex.AssertHeld(); + bool expectations_met = true; + for (UntypedExpectations::const_iterator it = + untyped_expectations_.begin(); + it != untyped_expectations_.end(); ++it) { + ExpectationBase* const untyped_expectation = it->get(); + if (untyped_expectation->IsOverSaturated()) { + // There was an upper-bound violation. Since the error was + // already reported when it occurred, there is no need to do + // anything here. + expectations_met = false; + } else if (!untyped_expectation->IsSatisfied()) { + expectations_met = false; + ::std::stringstream ss; + ss << "Actual function call count doesn't match " + << untyped_expectation->source_text() << "...\n"; + // No need to show the source file location of the expectation + // in the description, as the Expect() call that follows already + // takes care of it. + untyped_expectation->MaybeDescribeExtraMatcherTo(&ss); + untyped_expectation->DescribeCallCountTo(&ss); + Expect(false, untyped_expectation->file(), + untyped_expectation->line(), ss.str()); + } + } + untyped_expectations_.clear(); + return expectations_met; +} + } // namespace internal // Class Mock. @@ -190,7 +523,6 @@ class MockObjectRegistry { // object alive. Therefore we report any living object as test // failure, unless the user explicitly asked us to ignore it. ~MockObjectRegistry() { - // "using ::std::cout;" doesn't work with Symbian's STLport, where cout is // a macro. -- cgit v1.2.3 From 658ac0b71a350cc833ee4520536b6c4964c7b944 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Thu, 24 Feb 2011 07:29:13 +0000 Subject: Indents preprocessor directives. --- src/gmock-spec-builders.cc | 2 +- src/gmock_main.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index a99caef2..aa33cc44 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -45,7 +45,7 @@ #include "gtest/gtest.h" #if GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC -#include // NOLINT +# include // NOLINT #endif namespace testing { diff --git a/src/gmock_main.cc b/src/gmock_main.cc index 3725ae72..9d8aea22 100644 --- a/src/gmock_main.cc +++ b/src/gmock_main.cc @@ -39,7 +39,7 @@ // Windows. See the following link to track the current status of this bug: // http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=394464 // NOLINT #if GTEST_OS_WINDOWS_MOBILE -#include // NOLINT +# include // NOLINT int _tmain(int argc, TCHAR** argv) { #else -- cgit v1.2.3 From 587c1b37c2f0b6d430fb13ce09326db0135b557c Mon Sep 17 00:00:00 2001 From: vladlosev Date: Fri, 20 May 2011 00:42:22 +0000 Subject: Adds support for building Google Mock as a shared library (DLL). --- src/gmock-cardinalities.cc | 10 +++++----- src/gmock-internal-utils.cc | 11 ++++++----- src/gmock-matchers.cc | 7 ++++--- src/gmock-spec-builders.cc | 10 +++++----- src/gmock.cc | 4 ++-- src/gmock_main.cc | 4 ++-- 6 files changed, 24 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/gmock-cardinalities.cc b/src/gmock-cardinalities.cc index 1a7902b4..274f98a9 100644 --- a/src/gmock-cardinalities.cc +++ b/src/gmock-cardinalities.cc @@ -136,20 +136,20 @@ void Cardinality::DescribeActualCallCountTo(int actual_call_count, } // Creates a cardinality that allows at least n calls. -Cardinality AtLeast(int n) { return Between(n, INT_MAX); } +GTEST_API_ Cardinality AtLeast(int n) { return Between(n, INT_MAX); } // Creates a cardinality that allows at most n calls. -Cardinality AtMost(int n) { return Between(0, n); } +GTEST_API_ Cardinality AtMost(int n) { return Between(0, n); } // Creates a cardinality that allows any number of calls. -Cardinality AnyNumber() { return AtLeast(0); } +GTEST_API_ Cardinality AnyNumber() { return AtLeast(0); } // Creates a cardinality that allows between min and max calls. -Cardinality Between(int min, int max) { +GTEST_API_ Cardinality Between(int min, int max) { return Cardinality(new BetweenCardinalityImpl(min, max)); } // Creates a cardinality that allows exactly n calls. -Cardinality Exactly(int n) { return Between(n, n); } +GTEST_API_ Cardinality Exactly(int n) { return Between(n, n); } } // namespace testing diff --git a/src/gmock-internal-utils.cc b/src/gmock-internal-utils.cc index dd38132a..470fc447 100644 --- a/src/gmock-internal-utils.cc +++ b/src/gmock-internal-utils.cc @@ -51,7 +51,7 @@ namespace internal { // words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is // treated as one word. For example, both "FooBar123" and // "foo_bar_123" are converted to "foo bar 123". -string ConvertIdentifierNameToWords(const char* id_name) { +GTEST_API_ string ConvertIdentifierNameToWords(const char* id_name) { string result; char prev_char = '\0'; for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) { @@ -91,7 +91,7 @@ class GoogleTestFailureReporter : public FailureReporterInterface { // Returns the global failure reporter. Will create a // GoogleTestFailureReporter and return it the first time called. -FailureReporterInterface* GetFailureReporter() { +GTEST_API_ FailureReporterInterface* GetFailureReporter() { // Points to the global failure reporter used by Google Mock. gcc // guarantees that the following use of failure_reporter is // thread-safe. We may need to add additional synchronization to @@ -107,7 +107,7 @@ 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. -bool LogIsVisible(LogSeverity severity) { +GTEST_API_ bool LogIsVisible(LogSeverity severity) { if (GMOCK_FLAG(verbose) == kInfoVerbosity) { // Always show the log if --gmock_verbose=info. return true; @@ -128,8 +128,9 @@ bool LogIsVisible(LogSeverity severity) { // stack_frames_to_skip is treated as 0, since we don't know which // function calls will be inlined by the compiler and need to be // conservative. -void Log(LogSeverity severity, const string& message, - int stack_frames_to_skip) { +GTEST_API_ void Log(LogSeverity severity, + const string& message, + int stack_frames_to_skip) { if (!LogIsVisible(severity)) return; diff --git a/src/gmock-matchers.cc b/src/gmock-matchers.cc index a5e6824d..63f3859b 100644 --- a/src/gmock-matchers.cc +++ b/src/gmock-matchers.cc @@ -67,7 +67,7 @@ namespace internal { // Joins a vector of strings as if they are fields of a tuple; returns // the joined string. -string JoinAsTuple(const Strings& fields) { +GTEST_API_ string JoinAsTuple(const Strings& fields) { switch (fields.size()) { case 0: return ""; @@ -89,8 +89,9 @@ string JoinAsTuple(const Strings& fields) { // 'negation' is false; otherwise returns the description of the // negation of the matcher. 'param_values' contains a list of strings // that are the print-out of the matcher's parameters. -string FormatMatcherDescription(bool negation, const char* matcher_name, - const Strings& param_values) { +GTEST_API_ string FormatMatcherDescription(bool negation, + const char* matcher_name, + const Strings& param_values) { string result = ConvertIdentifierNameToWords(matcher_name); if (param_values.size() >= 1) result += " " + JoinAsTuple(param_values); diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index aa33cc44..c192f96c 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -53,12 +53,12 @@ namespace internal { // Protects the mock object registry (in class Mock), all function // mockers, and all expectations. -GTEST_DEFINE_STATIC_MUTEX_(g_gmock_mutex); +GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_gmock_mutex); // Logs a message including file and line number information. -void LogWithLocation(testing::internal::LogSeverity severity, - const char* file, int line, - const string& message) { +GTEST_API_ void LogWithLocation(testing::internal::LogSeverity severity, + const char* file, int line, + const string& message) { ::std::ostringstream s; s << file << ":" << line << ": " << message << ::std::endl; Log(severity, s.str(), 0); @@ -240,7 +240,7 @@ void ExpectationBase::UntypedTimes(const Cardinality& a_cardinality) { // Points to the implicit sequence introduced by a living InSequence // object (if any) in the current thread or NULL. -ThreadLocal g_gmock_implicit_sequence; +GTEST_API_ ThreadLocal g_gmock_implicit_sequence; // Reports an uninteresting call (whose description is in msg) in the // manner specified by 'reaction'. diff --git a/src/gmock.cc b/src/gmock.cc index 700bcb2e..e06acc5c 100644 --- a/src/gmock.cc +++ b/src/gmock.cc @@ -169,13 +169,13 @@ void InitGoogleMockImpl(int* argc, CharType** argv) { // Since Google Test is needed for Google Mock to work, this function // also initializes Google Test and parses its flags, if that hasn't // been done. -void InitGoogleMock(int* argc, char** argv) { +GTEST_API_ void InitGoogleMock(int* argc, char** argv) { internal::InitGoogleMockImpl(argc, argv); } // This overloaded version can be used in Windows programs compiled in // UNICODE mode. -void InitGoogleMock(int* argc, wchar_t** argv) { +GTEST_API_ void InitGoogleMock(int* argc, wchar_t** argv) { internal::InitGoogleMockImpl(argc, argv); } diff --git a/src/gmock_main.cc b/src/gmock_main.cc index 9d8aea22..bd5be03b 100644 --- a/src/gmock_main.cc +++ b/src/gmock_main.cc @@ -41,9 +41,9 @@ #if GTEST_OS_WINDOWS_MOBILE # include // NOLINT -int _tmain(int argc, TCHAR** argv) { +GTEST_API_ int _tmain(int argc, TCHAR** argv) { #else -int main(int argc, char** argv) { +GTEST_API_ int main(int argc, char** argv) { #endif // GTEST_OS_WINDOWS_MOBILE std::cout << "Running main() from gmock_main.cc\n"; // Since Google Mock depends on Google Test, InitGoogleMock() is -- cgit v1.2.3 From 4d60a596b4135c5a7e21ef7b4fe24a5c90329e0f Mon Sep 17 00:00:00 2001 From: vladlosev Date: Mon, 24 Oct 2011 21:16:22 +0000 Subject: Expressed the thread-safety annotations in code, replacing the existing comment-based system (by Aaron Jacobs). --- src/gmock-spec-builders.cc | 104 ++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index c192f96c..06299784 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -92,7 +92,8 @@ void ExpectationBase::SpecifyCardinality(const Cardinality& a_cardinality) { } // Retires all pre-requisites of this expectation. -void ExpectationBase::RetireAllPreRequisites() { +void ExpectationBase::RetireAllPreRequisites() + GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { if (is_retired()) { // We can take this short-cut as we never retire an expectation // until we have retired all its pre-requisites. @@ -111,8 +112,8 @@ void ExpectationBase::RetireAllPreRequisites() { // Returns true iff all pre-requisites of this expectation have been // satisfied. -// L >= g_gmock_mutex -bool ExpectationBase::AllPrerequisitesAreSatisfied() const { +bool ExpectationBase::AllPrerequisitesAreSatisfied() const + GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin(); it != immediate_prerequisites_.end(); ++it) { @@ -124,9 +125,8 @@ bool ExpectationBase::AllPrerequisitesAreSatisfied() const { } // Adds unsatisfied pre-requisites of this expectation to 'result'. -// L >= g_gmock_mutex -void ExpectationBase::FindUnsatisfiedPrerequisites( - ExpectationSet* result) const { +void ExpectationBase::FindUnsatisfiedPrerequisites(ExpectationSet* result) const + GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin(); it != immediate_prerequisites_.end(); ++it) { @@ -147,8 +147,8 @@ void ExpectationBase::FindUnsatisfiedPrerequisites( // Describes how many times a function call matching this // expectation has occurred. -// L >= g_gmock_mutex -void ExpectationBase::DescribeCallCountTo(::std::ostream* os) const { +void ExpectationBase::DescribeCallCountTo(::std::ostream* os) const + GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); // Describes how many times the function is expected to be called. @@ -170,8 +170,8 @@ void ExpectationBase::DescribeCallCountTo(::std::ostream* os) const { // WillRepeatedly() clauses) against the cardinality if this hasn't // been done before. Prints a warning if there are too many or too // few actions. -// L < mutex_ -void ExpectationBase::CheckActionCountIfNotDone() const { +void ExpectationBase::CheckActionCountIfNotDone() const + GTEST_LOCK_EXCLUDED_(mutex_) { bool should_check = false; { MutexLock l(&mutex_); @@ -266,8 +266,8 @@ UntypedFunctionMockerBase::~UntypedFunctionMockerBase() {} // this information in the global mock registry. Will be called // whenever an EXPECT_CALL() or ON_CALL() is executed on this mock // method. -// L < g_gmock_mutex -void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj) { +void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj) + GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { { MutexLock l(&g_gmock_mutex); mock_obj_ = mock_obj; @@ -278,9 +278,9 @@ void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj) { // Sets the mock object this mock method belongs to, and sets the name // of the mock function. Will be called upon each invocation of this // mock function. -// L < g_gmock_mutex -void UntypedFunctionMockerBase::SetOwnerAndName( - const void* mock_obj, const char* name) { +void UntypedFunctionMockerBase::SetOwnerAndName(const void* mock_obj, + const char* name) + GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { // We protect name_ under g_gmock_mutex in case this mock function // is called from two threads concurrently. MutexLock l(&g_gmock_mutex); @@ -290,8 +290,8 @@ void UntypedFunctionMockerBase::SetOwnerAndName( // Returns the name of the function being mocked. Must be called // after RegisterOwner() or SetOwnerAndName() has been called. -// L < g_gmock_mutex -const void* UntypedFunctionMockerBase::MockObject() const { +const void* UntypedFunctionMockerBase::MockObject() const + GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { const void* mock_obj; { // We protect mock_obj_ under g_gmock_mutex in case this mock @@ -307,8 +307,8 @@ const void* UntypedFunctionMockerBase::MockObject() const { // Returns the name of this mock method. Must be called after // SetOwnerAndName() has been called. -// L < g_gmock_mutex -const char* UntypedFunctionMockerBase::Name() const { +const char* UntypedFunctionMockerBase::Name() const + GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { const char* name; { // We protect name_ under g_gmock_mutex in case this mock @@ -325,9 +325,9 @@ const char* UntypedFunctionMockerBase::Name() const { // Calculates the result of invoking this mock function with the given // arguments, prints it, and returns it. The caller is responsible // for deleting the result. -// L < g_gmock_mutex const UntypedActionResultHolderBase* -UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) { +UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) + GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { if (untyped_expectations_.size() == 0) { // No expectation is set on this mock method - we have an // uninteresting call. @@ -453,8 +453,8 @@ Expectation UntypedFunctionMockerBase::GetHandleOf(ExpectationBase* exp) { // Verifies that all expectations on this mock function have been // satisfied. Reports one or more Google Test non-fatal failures // and returns false if not. -// L >= g_gmock_mutex -bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked() { +bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked() + GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); bool expectations_met = true; for (UntypedExpectations::const_iterator it = @@ -578,9 +578,9 @@ std::map g_uninteresting_call_reaction; // Sets the reaction Google Mock should have when an uninteresting // method of the given mock object is called. -// L < g_gmock_mutex void SetReactionOnUninterestingCalls(const void* mock_obj, - internal::CallReaction reaction) { + internal::CallReaction reaction) + GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { internal::MutexLock l(&internal::g_gmock_mutex); g_uninteresting_call_reaction[mock_obj] = reaction; } @@ -589,38 +589,38 @@ void SetReactionOnUninterestingCalls(const void* mock_obj, // Tells Google Mock to allow uninteresting calls on the given mock // object. -// L < g_gmock_mutex -void Mock::AllowUninterestingCalls(const void* mock_obj) { +void Mock::AllowUninterestingCalls(const void* mock_obj) + GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { SetReactionOnUninterestingCalls(mock_obj, internal::ALLOW); } // Tells Google Mock to warn the user about uninteresting calls on the // given mock object. -// L < g_gmock_mutex -void Mock::WarnUninterestingCalls(const void* mock_obj) { +void Mock::WarnUninterestingCalls(const void* mock_obj) + GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { SetReactionOnUninterestingCalls(mock_obj, internal::WARN); } // Tells Google Mock to fail uninteresting calls on the given mock // object. -// L < g_gmock_mutex -void Mock::FailUninterestingCalls(const void* mock_obj) { +void Mock::FailUninterestingCalls(const void* mock_obj) + GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { SetReactionOnUninterestingCalls(mock_obj, internal::FAIL); } // Tells Google Mock the given mock object is being destroyed and its // entry in the call-reaction table should be removed. -// L < g_gmock_mutex -void Mock::UnregisterCallReaction(const void* mock_obj) { +void Mock::UnregisterCallReaction(const void* mock_obj) + GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { internal::MutexLock l(&internal::g_gmock_mutex); g_uninteresting_call_reaction.erase(mock_obj); } // Returns the reaction Google Mock will have on uninteresting calls // made on the given mock object. -// L < g_gmock_mutex internal::CallReaction Mock::GetReactionOnUninterestingCalls( - const void* mock_obj) { + const void* mock_obj) + GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { internal::MutexLock l(&internal::g_gmock_mutex); return (g_uninteresting_call_reaction.count(mock_obj) == 0) ? internal::WARN : g_uninteresting_call_reaction[mock_obj]; @@ -628,8 +628,8 @@ internal::CallReaction Mock::GetReactionOnUninterestingCalls( // Tells Google Mock to ignore mock_obj when checking for leaked mock // objects. -// L < g_gmock_mutex -void Mock::AllowLeak(const void* mock_obj) { +void Mock::AllowLeak(const void* mock_obj) + GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { internal::MutexLock l(&internal::g_gmock_mutex); g_mock_object_registry.states()[mock_obj].leakable = true; } @@ -637,8 +637,8 @@ void Mock::AllowLeak(const void* mock_obj) { // Verifies and clears all expectations on the given mock object. If // the expectations aren't satisfied, generates one or more Google // Test non-fatal failures and returns false. -// L < g_gmock_mutex -bool Mock::VerifyAndClearExpectations(void* mock_obj) { +bool Mock::VerifyAndClearExpectations(void* mock_obj) + GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { internal::MutexLock l(&internal::g_gmock_mutex); return VerifyAndClearExpectationsLocked(mock_obj); } @@ -646,8 +646,8 @@ bool Mock::VerifyAndClearExpectations(void* mock_obj) { // Verifies all expectations on the given mock object and clears its // default actions and expectations. Returns true iff the // verification was successful. -// L < g_gmock_mutex -bool Mock::VerifyAndClear(void* mock_obj) { +bool Mock::VerifyAndClear(void* mock_obj) + GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { internal::MutexLock l(&internal::g_gmock_mutex); ClearDefaultActionsLocked(mock_obj); return VerifyAndClearExpectationsLocked(mock_obj); @@ -656,8 +656,8 @@ bool Mock::VerifyAndClear(void* mock_obj) { // Verifies and clears all expectations on the given mock object. If // the expectations aren't satisfied, generates one or more Google // Test non-fatal failures and returns false. -// L >= g_gmock_mutex -bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj) { +bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj) + GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) { internal::g_gmock_mutex.AssertHeld(); if (g_mock_object_registry.states().count(mock_obj) == 0) { // No EXPECT_CALL() was set on the given mock object. @@ -682,9 +682,9 @@ bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj) { } // Registers a mock object and a mock method it owns. -// L < g_gmock_mutex void Mock::Register(const void* mock_obj, - internal::UntypedFunctionMockerBase* mocker) { + internal::UntypedFunctionMockerBase* mocker) + GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { internal::MutexLock l(&internal::g_gmock_mutex); g_mock_object_registry.states()[mock_obj].function_mockers.insert(mocker); } @@ -692,9 +692,9 @@ void Mock::Register(const void* mock_obj, // Tells Google Mock where in the source code mock_obj is used in an // ON_CALL or EXPECT_CALL. In case mock_obj is leaked, this // information helps the user identify which object it is. -// L < g_gmock_mutex -void Mock::RegisterUseByOnCallOrExpectCall( - const void* mock_obj, const char* file, int line) { +void Mock::RegisterUseByOnCallOrExpectCall(const void* mock_obj, + const char* file, int line) + GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { internal::MutexLock l(&internal::g_gmock_mutex); MockObjectState& state = g_mock_object_registry.states()[mock_obj]; if (state.first_used_file == NULL) { @@ -716,8 +716,8 @@ void Mock::RegisterUseByOnCallOrExpectCall( // registry when the last mock method associated with it has been // unregistered. This is called only in the destructor of // FunctionMockerBase. -// L >= g_gmock_mutex -void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker) { +void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker) + GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) { internal::g_gmock_mutex.AssertHeld(); for (MockObjectRegistry::StateMap::iterator it = g_mock_object_registry.states().begin(); @@ -734,8 +734,8 @@ void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker) { } // Clears all ON_CALL()s set on the given mock object. -// L >= g_gmock_mutex -void Mock::ClearDefaultActionsLocked(void* mock_obj) { +void Mock::ClearDefaultActionsLocked(void* mock_obj) + GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) { internal::g_gmock_mutex.AssertHeld(); if (g_mock_object_registry.states().count(mock_obj) == 0) { -- cgit v1.2.3 From 9bcb5f9146db42bc38b6bb744fb0cf518a0205be Mon Sep 17 00:00:00 2001 From: vladlosev Date: Mon, 24 Oct 2011 23:41:07 +0000 Subject: Fixes a lock reentrancy when destroying a mock causes destruction of another mock (issue 79) (by Aaron Jacobs). --- src/gmock-spec-builders.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index 06299784..6599325d 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -480,7 +480,21 @@ bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked() untyped_expectation->line(), ss.str()); } } - untyped_expectations_.clear(); + + // Deleting our expectations may trigger other mock objects to be deleted, for + // example if an action contains a reference counted smart pointer to that + // mock object, and that is the last reference. So if we delete our + // expectations within the context of the global mutex we may deadlock when + // this method is called again. Instead, make a copy of the set of + // expectations to delete, clear our set within the mutex, and then clear the + // copied set outside of it. + UntypedExpectations expectations_to_delete; + untyped_expectations_.swap(expectations_to_delete); + + g_gmock_mutex.Unlock(); + expectations_to_delete.clear(); + g_gmock_mutex.Lock(); + return expectations_met; } -- cgit v1.2.3 From 79a367eb217fcd47e2beaf8c0f87fe6d5926f739 Mon Sep 17 00:00:00 2001 From: jgm Date: Tue, 10 Apr 2012 16:02:11 +0000 Subject: Reduced template instantiation depth for the AllOf and AnyOf matchers. Also some formatting changes. --- src/gmock-cardinalities.cc | 3 ++- src/gmock-spec-builders.cc | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gmock-cardinalities.cc b/src/gmock-cardinalities.cc index 274f98a9..50ec7286 100644 --- a/src/gmock-cardinalities.cc +++ b/src/gmock-cardinalities.cc @@ -75,7 +75,7 @@ class BetweenCardinalityImpl : public CardinalityInterface { virtual int ConservativeUpperBound() const { return max_; } virtual bool IsSatisfiedByCallCount(int call_count) const { - return min_ <= call_count && call_count <= max_ ; + return min_ <= call_count && call_count <= max_; } virtual bool IsSaturatedByCallCount(int call_count) const { @@ -83,6 +83,7 @@ class BetweenCardinalityImpl : public CardinalityInterface { } virtual void DescribeTo(::std::ostream* os) const; + private: const int min_; const int max_; diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index 6599325d..a93ea71a 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -579,6 +579,7 @@ class MockObjectRegistry { } StateMap& states() { return states_; } + private: StateMap states_; }; -- cgit v1.2.3 From 2fd619edd3d1ec053f6276debdb513f1122ebcf3 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Thu, 31 May 2012 20:40:56 +0000 Subject: Pulls in gtest r615. Renames internal enums to the kFoo naming style. Fixes gmock doctor to work with newer versions of Clang. --- src/gmock-internal-utils.cc | 8 ++++---- src/gmock-spec-builders.cc | 27 ++++++++++++++------------- 2 files changed, 18 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/gmock-internal-utils.cc b/src/gmock-internal-utils.cc index 470fc447..fb530801 100644 --- a/src/gmock-internal-utils.cc +++ b/src/gmock-internal-utils.cc @@ -77,13 +77,13 @@ class GoogleTestFailureReporter : public FailureReporterInterface { public: virtual void ReportFailure(FailureType type, const char* file, int line, const string& message) { - AssertHelper(type == FATAL ? + AssertHelper(type == kFatal ? TestPartResult::kFatalFailure : TestPartResult::kNonFatalFailure, file, line, message.c_str()) = Message(); - if (type == FATAL) { + if (type == kFatal) { posix::Abort(); } } @@ -117,7 +117,7 @@ GTEST_API_ bool LogIsVisible(LogSeverity severity) { } else { // If --gmock_verbose is neither "info" nor "error", we treat it // as "warning" (its default value). - return severity == WARNING; + return severity == kWarning; } } @@ -140,7 +140,7 @@ GTEST_API_ void Log(LogSeverity severity, // "using ::std::cout;" doesn't work with Symbian's STLport, where cout is a // macro. - if (severity == WARNING) { + if (severity == kWarning) { // Prints a GMOCK WARNING marker to make the warnings easily searchable. std::cout << "\nGMOCK WARNING:"; } diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index a93ea71a..9fcb61ea 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -217,7 +217,7 @@ void ExpectationBase::CheckActionCountIfNotDone() const ss << " and a WillRepeatedly()"; } ss << "."; - Log(WARNING, ss.str(), -1); // -1 means "don't print stack trace". + Log(kWarning, ss.str(), -1); // -1 means "don't print stack trace". } } @@ -246,11 +246,11 @@ GTEST_API_ ThreadLocal g_gmock_implicit_sequence; // manner specified by 'reaction'. void ReportUninterestingCall(CallReaction reaction, const string& msg) { switch (reaction) { - case ALLOW: - Log(INFO, msg, 3); + case kAllow: + Log(kInfo, msg, 3); break; - case WARN: - Log(WARNING, msg, 3); + case kWarn: + Log(kWarning, msg, 3); break; default: // FAIL Expect(false, NULL, -1, msg); @@ -345,10 +345,10 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) const bool need_to_report_uninteresting_call = // If the user allows this uninteresting call, we print it // only when he wants informational messages. - reaction == ALLOW ? LogIsVisible(INFO) : + reaction == kAllow ? LogIsVisible(kInfo) : // If the user wants this to be a warning, we print it only // when he wants to see warnings. - reaction == WARN ? LogIsVisible(WARNING) : + reaction == kWarn ? LogIsVisible(kWarning) : // Otherwise, the user wants this to be an error, and we // should always print detailed information in the error. true; @@ -391,7 +391,8 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) // True iff we need to print the call's arguments and return value. // This definition must be kept in sync with the uses of Expect() // and Log() in this function. - const bool need_to_report_call = !found || is_excessive || LogIsVisible(INFO); + const bool need_to_report_call = + !found || is_excessive || LogIsVisible(kInfo); if (!need_to_report_call) { // Perform the action without printing the call information. return @@ -427,7 +428,7 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) } else { // We had an expected call and the matching expectation is // described in ss. - Log(INFO, loc.str() + ss.str(), 2); + Log(kInfo, loc.str() + ss.str(), 2); } return result; @@ -606,21 +607,21 @@ void SetReactionOnUninterestingCalls(const void* mock_obj, // object. void Mock::AllowUninterestingCalls(const void* mock_obj) GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { - SetReactionOnUninterestingCalls(mock_obj, internal::ALLOW); + SetReactionOnUninterestingCalls(mock_obj, internal::kAllow); } // Tells Google Mock to warn the user about uninteresting calls on the // given mock object. void Mock::WarnUninterestingCalls(const void* mock_obj) GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { - SetReactionOnUninterestingCalls(mock_obj, internal::WARN); + SetReactionOnUninterestingCalls(mock_obj, internal::kWarn); } // Tells Google Mock to fail uninteresting calls on the given mock // object. void Mock::FailUninterestingCalls(const void* mock_obj) GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { - SetReactionOnUninterestingCalls(mock_obj, internal::FAIL); + SetReactionOnUninterestingCalls(mock_obj, internal::kFail); } // Tells Google Mock the given mock object is being destroyed and its @@ -638,7 +639,7 @@ internal::CallReaction Mock::GetReactionOnUninterestingCalls( GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { internal::MutexLock l(&internal::g_gmock_mutex); return (g_uninteresting_call_reaction.count(mock_obj) == 0) ? - internal::WARN : g_uninteresting_call_reaction[mock_obj]; + internal::kWarn : g_uninteresting_call_reaction[mock_obj]; } // Tells Google Mock to ignore mock_obj when checking for leaked mock -- cgit v1.2.3 From 38513a8bb154f0b6d0a4088814fe92552696d465 Mon Sep 17 00:00:00 2001 From: jgm Date: Thu, 15 Nov 2012 15:50:36 +0000 Subject: Unfortunately, the svn repo is a bit out of date. This commit contains 8 changes that haven't made it to svn. The descriptions of each change are listed below. - Fixes some python shebang lines. - Add ElementsAreArray overloads to gmock. ElementsAreArray now makes a copy of its input elements before the conversion to a Matcher. ElementsAreArray can now take a vector as input. ElementsAreArray can now take an iterator pair as input. - Templatize MatchAndExplain to allow independent string types for the matcher and matchee. I also templatized the ConstCharPointer version of MatchAndExplain to avoid calls with "char*" from using the new templated MatchAndExplain. - Fixes the bug where the constructor of the return type of ElementsAre() saves a reference instead of a copy of the arguments. - Extends ElementsAre() to accept arrays whose sizes aren't known. - Switches gTest's internal FilePath class from testing::internal::String to std::string. testing::internal::String was introduced when gTest couldn't depend on std::string. It's now deprecated. - Switches gTest & gMock from using testing::internal::String objects to std::string. Some static methods of String are still in use. We may be able to remove some but not all of them. In particular, String::Format() should eventually be removed as it truncates the result at 4096 characters, often causing problems. --- src/gmock.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gmock.cc b/src/gmock.cc index e06acc5c..1c06985d 100644 --- a/src/gmock.cc +++ b/src/gmock.cc @@ -62,7 +62,7 @@ static const char* ParseGoogleMockFlagValue(const char* str, if (str == NULL || flag == NULL) return NULL; // The flag must start with "--gmock_". - const String flag_str = String::Format("--gmock_%s", flag); + const std::string flag_str = std::string("--gmock_") + flag; const size_t flag_len = flag_str.length(); if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL; @@ -107,7 +107,7 @@ static bool ParseGoogleMockBoolFlag(const char* str, const char* flag, // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. static bool ParseGoogleMockStringFlag(const char* str, const char* flag, - String* value) { + std::string* value) { // Gets the value of the flag as a string. const char* const value_str = ParseGoogleMockFlagValue(str, flag, false); @@ -131,7 +131,7 @@ void InitGoogleMockImpl(int* argc, CharType** argv) { if (*argc <= 0) return; for (int i = 1; i != *argc; i++) { - const String arg_string = StreamableToString(argv[i]); + const std::string arg_string = StreamableToString(argv[i]); const char* const arg = arg_string.c_str(); // Do we see a Google Mock flag? -- cgit v1.2.3 From c896504e4175f08cd229ea151861558ba9380f50 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Fri, 1 Mar 2013 07:10:07 +0000 Subject: Improves the tests for nice, naggy, and strict mocks. --- src/gmock-spec-builders.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index 9fcb61ea..abaae3ad 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -639,7 +639,7 @@ internal::CallReaction Mock::GetReactionOnUninterestingCalls( GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) { internal::MutexLock l(&internal::g_gmock_mutex); return (g_uninteresting_call_reaction.count(mock_obj) == 0) ? - internal::kWarn : g_uninteresting_call_reaction[mock_obj]; + internal::kDefault : g_uninteresting_call_reaction[mock_obj]; } // Tells Google Mock to ignore mock_obj when checking for leaked mock -- cgit v1.2.3 From 1f122a06e6aad4d234123d2d8c1e352029ce0742 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Mon, 25 Mar 2013 16:27:03 +0000 Subject: Adds special support for matching StringPiece. Pulls in gtest r646. --- src/gmock-matchers.cc | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'src') diff --git a/src/gmock-matchers.cc b/src/gmock-matchers.cc index 63f3859b..5f746b95 100644 --- a/src/gmock-matchers.cc +++ b/src/gmock-matchers.cc @@ -63,6 +63,41 @@ Matcher::Matcher(const char* s) { *this = Eq(internal::string(s)); } +#if GTEST_HAS_STRING_PIECE_ +// Constructs a matcher that matches a const StringPiece& whose value is +// equal to s. +Matcher::Matcher(const internal::string& s) { + *this = Eq(s); +} + +// Constructs a matcher that matches a const StringPiece& whose value is +// equal to s. +Matcher::Matcher(const char* s) { + *this = Eq(internal::string(s)); +} + +// Constructs a matcher that matches a const StringPiece& whose value is +// equal to s. +Matcher::Matcher(StringPiece s) { + *this = Eq(s.ToString()); +} + +// Constructs a matcher that matches a StringPiece whose value is equal to s. +Matcher::Matcher(const internal::string& s) { + *this = Eq(s); +} + +// Constructs a matcher that matches a StringPiece whose value is equal to s. +Matcher::Matcher(const char* s) { + *this = Eq(internal::string(s)); +} + +// Constructs a matcher that matches a StringPiece whose value is equal to s. +Matcher::Matcher(StringPiece s) { + *this = Eq(s.ToString()); +} +#endif // GTEST_HAS_STRING_PIECE_ + namespace internal { // Joins a vector of strings as if they are fields of a tuple; returns -- cgit v1.2.3 From fb25d5391143a0fd4cbce862f19472ddc2a1ecab Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Sun, 28 Jul 2013 08:24:00 +0000 Subject: Adds matchers UnorderedElementsAre[Array]() (by Billy Donahue); pulls in gtest r660. --- src/gmock-matchers.cc | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 361 insertions(+) (limited to 'src') diff --git a/src/gmock-matchers.cc b/src/gmock-matchers.cc index 5f746b95..9ed29abf 100644 --- a/src/gmock-matchers.cc +++ b/src/gmock-matchers.cc @@ -133,5 +133,366 @@ GTEST_API_ string FormatMatcherDescription(bool negation, return negation ? "not (" + result + ")" : result; } +// FindMaxBipartiteMatching and its helper class. +// +// Uses the well-known Ford-Fulkerson max flow method to find a maximum +// bipartite matching. Flow is considered to be from left to right. +// There is an implicit source node that is connected to all of the left +// nodes, and an implicit sink node that is connected to all of the +// right nodes. All edges have unit capacity. +// +// Neither the flow graph nor the residual flow graph are represented +// explicitly. Instead, they are implied by the information in 'graph' and +// a vector called 'left_' whose elements are initialized to the +// value kUnused. This represents the initial state of the algorithm, +// where the flow graph is empty, and the residual flow graph has the +// following edges: +// - An edge from source to each left_ node +// - An edge from each right_ node to sink +// - An edge from each left_ node to each right_ node, if the +// corresponding edge exists in 'graph'. +// +// When the TryAugment() method adds a flow, it sets left_[l] = r for some +// nodes l and r. This induces the following changes: +// - The edges (source, l), (l, r), and (r, sink) are added to the +// flow graph. +// - The same three edges are removed from the residual flow graph. +// - The reverse edges (l, source), (r, l), and (sink, r) are added +// to the residual flow graph, which is a directional graph +// representing unused flow capacity. +// +// When the method augments a flow (moving left_[l] from some r1 to some +// other r2), this can be thought of as "undoing" the above steps with +// respect to r1 and "redoing" them with respect to r2. +// +// It bears repeating that the flow graph and residual flow graph are +// never represented explicitly, but can be derived by looking at the +// information in 'graph' and in left_. +// +// As an optimization, there is a second vector called right_ which +// does not provide any new information. Instead, it enables more +// efficient queries about edges entering or leaving the right-side nodes +// of the flow or residual flow graphs. The following invariants are +// maintained: +// +// left[l] == kUnused or right[left[l]] == l +// right[r] == kUnused or left[right[r]] == r +// +// . [ source ] . +// . ||| . +// . ||| . +// . ||\--> left[0]=1 ---\ right[0]=-1 ----\ . +// . || | | . +// . |\---> left[1]=-1 \--> right[1]=0 ---\| . +// . | || . +// . \----> left[2]=2 ------> right[2]=2 --\|| . +// . ||| . +// . elements matchers vvv . +// . [ sink ] . +// +// See Also: +// [1] Cormen, et al (2001). "Section 26.2: The Ford–Fulkerson method". +// "Introduction to Algorithms (Second ed.)", pp. 651–664. +// [2] "Ford–Fulkerson algorithm", Wikipedia, +// 'http://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm' +class MaxBipartiteMatchState { + public: + explicit MaxBipartiteMatchState(const MatchMatrix& graph) + : graph_(&graph), + left_(graph_->LhsSize(), kUnused), + right_(graph_->RhsSize(), kUnused) { + } + + // Returns the edges of a maximal match, each in the form {left, right}. + ElementMatcherPairs Compute() { + // 'seen' is used for path finding { 0: unseen, 1: seen }. + ::std::vector seen; + // Searches the residual flow graph for a path from each left node to + // the sink in the residual flow graph, and if one is found, add flow + // to the graph. It's okay to search through the left nodes once. The + // edge from the implicit source node to each previously-visited left + // node will have flow if that left node has any path to the sink + // whatsoever. Subsequent augmentations can only add flow to the + // network, and cannot take away that previous flow unit from the source. + // Since the source-to-left edge can only carry one flow unit (or, + // each element can be matched to only one matcher), there is no need + // to visit the left nodes more than once looking for augmented paths. + // The flow is known to be possible or impossible by looking at the + // node once. + for (size_t ilhs = 0; ilhs < graph_->LhsSize(); ++ilhs) { + // Reset the path-marking vector and try to find a path from + // source to sink starting at the left_[ilhs] node. + GTEST_CHECK_(left_[ilhs] == kUnused) + << "ilhs: " << ilhs << ", left_[ilhs]: " << left_[ilhs]; + // 'seen' initialized to 'graph_->RhsSize()' copies of 0. + seen.assign(graph_->RhsSize(), 0); + TryAugment(ilhs, &seen); + } + ElementMatcherPairs result; + for (size_t ilhs = 0; ilhs < left_.size(); ++ilhs) { + size_t irhs = left_[ilhs]; + if (irhs == kUnused) continue; + result.push_back(ElementMatcherPair(ilhs, irhs)); + } + return result; + } + + private: + static const size_t kUnused = static_cast(-1); + + // Perform a depth-first search from left node ilhs to the sink. If a + // path is found, flow is added to the network by linking the left and + // right vector elements corresponding each segment of the path. + // Returns true if a path to sink was found, which means that a unit of + // flow was added to the network. The 'seen' vector elements correspond + // to right nodes and are marked to eliminate cycles from the search. + // + // Left nodes will only be explored at most once because they + // are accessible from at most one right node in the residual flow + // graph. + // + // Note that left_[ilhs] is the only element of left_ that TryAugment will + // potentially transition from kUnused to another value. Any other + // left_ element holding kUnused before TryAugment will be holding it + // when TryAugment returns. + // + bool TryAugment(size_t ilhs, ::std::vector* seen) { + for (size_t irhs = 0; irhs < graph_->RhsSize(); ++irhs) { + if ((*seen)[irhs]) + continue; + if (!graph_->HasEdge(ilhs, irhs)) + continue; + // There's an available edge from ilhs to irhs. + (*seen)[irhs] = 1; + // Next a search is performed to determine whether + // this edge is a dead end or leads to the sink. + // + // right_[irhs] == kUnused means that there is residual flow from + // right node irhs to the sink, so we can use that to finish this + // flow path and return success. + // + // Otherwise there is residual flow to some ilhs. We push flow + // along that path and call ourselves recursively to see if this + // ultimately leads to sink. + if (right_[irhs] == kUnused || TryAugment(right_[irhs], seen)) { + // Add flow from left_[ilhs] to right_[irhs]. + left_[ilhs] = irhs; + right_[irhs] = ilhs; + return true; + } + } + return false; + } + + const MatchMatrix* graph_; // not owned + // Each element of the left_ vector represents a left hand side node + // (i.e. an element) and each element of right_ is a right hand side + // node (i.e. a matcher). The values in the left_ vector indicate + // outflow from that node to a node on the the right_ side. The values + // in the right_ indicate inflow, and specify which left_ node is + // feeding that right_ node, if any. For example, left_[3] == 1 means + // there's a flow from element #3 to matcher #1. Such a flow would also + // be redundantly represented in the right_ vector as right_[1] == 3. + // Elements of left_ and right_ are either kUnused or mutually + // referent. Mutually referent means that left_[right_[i]] = i and + // right_[left_[i]] = i. + ::std::vector left_; + ::std::vector right_; + + GTEST_DISALLOW_ASSIGN_(MaxBipartiteMatchState); +}; + +const size_t MaxBipartiteMatchState::kUnused; + +GTEST_API_ ElementMatcherPairs +FindMaxBipartiteMatching(const MatchMatrix& g) { + return MaxBipartiteMatchState(g).Compute(); +} + +static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs, + ::std::ostream* stream) { + typedef ElementMatcherPairs::const_iterator Iter; + ::std::ostream& os = *stream; + os << "{"; + const char *sep = ""; + for (Iter it = pairs.begin(); it != pairs.end(); ++it) { + os << sep << "\n (" + << "element #" << it->first << ", " + << "matcher #" << it->second << ")"; + sep = ","; + } + os << "\n}"; +} + +// Tries to find a pairing, and explains the result. +GTEST_API_ bool FindPairing(const MatchMatrix& matrix, + MatchResultListener* listener) { + ElementMatcherPairs matches = FindMaxBipartiteMatching(matrix); + + size_t max_flow = matches.size(); + bool result = (max_flow == matrix.RhsSize()); + + if (!result) { + if (listener->IsInterested()) { + *listener << "where no permutation of the elements can " + "satisfy all matchers, and the closest match is " + << max_flow << " of " << matrix.RhsSize() + << " matchers with the pairings:\n"; + LogElementMatcherPairVec(matches, listener->stream()); + } + return false; + } + + if (matches.size() > 1) { + if (listener->IsInterested()) { + const char *sep = "where:\n"; + for (size_t mi = 0; mi < matches.size(); ++mi) { + *listener << sep << " - element #" << matches[mi].first + << " is matched by matcher #" << matches[mi].second; + sep = ",\n"; + } + } + } + return true; +} + +bool MatchMatrix::NextGraph() { + for (size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) { + for (size_t irhs = 0; irhs < RhsSize(); ++irhs) { + char& b = matched_[SpaceIndex(ilhs, irhs)]; + if (!b) { + b = 1; + return true; + } + b = 0; + } + } + return false; +} + +void MatchMatrix::Randomize() { + for (size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) { + for (size_t irhs = 0; irhs < RhsSize(); ++irhs) { + char& b = matched_[SpaceIndex(ilhs, irhs)]; + b = static_cast(rand() & 1); // NOLINT + } + } +} + +string MatchMatrix::DebugString() const { + ::std::stringstream ss; + const char *sep = ""; + for (size_t i = 0; i < LhsSize(); ++i) { + ss << sep; + for (size_t j = 0; j < RhsSize(); ++j) { + ss << HasEdge(i, j); + } + sep = ";"; + } + return ss.str(); +} + +void UnorderedElementsAreMatcherImplBase::DescribeToImpl( + ::std::ostream* os) const { + if (matcher_describers_.empty()) { + *os << "is empty"; + return; + } + if (matcher_describers_.size() == 1) { + *os << "has " << Elements(1) << " and that element "; + matcher_describers_[0]->DescribeTo(os); + return; + } + *os << "has " << Elements(matcher_describers_.size()) + << " and there exists some permutation of elements such that:\n"; + const char* sep = ""; + for (size_t i = 0; i != matcher_describers_.size(); ++i) { + *os << sep << " - element #" << i << " "; + matcher_describers_[i]->DescribeTo(os); + sep = ", and\n"; + } +} + +void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl( + ::std::ostream* os) const { + if (matcher_describers_.empty()) { + *os << "isn't empty"; + return; + } + if (matcher_describers_.size() == 1) { + *os << "doesn't have " << Elements(1) + << ", or has " << Elements(1) << " that "; + matcher_describers_[0]->DescribeNegationTo(os); + return; + } + *os << "doesn't have " << Elements(matcher_describers_.size()) + << ", or there exists no permutation of elements such that:\n"; + const char* sep = ""; + for (size_t i = 0; i != matcher_describers_.size(); ++i) { + *os << sep << " - element #" << i << " "; + matcher_describers_[i]->DescribeTo(os); + sep = ", and\n"; + } +} + +// Checks that all matchers match at least one element, and that all +// elements match at least one matcher. This enables faster matching +// and better error reporting. +// Returns false, writing an explanation to 'listener', if and only +// if the success criteria are not met. +bool UnorderedElementsAreMatcherImplBase:: +VerifyAllElementsAndMatchersAreMatched( + const ::std::vector& element_printouts, + const MatchMatrix& matrix, + MatchResultListener* listener) const { + bool result = true; + ::std::vector element_matched(matrix.LhsSize(), 0); + ::std::vector matcher_matched(matrix.RhsSize(), 0); + + for (size_t ilhs = 0; ilhs < matrix.LhsSize(); ilhs++) { + for (size_t irhs = 0; irhs < matrix.RhsSize(); irhs++) { + char matched = matrix.HasEdge(ilhs, irhs); + element_matched[ilhs] |= matched; + matcher_matched[irhs] |= matched; + } + } + + { + const char* sep = + "where the following matchers don't match any elements:\n"; + for (size_t mi = 0; mi < matcher_matched.size(); ++mi) { + if (matcher_matched[mi]) + continue; + result = false; + if (listener->IsInterested()) { + *listener << sep << "matcher #" << mi << ": "; + matcher_describers_[mi]->DescribeTo(listener->stream()); + sep = ",\n"; + } + } + } + + { + const char* sep = + "where the following elements don't match any matchers:\n"; + const char* outer_sep = ""; + if (!result) { + outer_sep = "\nand "; + } + for (size_t ei = 0; ei < element_matched.size(); ++ei) { + if (element_matched[ei]) + continue; + result = false; + if (listener->IsInterested()) { + *listener << outer_sep << sep << "element #" << ei << ": " + << element_printouts[ei]; + sep = ",\n"; + outer_sep = ""; + } + } + } + return result; +} + } // namespace internal } // namespace testing -- cgit v1.2.3 From 04ce8521f481d857db1aa00a206278759b9b0381 Mon Sep 17 00:00:00 2001 From: kosak Date: Sun, 12 Jan 2014 23:42:34 +0000 Subject: Adds a note in the "uninteresting mock method call" warning to advise people how to handle the warning. Clarifies the purpose of utilities in gmock-port.h and adds guidance w.r.t. gmock-port.h vs gtest-port.h. Pulls in gtest r674. --- src/gmock-spec-builders.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index abaae3ad..cefb580f 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -250,7 +250,14 @@ void ReportUninterestingCall(CallReaction reaction, const string& msg) { Log(kInfo, msg, 3); break; case kWarn: - Log(kWarning, msg, 3); + Log(kWarning, + msg + + "\nNOTE: You can safely ignore the above warning unless this " + "call should not happen. Do not suppress it by blindly adding " + "an EXPECT_CALL() if you don't mean to enforce the call. " + "See http://code.google.com/p/googlemock/wiki/CookBook#" + "Knowing_When_to_Expect for details.", + 3); break; default: // FAIL Expect(false, NULL, -1, msg); -- cgit v1.2.3 From b5c81098a8ccc25e313ffca56c911200b3591ea0 Mon Sep 17 00:00:00 2001 From: kosak Date: Wed, 29 Jan 2014 06:41:44 +0000 Subject: Support mocking methods with move-only return types. --- src/gmock-spec-builders.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index cefb580f..a74f9e57 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -332,7 +332,7 @@ const char* UntypedFunctionMockerBase::Name() const // Calculates the result of invoking this mock function with the given // arguments, prints it, and returns it. The caller is responsible // for deleting the result. -const UntypedActionResultHolderBase* +UntypedActionResultHolderBase* UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { if (untyped_expectations_.size() == 0) { @@ -370,7 +370,7 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) this->UntypedDescribeUninterestingCall(untyped_args, &ss); // Calculates the function result. - const UntypedActionResultHolderBase* const result = + UntypedActionResultHolderBase* const result = this->UntypedPerformDefaultAction(untyped_args, ss.str()); // Prints the function result. @@ -417,7 +417,7 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) untyped_expectation->DescribeLocationTo(&loc); } - const UntypedActionResultHolderBase* const result = + UntypedActionResultHolderBase* const result = untyped_action == NULL ? this->UntypedPerformDefaultAction(untyped_args, ss.str()) : this->UntypedPerformAction(untyped_action, untyped_args); -- cgit v1.2.3 From 15d61e42bdd4182e7c4b50bcb3314b006ce578c7 Mon Sep 17 00:00:00 2001 From: kosak Date: Mon, 24 Mar 2014 22:08:24 +0000 Subject: Implement threading support for gmock on Windows. Replace U+2013 with U+002D in comment lines. Pull in gtest 681. --- src/gmock-matchers.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gmock-matchers.cc b/src/gmock-matchers.cc index 9ed29abf..e7424510 100644 --- a/src/gmock-matchers.cc +++ b/src/gmock-matchers.cc @@ -191,9 +191,9 @@ GTEST_API_ string FormatMatcherDescription(bool negation, // . [ sink ] . // // See Also: -// [1] Cormen, et al (2001). "Section 26.2: The Ford–Fulkerson method". -// "Introduction to Algorithms (Second ed.)", pp. 651–664. -// [2] "Ford–Fulkerson algorithm", Wikipedia, +// [1] Cormen, et al (2001). "Section 26.2: The Ford-Fulkerson method". +// "Introduction to Algorithms (Second ed.)", pp. 651-664. +// [2] "Ford-Fulkerson algorithm", Wikipedia, // 'http://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm' class MaxBipartiteMatchState { public: -- cgit v1.2.3 From 5625dd333a621932c469e2261fd9f0c8687378f8 Mon Sep 17 00:00:00 2001 From: kosak Date: Sat, 14 Feb 2015 22:05:58 +0000 Subject: Suppresses the stack trace in a warning for uninteresting call by default; the stack trace will still be printed when --gmock_verbose=info is printed. --- src/gmock-spec-builders.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gmock-spec-builders.cc b/src/gmock-spec-builders.cc index a74f9e57..2b48af13 100644 --- a/src/gmock-spec-builders.cc +++ b/src/gmock-spec-builders.cc @@ -245,9 +245,12 @@ GTEST_API_ ThreadLocal g_gmock_implicit_sequence; // Reports an uninteresting call (whose description is in msg) in the // manner specified by 'reaction'. void ReportUninterestingCall(CallReaction reaction, const string& msg) { + // Include a stack trace only if --gmock_verbose=info is specified. + const int stack_frames_to_skip = + GMOCK_FLAG(verbose) == kInfoVerbosity ? 3 : -1; switch (reaction) { case kAllow: - Log(kInfo, msg, 3); + Log(kInfo, msg, stack_frames_to_skip); break; case kWarn: Log(kWarning, @@ -256,8 +259,8 @@ void ReportUninterestingCall(CallReaction reaction, const string& msg) { "call should not happen. Do not suppress it by blindly adding " "an EXPECT_CALL() if you don't mean to enforce the call. " "See http://code.google.com/p/googlemock/wiki/CookBook#" - "Knowing_When_to_Expect for details.", - 3); + "Knowing_When_to_Expect for details.\n", + stack_frames_to_skip); break; default: // FAIL Expect(false, NULL, -1, msg); -- cgit v1.2.3 From c820efcc04bdc2bd673f112195bec11e70f0cc38 Mon Sep 17 00:00:00 2001 From: kosak Date: Mon, 27 Jul 2015 22:08:34 +0000 Subject: Templatize ParseeGoogleMockStringFlag on String type. --- src/gmock.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gmock.cc b/src/gmock.cc index 1c06985d..eac3d842 100644 --- a/src/gmock.cc +++ b/src/gmock.cc @@ -106,8 +106,9 @@ static bool ParseGoogleMockBoolFlag(const char* str, const char* flag, // // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. +template static bool ParseGoogleMockStringFlag(const char* str, const char* flag, - std::string* value) { + String* value) { // Gets the value of the flag as a string. const char* const value_str = ParseGoogleMockFlagValue(str, flag, false); -- cgit v1.2.3