diff options
author | Jonathan Wendeborn <jonathan.wendeborn@bruker.com> | 2018-10-16 06:38:34 (GMT) |
---|---|---|
committer | Jonathan Wendeborn <jonathan.wendeborn@bruker.com> | 2018-10-16 06:38:34 (GMT) |
commit | 96d16157721cda1fd6981e6ce70645acb44220da (patch) | |
tree | c68f2939aaf8904f06e7235dfa4607f167fbb758 /googlemock/src | |
parent | 386391b0144201e0cf5f66d8ba1cb60a1076f673 (diff) | |
parent | 8c82ba48e433005b9e25835b4a342ef4dcc0cfc0 (diff) | |
download | googletest-96d16157721cda1fd6981e6ce70645acb44220da.zip googletest-96d16157721cda1fd6981e6ce70645acb44220da.tar.gz googletest-96d16157721cda1fd6981e6ce70645acb44220da.tar.bz2 |
Merge branch 'isnice' of https://github.com/BrukerJWD/googletest into isnice
Diffstat (limited to 'googlemock/src')
-rw-r--r-- | googlemock/src/gmock-all.cc | 3 | ||||
-rw-r--r-- | googlemock/src/gmock-cardinalities.cc | 5 | ||||
-rw-r--r-- | googlemock/src/gmock-internal-utils.cc | 45 | ||||
-rw-r--r-- | googlemock/src/gmock-matchers.cc | 348 | ||||
-rw-r--r-- | googlemock/src/gmock-spec-builders.cc | 204 | ||||
-rw-r--r-- | googlemock/src/gmock.cc | 39 | ||||
-rw-r--r-- | googlemock/src/gmock_main.cc | 6 |
7 files changed, 414 insertions, 236 deletions
diff --git a/googlemock/src/gmock-all.cc b/googlemock/src/gmock-all.cc index 7aebce7..e43c9b7 100644 --- a/googlemock/src/gmock-all.cc +++ b/googlemock/src/gmock-all.cc @@ -26,8 +26,7 @@ // 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) // diff --git a/googlemock/src/gmock-cardinalities.cc b/googlemock/src/gmock-cardinalities.cc index 50ec728..0549f72 100644 --- a/googlemock/src/gmock-cardinalities.cc +++ b/googlemock/src/gmock-cardinalities.cc @@ -26,8 +26,7 @@ // 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. // @@ -92,7 +91,7 @@ class BetweenCardinalityImpl : public CardinalityInterface { }; // Formats "n times" in a human-friendly way. -inline internal::string FormatTimes(int n) { +inline std::string FormatTimes(int n) { if (n == 1) { return "once"; } else if (n == 2) { diff --git a/googlemock/src/gmock-internal-utils.cc b/googlemock/src/gmock-internal-utils.cc index fb53080..e3a6748 100644 --- a/googlemock/src/gmock-internal-utils.cc +++ b/googlemock/src/gmock-internal-utils.cc @@ -26,8 +26,7 @@ // 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. // @@ -47,12 +46,31 @@ namespace testing { namespace internal { +// Joins a vector of strings as if they are fields of a tuple; returns +// the joined string. +GTEST_API_ std::string JoinAsTuple(const Strings& fields) { + switch (fields.size()) { + case 0: + return ""; + case 1: + return fields[0]; + default: + std::string result = "(" + fields[0]; + for (size_t i = 1; i < fields.size(); i++) { + result += ", "; + result += fields[i]; + } + result += ")"; + return result; + } +} + // Converts an identifier name to a space-separated list of lower-case // 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". -GTEST_API_ string ConvertIdentifierNameToWords(const char* id_name) { - string result; +GTEST_API_ std::string ConvertIdentifierNameToWords(const char* id_name) { + std::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 @@ -71,12 +89,12 @@ GTEST_API_ string ConvertIdentifierNameToWords(const char* id_name) { } // This class reports Google Mock failures as Google Test failures. A -// user can define another class in a similar fashion if he intends to +// user can define another class in a similar fashion if they intend 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) { + const std::string& message) { AssertHelper(type == kFatal ? TestPartResult::kFatalFailure : TestPartResult::kNonFatalFailure, @@ -128,8 +146,7 @@ GTEST_API_ 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. -GTEST_API_ void Log(LogSeverity severity, - const string& message, +GTEST_API_ void Log(LogSeverity severity, const std::string& message, int stack_frames_to_skip) { if (!LogIsVisible(severity)) return; @@ -170,5 +187,17 @@ GTEST_API_ void Log(LogSeverity severity, std::cout << ::std::flush; } +GTEST_API_ WithoutMatchers GetWithoutMatchers() { return WithoutMatchers(); } + +GTEST_API_ void IllegalDoDefault(const char* file, int line) { + internal::Assert( + false, file, line, + "You are using DoDefault() inside a composite action like " + "DoAll() or WithArgs(). This is not supported for technical " + "reasons. Please instead spell out the default action, or " + "assign the default action to an Action variable and use " + "the variable in various places."); +} + } // namespace internal } // namespace testing diff --git a/googlemock/src/gmock-matchers.cc b/googlemock/src/gmock-matchers.cc index e742451..f8ddff1 100644 --- a/googlemock/src/gmock-matchers.cc +++ b/googlemock/src/gmock-matchers.cc @@ -26,8 +26,7 @@ // 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. // @@ -38,98 +37,133 @@ #include "gmock/gmock-generated-matchers.h" #include <string.h> +#include <iostream> #include <sstream> #include <string> namespace testing { -// Constructs a matcher that matches a const string& whose value is +// Constructs a matcher that matches a const std::string& whose value is // equal to s. -Matcher<const internal::string&>::Matcher(const internal::string& s) { - *this = Eq(s); +Matcher<const std::string&>::Matcher(const std::string& s) { *this = Eq(s); } + +#if GTEST_HAS_GLOBAL_STRING +// Constructs a matcher that matches a const std::string& whose value is +// equal to s. +Matcher<const std::string&>::Matcher(const ::string& s) { + *this = Eq(static_cast<std::string>(s)); } +#endif // GTEST_HAS_GLOBAL_STRING -// Constructs a matcher that matches a const string& whose value is +// Constructs a matcher that matches a const std::string& whose value is // equal to s. -Matcher<const internal::string&>::Matcher(const char* s) { - *this = Eq(internal::string(s)); +Matcher<const std::string&>::Matcher(const char* s) { + *this = Eq(std::string(s)); } -// Constructs a matcher that matches a string whose value is equal to s. -Matcher<internal::string>::Matcher(const internal::string& s) { *this = Eq(s); } +// Constructs a matcher that matches a std::string whose value is equal to +// s. +Matcher<std::string>::Matcher(const std::string& s) { *this = Eq(s); } -// Constructs a matcher that matches a string whose value is equal to s. -Matcher<internal::string>::Matcher(const char* s) { - *this = Eq(internal::string(s)); +#if GTEST_HAS_GLOBAL_STRING +// Constructs a matcher that matches a std::string whose value is equal to +// s. +Matcher<std::string>::Matcher(const ::string& s) { + *this = Eq(static_cast<std::string>(s)); } +#endif // GTEST_HAS_GLOBAL_STRING + +// Constructs a matcher that matches a std::string whose value is equal to +// s. +Matcher<std::string>::Matcher(const char* s) { *this = Eq(std::string(s)); } -#if GTEST_HAS_STRING_PIECE_ -// Constructs a matcher that matches a const StringPiece& whose value is +#if GTEST_HAS_GLOBAL_STRING +// Constructs a matcher that matches a const ::string& whose value is // equal to s. -Matcher<const StringPiece&>::Matcher(const internal::string& s) { - *this = Eq(s); +Matcher<const ::string&>::Matcher(const std::string& s) { + *this = Eq(static_cast<::string>(s)); } -// Constructs a matcher that matches a const StringPiece& whose value is +// Constructs a matcher that matches a const ::string& whose value is // equal to s. -Matcher<const StringPiece&>::Matcher(const char* s) { - *this = Eq(internal::string(s)); -} +Matcher<const ::string&>::Matcher(const ::string& s) { *this = Eq(s); } -// Constructs a matcher that matches a const StringPiece& whose value is +// Constructs a matcher that matches a const ::string& whose value is // equal to s. -Matcher<const StringPiece&>::Matcher(StringPiece s) { - *this = Eq(s.ToString()); +Matcher<const ::string&>::Matcher(const char* s) { *this = Eq(::string(s)); } + +// Constructs a matcher that matches a ::string whose value is equal to s. +Matcher<::string>::Matcher(const std::string& s) { + *this = Eq(static_cast<::string>(s)); } -// Constructs a matcher that matches a StringPiece whose value is equal to s. -Matcher<StringPiece>::Matcher(const internal::string& s) { +// Constructs a matcher that matches a ::string whose value is equal to s. +Matcher<::string>::Matcher(const ::string& s) { *this = Eq(s); } + +// Constructs a matcher that matches a string whose value is equal to s. +Matcher<::string>::Matcher(const char* s) { *this = Eq(::string(s)); } +#endif // GTEST_HAS_GLOBAL_STRING + +#if GTEST_HAS_ABSL +// Constructs a matcher that matches a const absl::string_view& whose value is +// equal to s. +Matcher<const absl::string_view&>::Matcher(const std::string& s) { *this = Eq(s); } -// Constructs a matcher that matches a StringPiece whose value is equal to s. -Matcher<StringPiece>::Matcher(const char* s) { - *this = Eq(internal::string(s)); +#if GTEST_HAS_GLOBAL_STRING +// Constructs a matcher that matches a const absl::string_view& whose value is +// equal to s. +Matcher<const absl::string_view&>::Matcher(const ::string& s) { *this = Eq(s); } +#endif // GTEST_HAS_GLOBAL_STRING + +// Constructs a matcher that matches a const absl::string_view& whose value is +// equal to s. +Matcher<const absl::string_view&>::Matcher(const char* s) { + *this = Eq(std::string(s)); } -// Constructs a matcher that matches a StringPiece whose value is equal to s. -Matcher<StringPiece>::Matcher(StringPiece s) { - *this = Eq(s.ToString()); +// Constructs a matcher that matches a const absl::string_view& whose value is +// equal to s. +Matcher<const absl::string_view&>::Matcher(absl::string_view s) { + *this = Eq(std::string(s)); } -#endif // GTEST_HAS_STRING_PIECE_ -namespace internal { +// Constructs a matcher that matches a absl::string_view whose value is equal to +// s. +Matcher<absl::string_view>::Matcher(const std::string& s) { *this = Eq(s); } -// Joins a vector of strings as if they are fields of a tuple; returns -// the joined string. -GTEST_API_ 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; - } +#if GTEST_HAS_GLOBAL_STRING +// Constructs a matcher that matches a absl::string_view whose value is equal to +// s. +Matcher<absl::string_view>::Matcher(const ::string& s) { *this = Eq(s); } +#endif // GTEST_HAS_GLOBAL_STRING + +// Constructs a matcher that matches a absl::string_view whose value is equal to +// s. +Matcher<absl::string_view>::Matcher(const char* s) { + *this = Eq(std::string(s)); } +// Constructs a matcher that matches a absl::string_view whose value is equal to +// s. +Matcher<absl::string_view>::Matcher(absl::string_view s) { + *this = Eq(std::string(s)); +} +#endif // GTEST_HAS_ABSL + +namespace internal { + // Returns the description for a matcher defined using the MATCHER*() // 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. -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); +GTEST_API_ std::string FormatMatcherDescription(bool negation, + const char* matcher_name, + const Strings& param_values) { + std::string result = ConvertIdentifierNameToWords(matcher_name); + if (param_values.size() >= 1) result += " " + JoinAsTuple(param_values); return negation ? "not (" + result + ")" : result; } @@ -200,8 +234,7 @@ class MaxBipartiteMatchState { explicit MaxBipartiteMatchState(const MatchMatrix& graph) : graph_(&graph), left_(graph_->LhsSize(), kUnused), - right_(graph_->RhsSize(), kUnused) { - } + right_(graph_->RhsSize(), kUnused) {} // Returns the edges of a maximal match, each in the form {left, right}. ElementMatcherPairs Compute() { @@ -258,10 +291,8 @@ class MaxBipartiteMatchState { // bool TryAugment(size_t ilhs, ::std::vector<char>* seen) { for (size_t irhs = 0; irhs < graph_->RhsSize(); ++irhs) { - if ((*seen)[irhs]) - continue; - if (!graph_->HasEdge(ilhs, irhs)) - continue; + 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 @@ -288,7 +319,7 @@ class MaxBipartiteMatchState { // 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 + // outflow from that node to a node on 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 @@ -304,8 +335,7 @@ class MaxBipartiteMatchState { const size_t MaxBipartiteMatchState::kUnused; -GTEST_API_ ElementMatcherPairs -FindMaxBipartiteMatching(const MatchMatrix& g) { +GTEST_API_ ElementMatcherPairs FindMaxBipartiteMatching(const MatchMatrix& g) { return MaxBipartiteMatchState(g).Compute(); } @@ -314,7 +344,7 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs, typedef ElementMatcherPairs::const_iterator Iter; ::std::ostream& os = *stream; os << "{"; - const char *sep = ""; + const char* sep = ""; for (Iter it = pairs.begin(); it != pairs.end(); ++it) { os << sep << "\n (" << "element #" << it->first << ", " @@ -324,38 +354,6 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs, 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) { @@ -379,9 +377,9 @@ void MatchMatrix::Randomize() { } } -string MatchMatrix::DebugString() const { +std::string MatchMatrix::DebugString() const { ::std::stringstream ss; - const char *sep = ""; + const char* sep = ""; for (size_t i = 0; i < LhsSize(); ++i) { ss << sep; for (size_t j = 0; j < RhsSize(); ++j) { @@ -394,44 +392,83 @@ string MatchMatrix::DebugString() const { 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; + switch (match_flags()) { + case UnorderedMatcherRequire::ExactMatch: + 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"; + break; + case UnorderedMatcherRequire::Superset: + *os << "a surjection from elements to requirements exists such that:\n"; + break; + case UnorderedMatcherRequire::Subset: + *os << "an injection from elements to requirements exists such that:\n"; + break; } - *os << "has " << Elements(matcher_describers_.size()) - << " and there exists some permutation of elements such that:\n"; + const char* sep = ""; for (size_t i = 0; i != matcher_describers_.size(); ++i) { - *os << sep << " - element #" << i << " "; + *os << sep; + if (match_flags() == UnorderedMatcherRequire::ExactMatch) { + *os << " - element #" << i << " "; + } else { + *os << " - an element "; + } matcher_describers_[i]->DescribeTo(os); - sep = ", and\n"; + if (match_flags() == UnorderedMatcherRequire::ExactMatch) { + sep = ", and\n"; + } else { + sep = "\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; + switch (match_flags()) { + case UnorderedMatcherRequire::ExactMatch: + 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"; + break; + case UnorderedMatcherRequire::Superset: + *os << "no surjection from elements to requirements exists such that:\n"; + break; + case UnorderedMatcherRequire::Subset: + *os << "no injection from elements to requirements exists such that:\n"; + break; } - *os << "doesn't have " << Elements(matcher_describers_.size()) - << ", or there exists no permutation of elements such that:\n"; const char* sep = ""; for (size_t i = 0; i != matcher_describers_.size(); ++i) { - *os << sep << " - element #" << i << " "; + *os << sep; + if (match_flags() == UnorderedMatcherRequire::ExactMatch) { + *os << " - element #" << i << " "; + } else { + *os << " - an element "; + } matcher_describers_[i]->DescribeTo(os); - sep = ", and\n"; + if (match_flags() == UnorderedMatcherRequire::ExactMatch) { + sep = ", and\n"; + } else { + sep = "\n"; + } } } @@ -440,11 +477,9 @@ void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl( // 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<string>& element_printouts, - const MatchMatrix& matrix, - MatchResultListener* listener) const { +bool UnorderedElementsAreMatcherImplBase::VerifyMatchMatrix( + const ::std::vector<std::string>& element_printouts, + const MatchMatrix& matrix, MatchResultListener* listener) const { bool result = true; ::std::vector<char> element_matched(matrix.LhsSize(), 0); ::std::vector<char> matcher_matched(matrix.RhsSize(), 0); @@ -457,12 +492,11 @@ VerifyAllElementsAndMatchersAreMatched( } } - { + if (match_flags() & UnorderedMatcherRequire::Superset) { 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; + if (matcher_matched[mi]) continue; result = false; if (listener->IsInterested()) { *listener << sep << "matcher #" << mi << ": "; @@ -472,7 +506,7 @@ VerifyAllElementsAndMatchersAreMatched( } } - { + if (match_flags() & UnorderedMatcherRequire::Subset) { const char* sep = "where the following elements don't match any matchers:\n"; const char* outer_sep = ""; @@ -480,8 +514,7 @@ VerifyAllElementsAndMatchersAreMatched( outer_sep = "\nand "; } for (size_t ei = 0; ei < element_matched.size(); ++ei) { - if (element_matched[ei]) - continue; + if (element_matched[ei]) continue; result = false; if (listener->IsInterested()) { *listener << outer_sep << sep << "element #" << ei << ": " @@ -494,5 +527,46 @@ VerifyAllElementsAndMatchersAreMatched( return result; } +bool UnorderedElementsAreMatcherImplBase::FindPairing( + const MatchMatrix& matrix, MatchResultListener* listener) const { + ElementMatcherPairs matches = FindMaxBipartiteMatching(matrix); + + size_t max_flow = matches.size(); + if ((match_flags() & UnorderedMatcherRequire::Superset) && + max_flow < matrix.RhsSize()) { + if (listener->IsInterested()) { + *listener << "where no permutation of the elements can satisfy all " + "matchers, and the closest match is " + << max_flow << " of " << matrix.RhsSize() + << " matchers with the pairings:\n"; + LogElementMatcherPairVec(matches, listener->stream()); + } + return false; + } + if ((match_flags() & UnorderedMatcherRequire::Subset) && + max_flow < matrix.LhsSize()) { + if (listener->IsInterested()) { + *listener + << "where not all elements can be matched, and the closest match is " + << max_flow << " of " << matrix.RhsSize() + << " matchers with the pairings:\n"; + LogElementMatcherPairVec(matches, listener->stream()); + } + return false; + } + + if (matches.size() > 1) { + if (listener->IsInterested()) { + const char* sep = "where:\n"; + for (size_t mi = 0; mi < matches.size(); ++mi) { + *listener << sep << " - element #" << matches[mi].first + << " is matched by matcher #" << matches[mi].second; + sep = ",\n"; + } + } + } + return true; +} + } // namespace internal } // namespace testing diff --git a/googlemock/src/gmock-spec-builders.cc b/googlemock/src/gmock-spec-builders.cc index 5b0a830..5c20ed1 100644 --- a/googlemock/src/gmock-spec-builders.cc +++ b/googlemock/src/gmock-spec-builders.cc @@ -26,8 +26,7 @@ // 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. // @@ -41,6 +40,7 @@ #include <map> #include <set> #include <string> +#include <vector> #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -48,6 +48,15 @@ # include <unistd.h> // NOLINT #endif +// Silence C4800 (C4800: 'int *const ': forcing value +// to bool 'true' or 'false') for MSVC 14,15 +#ifdef _MSC_VER +#if _MSC_VER <= 1900 +# pragma warning(push) +# pragma warning(disable:4800) +#endif +#endif + namespace testing { namespace internal { @@ -58,16 +67,15 @@ GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_gmock_mutex); // Logs a message including file and line number information. GTEST_API_ void LogWithLocation(testing::internal::LogSeverity severity, const char* file, int line, - const string& message) { + const std::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, - const string& a_source_text) +ExpectationBase::ExpectationBase(const char* a_file, int a_line, + const std::string& a_source_text) : file_(a_file), line_(a_line), source_text_(a_source_text), @@ -100,12 +108,19 @@ void ExpectationBase::RetireAllPreRequisites() return; } - 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(); + ::std::vector<ExpectationBase*> expectations(1, this); + while (!expectations.empty()) { + ExpectationBase* exp = expectations.back(); + expectations.pop_back(); + + for (ExpectationSet::const_iterator it = + exp->immediate_prerequisites_.begin(); + it != exp->immediate_prerequisites_.end(); ++it) { + ExpectationBase* next = it->expectation_base().get(); + if (!next->is_retired()) { + next->Retire(); + expectations.push_back(next); + } } } } @@ -115,11 +130,18 @@ void ExpectationBase::RetireAllPreRequisites() 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) { - if (!(it->expectation_base()->IsSatisfied()) || - !(it->expectation_base()->AllPrerequisitesAreSatisfied())) - return false; + ::std::vector<const ExpectationBase*> expectations(1, this); + while (!expectations.empty()) { + const ExpectationBase* exp = expectations.back(); + expectations.pop_back(); + + for (ExpectationSet::const_iterator it = + exp->immediate_prerequisites_.begin(); + it != exp->immediate_prerequisites_.end(); ++it) { + const ExpectationBase* next = it->expectation_base().get(); + if (!next->IsSatisfied()) return false; + expectations.push_back(next); + } } return true; } @@ -128,19 +150,28 @@ bool ExpectationBase::AllPrerequisitesAreSatisfied() 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) { - 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->expectation_base()->call_count_ == 0) { - it->expectation_base()->FindUnsatisfiedPrerequisites(result); + ::std::vector<const ExpectationBase*> expectations(1, this); + while (!expectations.empty()) { + const ExpectationBase* exp = expectations.back(); + expectations.pop_back(); + + for (ExpectationSet::const_iterator it = + exp->immediate_prerequisites_.begin(); + it != exp->immediate_prerequisites_.end(); ++it) { + const ExpectationBase* next = it->expectation_base().get(); + + if (next->IsSatisfied()) { + // If *it is satisfied and has a call count of 0, some of its + // pre-requisites may not be satisfied yet. + if (next->call_count_ == 0) { + expectations.push_back(next); + } + } else { + // Now that we know next is unsatisfied, we are not so interested + // in whether its pre-requisites are satisfied. Therefore we + // don't iterate into it here. + *result += *it; } - } else { - // Now that we know *it is unsatisfied, we are not so interested - // in whether its pre-requisites are satisfied. Therefore we - // don't recursively call FindUnsatisfiedPrerequisites() here. - *result += *it; } } } @@ -244,7 +275,7 @@ GTEST_API_ ThreadLocal<Sequence*> 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) { +void ReportUninterestingCall(CallReaction reaction, const std::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; @@ -255,20 +286,22 @@ void ReportUninterestingCall(CallReaction reaction, const string& msg) { case kWarn: 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 https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md#" - "knowing-when-to-expect for details.\n", + "\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 " + "https://github.com/google/googletest/blob/master/googlemock/" + "docs/CookBook.md#" + "knowing-when-to-expect for details.\n", stack_frames_to_skip); break; default: // FAIL - Expect(false, NULL, -1, msg); + Expect(false, nullptr, -1, msg); } } UntypedFunctionMockerBase::UntypedFunctionMockerBase() - : mock_obj_(NULL), name_("") {} + : mock_obj_(nullptr), name_("") {} UntypedFunctionMockerBase::~UntypedFunctionMockerBase() {} @@ -307,7 +340,7 @@ const void* UntypedFunctionMockerBase::MockObject() const // 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__, + Assert(mock_obj_ != nullptr, __FILE__, __LINE__, "MockObject() must not be called before RegisterOwner() or " "SetOwnerAndName() has been called."); mock_obj = mock_obj_; @@ -324,7 +357,7 @@ const char* UntypedFunctionMockerBase::Name() const // 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__, + Assert(name_ != nullptr, __FILE__, __LINE__, "Name() must not be called before SetOwnerAndName() has " "been called."); name = name_; @@ -335,9 +368,10 @@ 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. -UntypedActionResultHolderBase* -UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) - GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { +UntypedActionResultHolderBase* UntypedFunctionMockerBase::UntypedInvokeWith( + void* const untyped_args) GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { + // See the definition of untyped_expectations_ for why access to it + // is unprotected here. if (untyped_expectations_.size() == 0) { // No expectation is set on this mock method - we have an // uninteresting call. @@ -354,18 +388,21 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) // 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. + // only when they want informational messages. reaction == kAllow ? LogIsVisible(kInfo) : - // If the user wants this to be a warning, we print it only - // when he wants to see warnings. - reaction == kWarn ? LogIsVisible(kWarning) : - // Otherwise, the user wants this to be an error, and we - // should always print detailed information in the error. - true; + // If the user wants this to be a warning, we print + // it only when they want to see warnings. + reaction == kWarn + ? LogIsVisible(kWarning) + : + // 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, ""); + return this->UntypedPerformDefaultAction( + untyped_args, "Function call: " + std::string(Name())); } // Warns about the uninteresting call. @@ -377,8 +414,7 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) this->UntypedPerformDefaultAction(untyped_args, ss.str()); // Prints the function result. - if (result != NULL) - result->PrintAsActionResult(&ss); + if (result != nullptr) result->PrintAsActionResult(&ss); ReportUninterestingCall(reaction, ss.str()); return result; @@ -388,7 +424,7 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) ::std::stringstream ss; ::std::stringstream why; ::std::stringstream loc; - const void* untyped_action = NULL; + const void* untyped_action = nullptr; // The UntypedFindMatchingExpectation() function acquires and // releases g_gmock_mutex. @@ -396,7 +432,7 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) this->UntypedFindMatchingExpectation( untyped_args, &untyped_action, &is_excessive, &ss, &why); - const bool found = untyped_expectation != NULL; + const bool found = untyped_expectation != nullptr; // 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() @@ -405,10 +441,9 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) !found || is_excessive || LogIsVisible(kInfo); 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); + return untyped_action == nullptr + ? this->UntypedPerformDefaultAction(untyped_args, "") + : this->UntypedPerformAction(untyped_action, untyped_args); } ss << " Function call: " << Name(); @@ -421,16 +456,15 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) } UntypedActionResultHolderBase* const result = - untyped_action == NULL ? - this->UntypedPerformDefaultAction(untyped_args, ss.str()) : - this->UntypedPerformAction(untyped_action, untyped_args); - if (result != NULL) - result->PrintAsActionResult(&ss); + untyped_action == nullptr + ? this->UntypedPerformDefaultAction(untyped_args, ss.str()) + : this->UntypedPerformAction(untyped_action, untyped_args); + if (result != nullptr) result->PrintAsActionResult(&ss); ss << "\n" << why.str(); if (!found) { // No expectation matches this call - reports a failure. - Expect(false, NULL, -1, ss.str()); + Expect(false, nullptr, -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(), @@ -447,6 +481,8 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) // Returns an Expectation object that references and co-owns exp, // which must be an expectation on this mock function. Expectation UntypedFunctionMockerBase::GetHandleOf(ExpectationBase* exp) { + // See the definition of untyped_expectations_ for why access to it + // is unprotected here. for (UntypedExpectations::const_iterator it = untyped_expectations_.begin(); it != untyped_expectations_.end(); ++it) { @@ -509,6 +545,13 @@ bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked() return expectations_met; } +CallReaction intToCallReaction(int mock_behavior) { + if (mock_behavior >= kAllow && mock_behavior <= kFail) { + return static_cast<internal::CallReaction>(mock_behavior); + } + return kWarn; +} + } // namespace internal // Class Mock. @@ -522,7 +565,7 @@ typedef std::set<internal::UntypedFunctionMockerBase*> FunctionMockers; // expectations. struct MockObjectState { MockObjectState() - : first_used_file(NULL), first_used_line(-1), leakable(false) {} + : first_used_file(nullptr), first_used_line(-1), leakable(false) {} // Where in the source file an ON_CALL or EXPECT_CALL is first // invoked on this mock object. @@ -560,7 +603,7 @@ class MockObjectRegistry { 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. + // FIXME: Print the type of the leaked object. // This can help the user identify the leaked object. std::cout << "\n"; const MockObjectState& state = it->second; @@ -576,9 +619,15 @@ class MockObjectRegistry { leaked_count++; } if (leaked_count > 0) { - std::cout << "\nERROR: " << leaked_count - << " leaked mock " << (leaked_count == 1 ? "object" : "objects") - << " found at program exit.\n"; + std::cout << "\nERROR: " << leaked_count << " leaked mock " + << (leaked_count == 1 ? "object" : "objects") + << " found at program exit. Expectations on a mock object is " + "verified when the object is destructed. Leaking a mock " + "means that its expectations aren't verified, which is " + "usually a test bug. If you really intend to leak a mock, " + "you can suppress this error using " + "testing::Mock::AllowLeak(mock_object), or you may use a " + "fake or stub instead of a mock.\n"; std::cout.flush(); ::std::cerr.flush(); // RUN_ALL_TESTS() has already returned when this destructor is @@ -649,7 +698,8 @@ 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::kDefault : g_uninteresting_call_reaction[mock_obj]; + internal::intToCallReaction(GMOCK_FLAG(default_mock_behavior)) : + g_uninteresting_call_reaction[mock_obj]; } // Tells Google Mock to ignore mock_obj when checking for leaked mock @@ -736,13 +786,13 @@ void Mock::RegisterUseByOnCallOrExpectCall(const void* mock_obj, 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) { + if (state.first_used_file == nullptr) { 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 + if (test_info != nullptr) { + // FIXME: 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(); @@ -806,7 +856,7 @@ Expectation::~Expectation() {} // Adds an expectation to a sequence. void Sequence::AddExpectation(const Expectation& expectation) const { if (*last_expectation_ != expectation) { - if (last_expectation_->expectation_base() != NULL) { + if (last_expectation_->expectation_base() != nullptr) { expectation.expectation_base()->immediate_prerequisites_ += *last_expectation_; } @@ -834,3 +884,9 @@ InSequence::~InSequence() { } } // namespace testing + +#ifdef _MSC_VER +#if _MSC_VER <= 1900 +# pragma warning(pop) +#endif +#endif diff --git a/googlemock/src/gmock.cc b/googlemock/src/gmock.cc index eac3d84..675e8db 100644 --- a/googlemock/src/gmock.cc +++ b/googlemock/src/gmock.cc @@ -26,15 +26,14 @@ // 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 "gmock/gmock.h" #include "gmock/internal/gmock-port.h" namespace testing { -// TODO(wan@google.com): support using environment variables to +// FIXME: support using environment variables to // control the flag values, like what Google Test does. GMOCK_DEFINE_bool_(catch_leaked_mocks, true, @@ -48,6 +47,13 @@ GMOCK_DEFINE_string_(verbose, internal::kWarningVerbosity, " warning - prints warnings and errors.\n" " error - prints errors only."); +GMOCK_DEFINE_int32_(default_mock_behavior, 1, + "Controls the default behavior of mocks." + " Valid values:\n" + " 0 - by default, mocks act as NiceMocks.\n" + " 1 - by default, mocks act as NaggyMocks.\n" + " 2 - by default, mocks act as StrictMocks."); + namespace internal { // Parses a string as a command line flag. The string should have the @@ -59,12 +65,12 @@ 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; + if (str == nullptr || flag == nullptr) return nullptr; // The flag must start with "--gmock_". 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; + if (strncmp(str, flag_str.c_str(), flag_len) != 0) return nullptr; // Skips the flag name. const char* flag_end = str + flag_len; @@ -77,7 +83,7 @@ static const char* ParseGoogleMockFlagValue(const char* str, // 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; + if (flag_end[0] != '=') return nullptr; // Returns the string after "=". return flag_end + 1; @@ -94,7 +100,7 @@ static bool ParseGoogleMockBoolFlag(const char* str, const char* flag, const char* const value_str = ParseGoogleMockFlagValue(str, flag, true); // Aborts if the parsing failed. - if (value_str == NULL) return false; + if (value_str == nullptr) return false; // Converts the string value to a bool. *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F'); @@ -113,13 +119,26 @@ static bool ParseGoogleMockStringFlag(const char* str, const char* flag, const char* const value_str = ParseGoogleMockFlagValue(str, flag, false); // Aborts if the parsing failed. - if (value_str == NULL) return false; + if (value_str == nullptr) return false; // Sets *value to the value of the flag. *value = value_str; return true; } +static bool ParseGoogleMockIntFlag(const char* str, const char* flag, + int* 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 == nullptr) return false; + + // Sets *value to the value of the flag. + return ParseInt32(Message() << "The value of flag --" << flag, + value_str, value); +} + // The internal implementation of InitGoogleMock(). // // The type parameter CharType can be instantiated to either char or @@ -138,7 +157,9 @@ void InitGoogleMockImpl(int* argc, CharType** argv) { // Do we see a Google Mock flag? if (ParseGoogleMockBoolFlag(arg, "catch_leaked_mocks", &GMOCK_FLAG(catch_leaked_mocks)) || - ParseGoogleMockStringFlag(arg, "verbose", &GMOCK_FLAG(verbose))) { + ParseGoogleMockStringFlag(arg, "verbose", &GMOCK_FLAG(verbose)) || + ParseGoogleMockIntFlag(arg, "default_mock_behavior", + &GMOCK_FLAG(default_mock_behavior))) { // 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 diff --git a/googlemock/src/gmock_main.cc b/googlemock/src/gmock_main.cc index bd5be03..a3a271e 100644 --- a/googlemock/src/gmock_main.cc +++ b/googlemock/src/gmock_main.cc @@ -26,8 +26,7 @@ // 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 <iostream> #include "gmock/gmock.h" @@ -37,7 +36,8 @@ // 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 +// https://web.archive.org/web/20170912203238/connect.microsoft.com/VisualStudio/feedback/details/394464/wmain-link-error-in-the-static-library +// // NOLINT #if GTEST_OS_WINDOWS_MOBILE # include <tchar.h> // NOLINT |