Merge branch 'master' into isnice
This commit is contained in:
@@ -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)
|
||||
//
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 std::string& whose value is
|
||||
// equal to s.
|
||||
Matcher<const std::string&>::Matcher(const char* s) {
|
||||
*this = Eq(std::string(s));
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a const string& whose value is
|
||||
// equal to s.
|
||||
Matcher<const internal::string&>::Matcher(const char* s) {
|
||||
*this = Eq(internal::string(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); }
|
||||
|
||||
#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_GLOBAL_STRING
|
||||
// Constructs a matcher that matches a const ::string& whose value is
|
||||
// equal to s.
|
||||
Matcher<const ::string&>::Matcher(const std::string& s) {
|
||||
*this = Eq(static_cast<::string>(s));
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a const ::string& whose value is
|
||||
// equal to s.
|
||||
Matcher<const ::string&>::Matcher(const ::string& s) { *this = Eq(s); }
|
||||
|
||||
// Constructs a matcher that matches a const ::string& whose value is
|
||||
// equal to s.
|
||||
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 ::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<internal::string>::Matcher(const internal::string& s) { *this = Eq(s); }
|
||||
Matcher<::string>::Matcher(const char* s) { *this = Eq(::string(s)); }
|
||||
#endif // GTEST_HAS_GLOBAL_STRING
|
||||
|
||||
// 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_STRING_PIECE_
|
||||
// Constructs a matcher that matches a const StringPiece& whose value is
|
||||
#if GTEST_HAS_ABSL
|
||||
// Constructs a matcher that matches a const absl::string_view& whose value is
|
||||
// equal to s.
|
||||
Matcher<const StringPiece&>::Matcher(const internal::string& s) {
|
||||
Matcher<const absl::string_view&>::Matcher(const std::string& s) {
|
||||
*this = Eq(s);
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a const StringPiece& whose value is
|
||||
#if GTEST_HAS_GLOBAL_STRING
|
||||
// Constructs a matcher that matches a const absl::string_view& whose value is
|
||||
// equal to s.
|
||||
Matcher<const StringPiece&>::Matcher(const char* s) {
|
||||
*this = Eq(internal::string(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 StringPiece& whose value is
|
||||
// Constructs a matcher that matches a const absl::string_view& whose value is
|
||||
// equal to s.
|
||||
Matcher<const StringPiece&>::Matcher(StringPiece s) {
|
||||
*this = Eq(s.ToString());
|
||||
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(const internal::string& s) {
|
||||
*this = Eq(s);
|
||||
// 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));
|
||||
}
|
||||
|
||||
// Constructs a matcher that matches a StringPiece whose value is equal to s.
|
||||
Matcher<StringPiece>::Matcher(const char* s) {
|
||||
*this = Eq(internal::string(s));
|
||||
// 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); }
|
||||
|
||||
#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 StringPiece whose value is equal to s.
|
||||
Matcher<StringPiece>::Matcher(StringPiece s) {
|
||||
*this = Eq(s.ToString());
|
||||
// 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_STRING_PIECE_
|
||||
#endif // GTEST_HAS_ABSL
|
||||
|
||||
namespace internal {
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
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;
|
||||
}
|
||||
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 << " ";
|
||||
*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;
|
||||
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;
|
||||
}
|
||||
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 << " ";
|
||||
*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
|
||||
|
||||
@@ -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
|
||||
@@ -750,13 +800,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();
|
||||
@@ -820,7 +870,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_;
|
||||
}
|
||||
@@ -848,3 +898,9 @@ InSequence::~InSequence() {
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER <= 1900
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user