mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-10-13 17:48:10 +08:00
Add Google unit test for VS builds (via -tests option)
This commit is contained in:
155
tests/gmock/gmock-cardinalities.cc
Normal file
155
tests/gmock/gmock-cardinalities.cc
Normal file
@@ -0,0 +1,155 @@
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements cardinalities.
|
||||
|
||||
#include "gmock/gmock-cardinalities.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <ostream> // NOLINT
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include "gmock/internal/gmock-internal-utils.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace testing {
|
||||
|
||||
namespace {
|
||||
|
||||
// Implements the Between(m, n) cardinality.
|
||||
class BetweenCardinalityImpl : public CardinalityInterface {
|
||||
public:
|
||||
BetweenCardinalityImpl(int min, int max)
|
||||
: min_(min >= 0 ? min : 0),
|
||||
max_(max >= min_ ? max : min_) {
|
||||
std::stringstream ss;
|
||||
if (min < 0) {
|
||||
ss << "The invocation lower bound must be >= 0, "
|
||||
<< "but is actually " << min << ".";
|
||||
internal::Expect(false, __FILE__, __LINE__, ss.str());
|
||||
} else if (max < 0) {
|
||||
ss << "The invocation upper bound must be >= 0, "
|
||||
<< "but is actually " << max << ".";
|
||||
internal::Expect(false, __FILE__, __LINE__, ss.str());
|
||||
} else if (min > max) {
|
||||
ss << "The invocation upper bound (" << max
|
||||
<< ") must be >= the invocation lower bound (" << min
|
||||
<< ").";
|
||||
internal::Expect(false, __FILE__, __LINE__, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
// Conservative estimate on the lower/upper bound of the number of
|
||||
// calls allowed.
|
||||
int ConservativeLowerBound() const override { return min_; }
|
||||
int ConservativeUpperBound() const override { return max_; }
|
||||
|
||||
bool IsSatisfiedByCallCount(int call_count) const override {
|
||||
return min_ <= call_count && call_count <= max_;
|
||||
}
|
||||
|
||||
bool IsSaturatedByCallCount(int call_count) const override {
|
||||
return call_count >= max_;
|
||||
}
|
||||
|
||||
void DescribeTo(::std::ostream* os) const override;
|
||||
|
||||
private:
|
||||
const int min_;
|
||||
const int max_;
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(BetweenCardinalityImpl);
|
||||
};
|
||||
|
||||
// Formats "n times" in a human-friendly way.
|
||||
inline std::string FormatTimes(int n) {
|
||||
if (n == 1) {
|
||||
return "once";
|
||||
} else if (n == 2) {
|
||||
return "twice";
|
||||
} else {
|
||||
std::stringstream ss;
|
||||
ss << n << " times";
|
||||
return ss.str();
|
||||
}
|
||||
}
|
||||
|
||||
// Describes the Between(m, n) cardinality in human-friendly text.
|
||||
void BetweenCardinalityImpl::DescribeTo(::std::ostream* os) const {
|
||||
if (min_ == 0) {
|
||||
if (max_ == 0) {
|
||||
*os << "never called";
|
||||
} else if (max_ == INT_MAX) {
|
||||
*os << "called any number of times";
|
||||
} else {
|
||||
*os << "called at most " << FormatTimes(max_);
|
||||
}
|
||||
} else if (min_ == max_) {
|
||||
*os << "called " << FormatTimes(min_);
|
||||
} else if (max_ == INT_MAX) {
|
||||
*os << "called at least " << FormatTimes(min_);
|
||||
} else {
|
||||
// 0 < min_ < max_ < INT_MAX
|
||||
*os << "called between " << min_ << " and " << max_ << " times";
|
||||
}
|
||||
}
|
||||
|
||||
} // Unnamed namespace
|
||||
|
||||
// Describes the given call count to an ostream.
|
||||
void Cardinality::DescribeActualCallCountTo(int actual_call_count,
|
||||
::std::ostream* os) {
|
||||
if (actual_call_count > 0) {
|
||||
*os << "called " << FormatTimes(actual_call_count);
|
||||
} else {
|
||||
*os << "never called";
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a cardinality that allows at least n calls.
|
||||
GTEST_API_ Cardinality AtLeast(int n) { return Between(n, INT_MAX); }
|
||||
|
||||
// Creates a cardinality that allows at most n calls.
|
||||
GTEST_API_ Cardinality AtMost(int n) { return Between(0, n); }
|
||||
|
||||
// Creates a cardinality that allows any number of calls.
|
||||
GTEST_API_ Cardinality AnyNumber() { return AtLeast(0); }
|
||||
|
||||
// Creates a cardinality that allows between min and max calls.
|
||||
GTEST_API_ Cardinality Between(int min, int max) {
|
||||
return Cardinality(new BetweenCardinalityImpl(min, max));
|
||||
}
|
||||
|
||||
// Creates a cardinality that allows exactly n calls.
|
||||
GTEST_API_ Cardinality Exactly(int n) { return Between(n, n); }
|
||||
|
||||
} // namespace testing
|
200
tests/gmock/gmock-internal-utils.cc
Normal file
200
tests/gmock/gmock-internal-utils.cc
Normal file
@@ -0,0 +1,200 @@
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file defines some utilities useful for implementing Google
|
||||
// Mock. They are subject to change without notice, so please DO NOT
|
||||
// USE THEM IN USER CODE.
|
||||
|
||||
#include "gmock/internal/gmock-internal-utils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <ostream> // NOLINT
|
||||
#include <string>
|
||||
#include "gmock/gmock.h"
|
||||
#include "gmock/internal/gmock-port.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
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_ 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
|
||||
// guaranteed to be a valid C++ identifier name.
|
||||
const bool starts_new_word = IsUpper(*p) ||
|
||||
(!IsAlpha(prev_char) && IsLower(*p)) ||
|
||||
(!IsDigit(prev_char) && IsDigit(*p));
|
||||
|
||||
if (IsAlNum(*p)) {
|
||||
if (starts_new_word && result != "")
|
||||
result += ' ';
|
||||
result += ToLower(*p);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// This class reports Google Mock failures as Google Test failures. A
|
||||
// user can define another class in a similar fashion if they intend to
|
||||
// use Google Mock with a testing framework other than Google Test.
|
||||
class GoogleTestFailureReporter : public FailureReporterInterface {
|
||||
public:
|
||||
void ReportFailure(FailureType type, const char* file, int line,
|
||||
const std::string& message) override {
|
||||
AssertHelper(type == kFatal ?
|
||||
TestPartResult::kFatalFailure :
|
||||
TestPartResult::kNonFatalFailure,
|
||||
file,
|
||||
line,
|
||||
message.c_str()) = Message();
|
||||
if (type == kFatal) {
|
||||
posix::Abort();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Returns the global failure reporter. Will create a
|
||||
// GoogleTestFailureReporter and return it the first time called.
|
||||
GTEST_API_ FailureReporterInterface* GetFailureReporter() {
|
||||
// Points to the global failure reporter used by Google Mock. gcc
|
||||
// guarantees that the following use of failure_reporter is
|
||||
// thread-safe. We may need to add additional synchronization to
|
||||
// protect failure_reporter if we port Google Mock to other
|
||||
// compilers.
|
||||
static FailureReporterInterface* const failure_reporter =
|
||||
new GoogleTestFailureReporter();
|
||||
return failure_reporter;
|
||||
}
|
||||
|
||||
// Protects global resources (stdout in particular) used by Log().
|
||||
static GTEST_DEFINE_STATIC_MUTEX_(g_log_mutex);
|
||||
|
||||
// Returns true if and only if a log with the given severity is visible
|
||||
// according to the --gmock_verbose flag.
|
||||
GTEST_API_ bool LogIsVisible(LogSeverity severity) {
|
||||
if (GMOCK_FLAG(verbose) == kInfoVerbosity) {
|
||||
// Always show the log if --gmock_verbose=info.
|
||||
return true;
|
||||
} else if (GMOCK_FLAG(verbose) == kErrorVerbosity) {
|
||||
// Always hide it if --gmock_verbose=error.
|
||||
return false;
|
||||
} else {
|
||||
// If --gmock_verbose is neither "info" nor "error", we treat it
|
||||
// as "warning" (its default value).
|
||||
return severity == kWarning;
|
||||
}
|
||||
}
|
||||
|
||||
// Prints the given message to stdout if and only if 'severity' >= the level
|
||||
// specified by the --gmock_verbose flag. If stack_frames_to_skip >=
|
||||
// 0, also prints the stack trace excluding the top
|
||||
// stack_frames_to_skip frames. In opt mode, any positive
|
||||
// stack_frames_to_skip is treated as 0, since we don't know which
|
||||
// function calls will be inlined by the compiler and need to be
|
||||
// conservative.
|
||||
GTEST_API_ void Log(LogSeverity severity, const std::string& message,
|
||||
int stack_frames_to_skip) {
|
||||
if (!LogIsVisible(severity))
|
||||
return;
|
||||
|
||||
// Ensures that logs from different threads don't interleave.
|
||||
MutexLock l(&g_log_mutex);
|
||||
|
||||
if (severity == kWarning) {
|
||||
// Prints a GMOCK WARNING marker to make the warnings easily searchable.
|
||||
std::cout << "\nGMOCK WARNING:";
|
||||
}
|
||||
// Pre-pends a new-line to message if it doesn't start with one.
|
||||
if (message.empty() || message[0] != '\n') {
|
||||
std::cout << "\n";
|
||||
}
|
||||
std::cout << message;
|
||||
if (stack_frames_to_skip >= 0) {
|
||||
#ifdef NDEBUG
|
||||
// In opt mode, we have to be conservative and skip no stack frame.
|
||||
const int actual_to_skip = 0;
|
||||
#else
|
||||
// In dbg mode, we can do what the caller tell us to do (plus one
|
||||
// for skipping this function's stack frame).
|
||||
const int actual_to_skip = stack_frames_to_skip + 1;
|
||||
#endif // NDEBUG
|
||||
|
||||
// Appends a new-line to message if it doesn't end with one.
|
||||
if (!message.empty() && *message.rbegin() != '\n') {
|
||||
std::cout << "\n";
|
||||
}
|
||||
std::cout << "Stack trace:\n"
|
||||
<< ::testing::internal::GetCurrentOsStackTraceExceptTop(
|
||||
::testing::UnitTest::GetInstance(), actual_to_skip);
|
||||
}
|
||||
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
|
908
tests/gmock/gmock-spec-builders.cc
Normal file
908
tests/gmock/gmock-spec-builders.cc
Normal file
@@ -0,0 +1,908 @@
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements the spec builder syntax (ON_CALL and
|
||||
// EXPECT_CALL).
|
||||
|
||||
#include "gmock/gmock-spec-builders.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <iostream> // NOLINT
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
|
||||
#if GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC
|
||||
# include <unistd.h> // NOLINT
|
||||
#endif
|
||||
|
||||
// Silence C4800 (C4800: 'int *const ': forcing value
|
||||
// to bool 'true' or 'false') for MSVC 15
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER == 1900
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4800)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// Protects the mock object registry (in class Mock), all function
|
||||
// mockers, and all expectations.
|
||||
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 std::string& message) {
|
||||
::std::ostringstream s;
|
||||
s << internal::FormatFileLocation(file, line) << " " << message
|
||||
<< ::std::endl;
|
||||
Log(severity, s.str(), 0);
|
||||
}
|
||||
|
||||
// Constructs an ExpectationBase object.
|
||||
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),
|
||||
cardinality_specified_(false),
|
||||
cardinality_(Exactly(1)),
|
||||
call_count_(0),
|
||||
retired_(false),
|
||||
extra_matcher_specified_(false),
|
||||
repeated_action_specified_(false),
|
||||
retires_on_saturation_(false),
|
||||
last_clause_(kNone),
|
||||
action_count_checked_(false) {}
|
||||
|
||||
// Destructs an ExpectationBase object.
|
||||
ExpectationBase::~ExpectationBase() {}
|
||||
|
||||
// Explicitly specifies the cardinality of this expectation. Used by
|
||||
// the subclasses to implement the .Times() clause.
|
||||
void ExpectationBase::SpecifyCardinality(const Cardinality& a_cardinality) {
|
||||
cardinality_specified_ = true;
|
||||
cardinality_ = a_cardinality;
|
||||
}
|
||||
|
||||
// Retires all pre-requisites of this expectation.
|
||||
void ExpectationBase::RetireAllPreRequisites()
|
||||
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||
if (is_retired()) {
|
||||
// We can take this short-cut as we never retire an expectation
|
||||
// until we have retired all its pre-requisites.
|
||||
return;
|
||||
}
|
||||
|
||||
::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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if and only if all pre-requisites of this expectation
|
||||
// have been satisfied.
|
||||
bool ExpectationBase::AllPrerequisitesAreSatisfied() const
|
||||
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||
g_gmock_mutex.AssertHeld();
|
||||
::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;
|
||||
}
|
||||
|
||||
// Adds unsatisfied pre-requisites of this expectation to 'result'.
|
||||
void ExpectationBase::FindUnsatisfiedPrerequisites(ExpectationSet* result) const
|
||||
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||
g_gmock_mutex.AssertHeld();
|
||||
::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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Describes how many times a function call matching this
|
||||
// expectation has occurred.
|
||||
void ExpectationBase::DescribeCallCountTo(::std::ostream* os) const
|
||||
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||
g_gmock_mutex.AssertHeld();
|
||||
|
||||
// Describes how many times the function is expected to be called.
|
||||
*os << " Expected: to be ";
|
||||
cardinality().DescribeTo(os);
|
||||
*os << "\n Actual: ";
|
||||
Cardinality::DescribeActualCallCountTo(call_count(), os);
|
||||
|
||||
// Describes the state of the expectation (e.g. is it satisfied?
|
||||
// is it active?).
|
||||
*os << " - " << (IsOverSaturated() ? "over-saturated" :
|
||||
IsSaturated() ? "saturated" :
|
||||
IsSatisfied() ? "satisfied" : "unsatisfied")
|
||||
<< " and "
|
||||
<< (is_retired() ? "retired" : "active");
|
||||
}
|
||||
|
||||
// Checks the action count (i.e. the number of WillOnce() and
|
||||
// WillRepeatedly() clauses) against the cardinality if this hasn't
|
||||
// been done before. Prints a warning if there are too many or too
|
||||
// few actions.
|
||||
void ExpectationBase::CheckActionCountIfNotDone() const
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
bool should_check = false;
|
||||
{
|
||||
MutexLock l(&mutex_);
|
||||
if (!action_count_checked_) {
|
||||
action_count_checked_ = true;
|
||||
should_check = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (should_check) {
|
||||
if (!cardinality_specified_) {
|
||||
// The cardinality was inferred - no need to check the action
|
||||
// count against it.
|
||||
return;
|
||||
}
|
||||
|
||||
// The cardinality was explicitly specified.
|
||||
const int action_count = static_cast<int>(untyped_actions_.size());
|
||||
const int upper_bound = cardinality().ConservativeUpperBound();
|
||||
const int lower_bound = cardinality().ConservativeLowerBound();
|
||||
bool too_many; // True if there are too many actions, or false
|
||||
// if there are too few.
|
||||
if (action_count > upper_bound ||
|
||||
(action_count == upper_bound && repeated_action_specified_)) {
|
||||
too_many = true;
|
||||
} else if (0 < action_count && action_count < lower_bound &&
|
||||
!repeated_action_specified_) {
|
||||
too_many = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
::std::stringstream ss;
|
||||
DescribeLocationTo(&ss);
|
||||
ss << "Too " << (too_many ? "many" : "few")
|
||||
<< " actions specified in " << source_text() << "...\n"
|
||||
<< "Expected to be ";
|
||||
cardinality().DescribeTo(&ss);
|
||||
ss << ", but has " << (too_many ? "" : "only ")
|
||||
<< action_count << " WillOnce()"
|
||||
<< (action_count == 1 ? "" : "s");
|
||||
if (repeated_action_specified_) {
|
||||
ss << " and a WillRepeatedly()";
|
||||
}
|
||||
ss << ".";
|
||||
Log(kWarning, ss.str(), -1); // -1 means "don't print stack trace".
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the .Times() clause.
|
||||
void ExpectationBase::UntypedTimes(const Cardinality& a_cardinality) {
|
||||
if (last_clause_ == kTimes) {
|
||||
ExpectSpecProperty(false,
|
||||
".Times() cannot appear "
|
||||
"more than once in an EXPECT_CALL().");
|
||||
} else {
|
||||
ExpectSpecProperty(last_clause_ < kTimes,
|
||||
".Times() cannot appear after "
|
||||
".InSequence(), .WillOnce(), .WillRepeatedly(), "
|
||||
"or .RetiresOnSaturation().");
|
||||
}
|
||||
last_clause_ = kTimes;
|
||||
|
||||
SpecifyCardinality(a_cardinality);
|
||||
}
|
||||
|
||||
// Points to the implicit sequence introduced by a living InSequence
|
||||
// object (if any) in the current thread or NULL.
|
||||
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 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;
|
||||
switch (reaction) {
|
||||
case kAllow:
|
||||
Log(kInfo, msg, stack_frames_to_skip);
|
||||
break;
|
||||
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/docs/"
|
||||
"gmock_cook_book.md#"
|
||||
"knowing-when-to-expect for details.\n",
|
||||
stack_frames_to_skip);
|
||||
break;
|
||||
default: // FAIL
|
||||
Expect(false, nullptr, -1, msg);
|
||||
}
|
||||
}
|
||||
|
||||
UntypedFunctionMockerBase::UntypedFunctionMockerBase()
|
||||
: mock_obj_(nullptr), name_("") {}
|
||||
|
||||
UntypedFunctionMockerBase::~UntypedFunctionMockerBase() {}
|
||||
|
||||
// Sets the mock object this mock method belongs to, and registers
|
||||
// this information in the global mock registry. Will be called
|
||||
// whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
|
||||
// method.
|
||||
void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
{
|
||||
MutexLock l(&g_gmock_mutex);
|
||||
mock_obj_ = mock_obj;
|
||||
}
|
||||
Mock::Register(mock_obj, this);
|
||||
}
|
||||
|
||||
// Sets the mock object this mock method belongs to, and sets the name
|
||||
// of the mock function. Will be called upon each invocation of this
|
||||
// mock function.
|
||||
void UntypedFunctionMockerBase::SetOwnerAndName(const void* mock_obj,
|
||||
const char* name)
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
// We protect name_ under g_gmock_mutex in case this mock function
|
||||
// is called from two threads concurrently.
|
||||
MutexLock l(&g_gmock_mutex);
|
||||
mock_obj_ = mock_obj;
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
// Returns the name of the function being mocked. Must be called
|
||||
// after RegisterOwner() or SetOwnerAndName() has been called.
|
||||
const void* UntypedFunctionMockerBase::MockObject() const
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
const void* mock_obj;
|
||||
{
|
||||
// We protect mock_obj_ under g_gmock_mutex in case this mock
|
||||
// function is called from two threads concurrently.
|
||||
MutexLock l(&g_gmock_mutex);
|
||||
Assert(mock_obj_ != nullptr, __FILE__, __LINE__,
|
||||
"MockObject() must not be called before RegisterOwner() or "
|
||||
"SetOwnerAndName() has been called.");
|
||||
mock_obj = mock_obj_;
|
||||
}
|
||||
return mock_obj;
|
||||
}
|
||||
|
||||
// Returns the name of this mock method. Must be called after
|
||||
// SetOwnerAndName() has been called.
|
||||
const char* UntypedFunctionMockerBase::Name() const
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
const char* name;
|
||||
{
|
||||
// We protect name_ under g_gmock_mutex in case this mock
|
||||
// function is called from two threads concurrently.
|
||||
MutexLock l(&g_gmock_mutex);
|
||||
Assert(name_ != nullptr, __FILE__, __LINE__,
|
||||
"Name() must not be called before SetOwnerAndName() has "
|
||||
"been called.");
|
||||
name = name_;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
// Calculates the result of invoking this mock function with the given
|
||||
// arguments, prints it, and returns it. The caller is responsible
|
||||
// for deleting the result.
|
||||
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.
|
||||
|
||||
// We must get Google Mock's reaction on uninteresting calls
|
||||
// made on this mock object BEFORE performing the action,
|
||||
// because the action may DELETE the mock object and make the
|
||||
// following expression meaningless.
|
||||
const CallReaction reaction =
|
||||
Mock::GetReactionOnUninterestingCalls(MockObject());
|
||||
|
||||
// True if and only if we need to print this call's arguments and return
|
||||
// value. This definition must be kept in sync with
|
||||
// the behavior of ReportUninterestingCall().
|
||||
const bool need_to_report_uninteresting_call =
|
||||
// If the user allows this uninteresting call, we print it
|
||||
// only when they want informational messages.
|
||||
reaction == kAllow ? LogIsVisible(kInfo) :
|
||||
// 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, "Function call: " + std::string(Name()));
|
||||
}
|
||||
|
||||
// Warns about the uninteresting call.
|
||||
::std::stringstream ss;
|
||||
this->UntypedDescribeUninterestingCall(untyped_args, &ss);
|
||||
|
||||
// Calculates the function result.
|
||||
UntypedActionResultHolderBase* const result =
|
||||
this->UntypedPerformDefaultAction(untyped_args, ss.str());
|
||||
|
||||
// Prints the function result.
|
||||
if (result != nullptr) result->PrintAsActionResult(&ss);
|
||||
|
||||
ReportUninterestingCall(reaction, ss.str());
|
||||
return result;
|
||||
}
|
||||
|
||||
bool is_excessive = false;
|
||||
::std::stringstream ss;
|
||||
::std::stringstream why;
|
||||
::std::stringstream loc;
|
||||
const void* untyped_action = nullptr;
|
||||
|
||||
// The UntypedFindMatchingExpectation() function acquires and
|
||||
// releases g_gmock_mutex.
|
||||
|
||||
const ExpectationBase* const untyped_expectation =
|
||||
this->UntypedFindMatchingExpectation(untyped_args, &untyped_action,
|
||||
&is_excessive, &ss, &why);
|
||||
const bool found = untyped_expectation != nullptr;
|
||||
|
||||
// True if and only if we need to print the call's arguments
|
||||
// and return value.
|
||||
// This definition must be kept in sync with the uses of Expect()
|
||||
// and Log() in this function.
|
||||
const bool need_to_report_call =
|
||||
!found || is_excessive || LogIsVisible(kInfo);
|
||||
if (!need_to_report_call) {
|
||||
// Perform the action without printing the call information.
|
||||
return untyped_action == nullptr
|
||||
? this->UntypedPerformDefaultAction(untyped_args, "")
|
||||
: this->UntypedPerformAction(untyped_action, untyped_args);
|
||||
}
|
||||
|
||||
ss << " Function call: " << Name();
|
||||
this->UntypedPrintArgs(untyped_args, &ss);
|
||||
|
||||
// In case the action deletes a piece of the expectation, we
|
||||
// generate the message beforehand.
|
||||
if (found && !is_excessive) {
|
||||
untyped_expectation->DescribeLocationTo(&loc);
|
||||
}
|
||||
|
||||
UntypedActionResultHolderBase* result = nullptr;
|
||||
|
||||
auto perform_action = [&] {
|
||||
return untyped_action == nullptr
|
||||
? this->UntypedPerformDefaultAction(untyped_args, ss.str())
|
||||
: this->UntypedPerformAction(untyped_action, untyped_args);
|
||||
};
|
||||
auto handle_failures = [&] {
|
||||
ss << "\n" << why.str();
|
||||
|
||||
if (!found) {
|
||||
// No expectation matches this call - reports a failure.
|
||||
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(), untyped_expectation->line(),
|
||||
ss.str());
|
||||
} else {
|
||||
// We had an expected call and the matching expectation is
|
||||
// described in ss.
|
||||
Log(kInfo, loc.str() + ss.str(), 2);
|
||||
}
|
||||
};
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
try {
|
||||
result = perform_action();
|
||||
} catch (...) {
|
||||
handle_failures();
|
||||
throw;
|
||||
}
|
||||
#else
|
||||
result = perform_action();
|
||||
#endif
|
||||
|
||||
if (result != nullptr) result->PrintAsActionResult(&ss);
|
||||
handle_failures();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns an Expectation object that references and co-owns exp,
|
||||
// which must be an expectation on this mock function.
|
||||
Expectation UntypedFunctionMockerBase::GetHandleOf(ExpectationBase* exp) {
|
||||
// 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) {
|
||||
if (it->get() == exp) {
|
||||
return Expectation(*it);
|
||||
}
|
||||
}
|
||||
|
||||
Assert(false, __FILE__, __LINE__, "Cannot find expectation.");
|
||||
return Expectation();
|
||||
// The above statement is just to make the code compile, and will
|
||||
// never be executed.
|
||||
}
|
||||
|
||||
// Verifies that all expectations on this mock function have been
|
||||
// satisfied. Reports one or more Google Test non-fatal failures
|
||||
// and returns false if not.
|
||||
bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked()
|
||||
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||
g_gmock_mutex.AssertHeld();
|
||||
bool expectations_met = true;
|
||||
for (UntypedExpectations::const_iterator it =
|
||||
untyped_expectations_.begin();
|
||||
it != untyped_expectations_.end(); ++it) {
|
||||
ExpectationBase* const untyped_expectation = it->get();
|
||||
if (untyped_expectation->IsOverSaturated()) {
|
||||
// There was an upper-bound violation. Since the error was
|
||||
// already reported when it occurred, there is no need to do
|
||||
// anything here.
|
||||
expectations_met = false;
|
||||
} else if (!untyped_expectation->IsSatisfied()) {
|
||||
expectations_met = false;
|
||||
::std::stringstream ss;
|
||||
ss << "Actual function call count doesn't match "
|
||||
<< untyped_expectation->source_text() << "...\n";
|
||||
// No need to show the source file location of the expectation
|
||||
// in the description, as the Expect() call that follows already
|
||||
// takes care of it.
|
||||
untyped_expectation->MaybeDescribeExtraMatcherTo(&ss);
|
||||
untyped_expectation->DescribeCallCountTo(&ss);
|
||||
Expect(false, untyped_expectation->file(),
|
||||
untyped_expectation->line(), ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
// Deleting our expectations may trigger other mock objects to be deleted, for
|
||||
// example if an action contains a reference counted smart pointer to that
|
||||
// mock object, and that is the last reference. So if we delete our
|
||||
// expectations within the context of the global mutex we may deadlock when
|
||||
// this method is called again. Instead, make a copy of the set of
|
||||
// expectations to delete, clear our set within the mutex, and then clear the
|
||||
// copied set outside of it.
|
||||
UntypedExpectations expectations_to_delete;
|
||||
untyped_expectations_.swap(expectations_to_delete);
|
||||
|
||||
g_gmock_mutex.Unlock();
|
||||
expectations_to_delete.clear();
|
||||
g_gmock_mutex.Lock();
|
||||
|
||||
return expectations_met;
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
namespace {
|
||||
|
||||
typedef std::set<internal::UntypedFunctionMockerBase*> FunctionMockers;
|
||||
|
||||
// The current state of a mock object. Such information is needed for
|
||||
// detecting leaked mock objects and explicitly verifying a mock's
|
||||
// expectations.
|
||||
struct MockObjectState {
|
||||
MockObjectState()
|
||||
: first_used_file(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.
|
||||
const char* first_used_file;
|
||||
int first_used_line;
|
||||
::std::string first_used_test_suite;
|
||||
::std::string first_used_test;
|
||||
bool leakable; // true if and only if it's OK to leak the object.
|
||||
FunctionMockers function_mockers; // All registered methods of the object.
|
||||
};
|
||||
|
||||
// A global registry holding the state of all mock objects that are
|
||||
// alive. A mock object is added to this registry the first time
|
||||
// Mock::AllowLeak(), ON_CALL(), or EXPECT_CALL() is called on it. It
|
||||
// is removed from the registry in the mock object's destructor.
|
||||
class MockObjectRegistry {
|
||||
public:
|
||||
// Maps a mock object (identified by its address) to its state.
|
||||
typedef std::map<const void*, MockObjectState> StateMap;
|
||||
|
||||
// This destructor will be called when a program exits, after all
|
||||
// tests in it have been run. By then, there should be no mock
|
||||
// object alive. Therefore we report any living object as test
|
||||
// failure, unless the user explicitly asked us to ignore it.
|
||||
~MockObjectRegistry() {
|
||||
if (!GMOCK_FLAG(catch_leaked_mocks))
|
||||
return;
|
||||
|
||||
int leaked_count = 0;
|
||||
for (StateMap::const_iterator it = states_.begin(); it != states_.end();
|
||||
++it) {
|
||||
if (it->second.leakable) // The user said it's fine to leak this object.
|
||||
continue;
|
||||
|
||||
// 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;
|
||||
std::cout << internal::FormatFileLocation(state.first_used_file,
|
||||
state.first_used_line);
|
||||
std::cout << " ERROR: this mock object";
|
||||
if (state.first_used_test != "") {
|
||||
std::cout << " (used in test " << state.first_used_test_suite << "."
|
||||
<< state.first_used_test << ")";
|
||||
}
|
||||
std::cout << " should be deleted but never is. Its address is @"
|
||||
<< it->first << ".";
|
||||
leaked_count++;
|
||||
}
|
||||
if (leaked_count > 0) {
|
||||
std::cout << "\nERROR: " << leaked_count << " leaked mock "
|
||||
<< (leaked_count == 1 ? "object" : "objects")
|
||||
<< " found at program exit. Expectations on a mock object are "
|
||||
"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
|
||||
// called. Therefore we cannot use the normal Google Test
|
||||
// failure reporting mechanism.
|
||||
_exit(1); // We cannot call exit() as it is not reentrant and
|
||||
// may already have been called.
|
||||
}
|
||||
}
|
||||
|
||||
StateMap& states() { return states_; }
|
||||
|
||||
private:
|
||||
StateMap states_;
|
||||
};
|
||||
|
||||
// Protected by g_gmock_mutex.
|
||||
MockObjectRegistry g_mock_object_registry;
|
||||
|
||||
// Maps a mock object to the reaction Google Mock should have when an
|
||||
// uninteresting method is called. Protected by g_gmock_mutex.
|
||||
std::map<const void*, internal::CallReaction> g_uninteresting_call_reaction;
|
||||
|
||||
// Sets the reaction Google Mock should have when an uninteresting
|
||||
// method of the given mock object is called.
|
||||
void SetReactionOnUninterestingCalls(const void* mock_obj,
|
||||
internal::CallReaction reaction)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||
g_uninteresting_call_reaction[mock_obj] = reaction;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Tells Google Mock to allow uninteresting calls on the given mock
|
||||
// object.
|
||||
void Mock::AllowUninterestingCalls(const void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
SetReactionOnUninterestingCalls(mock_obj, internal::kAllow);
|
||||
}
|
||||
|
||||
// Tells Google Mock to warn the user about uninteresting calls on the
|
||||
// given mock object.
|
||||
void Mock::WarnUninterestingCalls(const void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
SetReactionOnUninterestingCalls(mock_obj, internal::kWarn);
|
||||
}
|
||||
|
||||
// Tells Google Mock to fail uninteresting calls on the given mock
|
||||
// object.
|
||||
void Mock::FailUninterestingCalls(const void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
SetReactionOnUninterestingCalls(mock_obj, internal::kFail);
|
||||
}
|
||||
|
||||
// Tells Google Mock the given mock object is being destroyed and its
|
||||
// entry in the call-reaction table should be removed.
|
||||
void Mock::UnregisterCallReaction(const void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||
g_uninteresting_call_reaction.erase(mock_obj);
|
||||
}
|
||||
|
||||
// Returns the reaction Google Mock will have on uninteresting calls
|
||||
// made on the given mock object.
|
||||
internal::CallReaction Mock::GetReactionOnUninterestingCalls(
|
||||
const void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||
return (g_uninteresting_call_reaction.count(mock_obj) == 0) ?
|
||||
internal::intToCallReaction(GMOCK_FLAG(default_mock_behavior)) :
|
||||
g_uninteresting_call_reaction[mock_obj];
|
||||
}
|
||||
|
||||
// Tells Google Mock to ignore mock_obj when checking for leaked mock
|
||||
// objects.
|
||||
void Mock::AllowLeak(const void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||
g_mock_object_registry.states()[mock_obj].leakable = true;
|
||||
}
|
||||
|
||||
// Verifies and clears all expectations on the given mock object. If
|
||||
// the expectations aren't satisfied, generates one or more Google
|
||||
// Test non-fatal failures and returns false.
|
||||
bool Mock::VerifyAndClearExpectations(void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||
return VerifyAndClearExpectationsLocked(mock_obj);
|
||||
}
|
||||
|
||||
// Verifies all expectations on the given mock object and clears its
|
||||
// default actions and expectations. Returns true if and only if the
|
||||
// verification was successful.
|
||||
bool Mock::VerifyAndClear(void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||
ClearDefaultActionsLocked(mock_obj);
|
||||
return VerifyAndClearExpectationsLocked(mock_obj);
|
||||
}
|
||||
|
||||
// Verifies and clears all expectations on the given mock object. If
|
||||
// the expectations aren't satisfied, generates one or more Google
|
||||
// Test non-fatal failures and returns false.
|
||||
bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj)
|
||||
GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) {
|
||||
internal::g_gmock_mutex.AssertHeld();
|
||||
if (g_mock_object_registry.states().count(mock_obj) == 0) {
|
||||
// No EXPECT_CALL() was set on the given mock object.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Verifies and clears the expectations on each mock method in the
|
||||
// given mock object.
|
||||
bool expectations_met = true;
|
||||
FunctionMockers& mockers =
|
||||
g_mock_object_registry.states()[mock_obj].function_mockers;
|
||||
for (FunctionMockers::const_iterator it = mockers.begin();
|
||||
it != mockers.end(); ++it) {
|
||||
if (!(*it)->VerifyAndClearExpectationsLocked()) {
|
||||
expectations_met = false;
|
||||
}
|
||||
}
|
||||
|
||||
// We don't clear the content of mockers, as they may still be
|
||||
// needed by ClearDefaultActionsLocked().
|
||||
return expectations_met;
|
||||
}
|
||||
|
||||
bool Mock::IsNaggy(void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
return Mock::GetReactionOnUninterestingCalls(mock_obj) == internal::kWarn;
|
||||
}
|
||||
bool Mock::IsNice(void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
return Mock::GetReactionOnUninterestingCalls(mock_obj) == internal::kAllow;
|
||||
}
|
||||
bool Mock::IsStrict(void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
return Mock::GetReactionOnUninterestingCalls(mock_obj) == internal::kFail;
|
||||
}
|
||||
|
||||
// Registers a mock object and a mock method it owns.
|
||||
void Mock::Register(const void* mock_obj,
|
||||
internal::UntypedFunctionMockerBase* mocker)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||
g_mock_object_registry.states()[mock_obj].function_mockers.insert(mocker);
|
||||
}
|
||||
|
||||
// Tells Google Mock where in the source code mock_obj is used in an
|
||||
// ON_CALL or EXPECT_CALL. In case mock_obj is leaked, this
|
||||
// information helps the user identify which object it is.
|
||||
void Mock::RegisterUseByOnCallOrExpectCall(const void* mock_obj,
|
||||
const char* file, int line)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||
MockObjectState& state = g_mock_object_registry.states()[mock_obj];
|
||||
if (state.first_used_file == nullptr) {
|
||||
state.first_used_file = file;
|
||||
state.first_used_line = line;
|
||||
const TestInfo* const test_info =
|
||||
UnitTest::GetInstance()->current_test_info();
|
||||
if (test_info != nullptr) {
|
||||
state.first_used_test_suite = test_info->test_suite_name();
|
||||
state.first_used_test = test_info->name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unregisters a mock method; removes the owning mock object from the
|
||||
// registry when the last mock method associated with it has been
|
||||
// unregistered. This is called only in the destructor of
|
||||
// FunctionMockerBase.
|
||||
void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker)
|
||||
GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) {
|
||||
internal::g_gmock_mutex.AssertHeld();
|
||||
for (MockObjectRegistry::StateMap::iterator it =
|
||||
g_mock_object_registry.states().begin();
|
||||
it != g_mock_object_registry.states().end(); ++it) {
|
||||
FunctionMockers& mockers = it->second.function_mockers;
|
||||
if (mockers.erase(mocker) > 0) {
|
||||
// mocker was in mockers and has been just removed.
|
||||
if (mockers.empty()) {
|
||||
g_mock_object_registry.states().erase(it);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clears all ON_CALL()s set on the given mock object.
|
||||
void Mock::ClearDefaultActionsLocked(void* mock_obj)
|
||||
GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) {
|
||||
internal::g_gmock_mutex.AssertHeld();
|
||||
|
||||
if (g_mock_object_registry.states().count(mock_obj) == 0) {
|
||||
// No ON_CALL() was set on the given mock object.
|
||||
return;
|
||||
}
|
||||
|
||||
// Clears the default actions for each mock method in the given mock
|
||||
// object.
|
||||
FunctionMockers& mockers =
|
||||
g_mock_object_registry.states()[mock_obj].function_mockers;
|
||||
for (FunctionMockers::const_iterator it = mockers.begin();
|
||||
it != mockers.end(); ++it) {
|
||||
(*it)->ClearDefaultActionsLocked();
|
||||
}
|
||||
|
||||
// We don't clear the content of mockers, as they may still be
|
||||
// needed by VerifyAndClearExpectationsLocked().
|
||||
}
|
||||
|
||||
Expectation::Expectation() {}
|
||||
|
||||
Expectation::Expectation(
|
||||
const std::shared_ptr<internal::ExpectationBase>& an_expectation_base)
|
||||
: expectation_base_(an_expectation_base) {}
|
||||
|
||||
Expectation::~Expectation() {}
|
||||
|
||||
// Adds an expectation to a sequence.
|
||||
void Sequence::AddExpectation(const Expectation& expectation) const {
|
||||
if (*last_expectation_ != expectation) {
|
||||
if (last_expectation_->expectation_base() != nullptr) {
|
||||
expectation.expectation_base()->immediate_prerequisites_
|
||||
+= *last_expectation_;
|
||||
}
|
||||
*last_expectation_ = expectation;
|
||||
}
|
||||
}
|
||||
|
||||
// Creates the implicit sequence if there isn't one.
|
||||
InSequence::InSequence() {
|
||||
if (internal::g_gmock_implicit_sequence.get() == nullptr) {
|
||||
internal::g_gmock_implicit_sequence.set(new Sequence);
|
||||
sequence_created_ = true;
|
||||
} else {
|
||||
sequence_created_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Deletes the implicit sequence if it was created by the constructor
|
||||
// of this object.
|
||||
InSequence::~InSequence() {
|
||||
if (sequence_created_) {
|
||||
delete internal::g_gmock_implicit_sequence.get();
|
||||
internal::g_gmock_implicit_sequence.set(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER == 1900
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
#endif
|
213
tests/gmock/gmock.cc
Normal file
213
tests/gmock/gmock.cc
Normal file
@@ -0,0 +1,213 @@
|
||||
// Copyright 2008, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gmock/internal/gmock-port.h"
|
||||
|
||||
namespace testing {
|
||||
|
||||
GMOCK_DEFINE_bool_(catch_leaked_mocks, true,
|
||||
"true if and only if Google Mock should report leaked "
|
||||
"mock objects as failures.");
|
||||
|
||||
GMOCK_DEFINE_string_(verbose, internal::kWarningVerbosity,
|
||||
"Controls how verbose Google Mock's output is."
|
||||
" Valid values:\n"
|
||||
" info - prints all messages.\n"
|
||||
" 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
|
||||
// format "--gmock_flag=value". When def_optional is true, the
|
||||
// "=value" part can be omitted.
|
||||
//
|
||||
// Returns the value of the flag, or NULL if the parsing failed.
|
||||
static const char* ParseGoogleMockFlagValue(const char* str,
|
||||
const char* flag,
|
||||
bool def_optional) {
|
||||
// str and flag must not be NULL.
|
||||
if (str == 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 nullptr;
|
||||
|
||||
// Skips the flag name.
|
||||
const char* flag_end = str + flag_len;
|
||||
|
||||
// When def_optional is true, it's OK to not have a "=value" part.
|
||||
if (def_optional && (flag_end[0] == '\0')) {
|
||||
return flag_end;
|
||||
}
|
||||
|
||||
// If def_optional is true and there are more characters after the
|
||||
// flag name, or if def_optional is false, there must be a '=' after
|
||||
// the flag name.
|
||||
if (flag_end[0] != '=') return nullptr;
|
||||
|
||||
// Returns the string after "=".
|
||||
return flag_end + 1;
|
||||
}
|
||||
|
||||
// Parses a string for a Google Mock bool flag, in the form of
|
||||
// "--gmock_flag=value".
|
||||
//
|
||||
// On success, stores the value of the flag in *value, and returns
|
||||
// true. On failure, returns false without changing *value.
|
||||
static bool ParseGoogleMockBoolFlag(const char* str, const char* flag,
|
||||
bool* value) {
|
||||
// Gets the value of the flag as a string.
|
||||
const char* const value_str = ParseGoogleMockFlagValue(str, flag, true);
|
||||
|
||||
// Aborts if the parsing failed.
|
||||
if (value_str == nullptr) return false;
|
||||
|
||||
// Converts the string value to a bool.
|
||||
*value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parses a string for a Google Mock string flag, in the form of
|
||||
// "--gmock_flag=value".
|
||||
//
|
||||
// On success, stores the value of the flag in *value, and returns
|
||||
// true. On failure, returns false without changing *value.
|
||||
template <typename String>
|
||||
static bool ParseGoogleMockStringFlag(const char* str, const char* flag,
|
||||
String* value) {
|
||||
// Gets the value of the flag as a string.
|
||||
const char* const value_str = ParseGoogleMockFlagValue(str, flag, false);
|
||||
|
||||
// Aborts if the parsing failed.
|
||||
if (value_str == 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,
|
||||
int32_t* 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
|
||||
// wchar_t.
|
||||
template <typename CharType>
|
||||
void InitGoogleMockImpl(int* argc, CharType** argv) {
|
||||
// Makes sure Google Test is initialized. InitGoogleTest() is
|
||||
// idempotent, so it's fine if the user has already called it.
|
||||
InitGoogleTest(argc, argv);
|
||||
if (*argc <= 0) return;
|
||||
|
||||
for (int i = 1; i != *argc; i++) {
|
||||
const std::string arg_string = StreamableToString(argv[i]);
|
||||
const char* const arg = arg_string.c_str();
|
||||
|
||||
// Do we see a Google Mock flag?
|
||||
if (ParseGoogleMockBoolFlag(arg, "catch_leaked_mocks",
|
||||
&GMOCK_FLAG(catch_leaked_mocks)) ||
|
||||
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
|
||||
// well.
|
||||
for (int j = i; j != *argc; j++) {
|
||||
argv[j] = argv[j + 1];
|
||||
}
|
||||
|
||||
// Decrements the argument count.
|
||||
(*argc)--;
|
||||
|
||||
// We also need to decrement the iterator as we just removed
|
||||
// an element.
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Initializes Google Mock. This must be called before running the
|
||||
// tests. In particular, it parses a command line for the flags that
|
||||
// Google Mock recognizes. Whenever a Google Mock flag is seen, it is
|
||||
// removed from argv, and *argc is decremented.
|
||||
//
|
||||
// No value is returned. Instead, the Google Mock flag variables are
|
||||
// updated.
|
||||
//
|
||||
// Since Google Test is needed for Google Mock to work, this function
|
||||
// also initializes Google Test and parses its flags, if that hasn't
|
||||
// been done.
|
||||
GTEST_API_ void InitGoogleMock(int* argc, char** argv) {
|
||||
internal::InitGoogleMockImpl(argc, argv);
|
||||
}
|
||||
|
||||
// This overloaded version can be used in Windows programs compiled in
|
||||
// UNICODE mode.
|
||||
GTEST_API_ void InitGoogleMock(int* argc, wchar_t** argv) {
|
||||
internal::InitGoogleMockImpl(argc, argv);
|
||||
}
|
||||
|
||||
// This overloaded version can be used on Arduino/embedded platforms where
|
||||
// there is no argc/argv.
|
||||
GTEST_API_ void InitGoogleMock() {
|
||||
// Since Arduino doesn't have a command line, fake out the argc/argv arguments
|
||||
int argc = 1;
|
||||
const auto arg0 = "dummy";
|
||||
char* argv0 = const_cast<char*>(arg0);
|
||||
char** argv = &argv0;
|
||||
|
||||
internal::InitGoogleMockImpl(&argc, argv);
|
||||
}
|
||||
|
||||
} // namespace testing
|
72
tests/gmock/gmock_main.cc
Normal file
72
tests/gmock/gmock_main.cc
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright 2008, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#if GTEST_OS_ESP8266 || GTEST_OS_ESP32
|
||||
#if GTEST_OS_ESP8266
|
||||
extern "C" {
|
||||
#endif
|
||||
void setup() {
|
||||
// Since Google Mock depends on Google Test, InitGoogleMock() is
|
||||
// also responsible for initializing Google Test. Therefore there's
|
||||
// no need for calling testing::InitGoogleTest() separately.
|
||||
testing::InitGoogleMock();
|
||||
}
|
||||
void loop() { RUN_ALL_TESTS(); }
|
||||
#if GTEST_OS_ESP8266
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
// MS C++ compiler/linker has a bug on Windows (not on Windows CE), which
|
||||
// causes a link error when _tmain is defined in a static library and UNICODE
|
||||
// is enabled. For this reason instead of _tmain, main function is used on
|
||||
// Windows. See the following link to track the current status of this bug:
|
||||
// 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
|
||||
|
||||
GTEST_API_ int _tmain(int argc, TCHAR** argv) {
|
||||
#else
|
||||
GTEST_API_ int main(int argc, char** argv) {
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
std::cout << "Running main() from gmock_main.cc\n";
|
||||
// Since Google Mock depends on Google Test, InitGoogleMock() is
|
||||
// also responsible for initializing Google Test. Therefore there's
|
||||
// no need for calling testing::InitGoogleTest() separately.
|
||||
testing::InitGoogleMock(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
#endif
|
1644
tests/gtest/gtest-death-test.cc
Normal file
1644
tests/gtest/gtest-death-test.cc
Normal file
File diff suppressed because it is too large
Load Diff
369
tests/gtest/gtest-filepath.cc
Normal file
369
tests/gtest/gtest-filepath.cc
Normal file
@@ -0,0 +1,369 @@
|
||||
// Copyright 2008, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "gtest/internal/gtest-filepath.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "gtest/gtest-message.h"
|
||||
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
# include <windows.h>
|
||||
#elif GTEST_OS_WINDOWS
|
||||
# include <direct.h>
|
||||
# include <io.h>
|
||||
#else
|
||||
# include <limits.h>
|
||||
# include <climits> // Some Linux distributions define PATH_MAX here.
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
|
||||
#include "gtest/internal/gtest-string.h"
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# define GTEST_PATH_MAX_ _MAX_PATH
|
||||
#elif defined(PATH_MAX)
|
||||
# define GTEST_PATH_MAX_ PATH_MAX
|
||||
#elif defined(_XOPEN_PATH_MAX)
|
||||
# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
|
||||
#else
|
||||
# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// On Windows, '\\' is the standard path separator, but many tools and the
|
||||
// Windows API also accept '/' as an alternate path separator. Unless otherwise
|
||||
// noted, a file path can contain either kind of path separators, or a mixture
|
||||
// of them.
|
||||
const char kPathSeparator = '\\';
|
||||
const char kAlternatePathSeparator = '/';
|
||||
const char kAlternatePathSeparatorString[] = "/";
|
||||
# if GTEST_OS_WINDOWS_MOBILE
|
||||
// Windows CE doesn't have a current directory. You should not use
|
||||
// the current directory in tests on Windows CE, but this at least
|
||||
// provides a reasonable fallback.
|
||||
const char kCurrentDirectoryString[] = "\\";
|
||||
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
|
||||
const DWORD kInvalidFileAttributes = 0xffffffff;
|
||||
# else
|
||||
const char kCurrentDirectoryString[] = ".\\";
|
||||
# endif // GTEST_OS_WINDOWS_MOBILE
|
||||
#else
|
||||
const char kPathSeparator = '/';
|
||||
const char kCurrentDirectoryString[] = "./";
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
// Returns whether the given character is a valid path separator.
|
||||
static bool IsPathSeparator(char c) {
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
return (c == kPathSeparator) || (c == kAlternatePathSeparator);
|
||||
#else
|
||||
return c == kPathSeparator;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns the current working directory, or "" if unsuccessful.
|
||||
FilePath FilePath::GetCurrentDir() {
|
||||
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \
|
||||
GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_ESP32 || \
|
||||
GTEST_OS_XTENSA
|
||||
// These platforms do not have a current directory, so we just return
|
||||
// something reasonable.
|
||||
return FilePath(kCurrentDirectoryString);
|
||||
#elif GTEST_OS_WINDOWS
|
||||
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
||||
return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd);
|
||||
#else
|
||||
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
||||
char* result = getcwd(cwd, sizeof(cwd));
|
||||
# if GTEST_OS_NACL
|
||||
// getcwd will likely fail in NaCl due to the sandbox, so return something
|
||||
// reasonable. The user may have provided a shim implementation for getcwd,
|
||||
// however, so fallback only when failure is detected.
|
||||
return FilePath(result == nullptr ? kCurrentDirectoryString : cwd);
|
||||
# endif // GTEST_OS_NACL
|
||||
return FilePath(result == nullptr ? "" : cwd);
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
}
|
||||
|
||||
// Returns a copy of the FilePath with the case-insensitive extension removed.
|
||||
// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
|
||||
// FilePath("dir/file"). If a case-insensitive extension is not
|
||||
// found, returns a copy of the original FilePath.
|
||||
FilePath FilePath::RemoveExtension(const char* extension) const {
|
||||
const std::string dot_extension = std::string(".") + extension;
|
||||
if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) {
|
||||
return FilePath(pathname_.substr(
|
||||
0, pathname_.length() - dot_extension.length()));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Returns a pointer to the last occurrence of a valid path separator in
|
||||
// the FilePath. On Windows, for example, both '/' and '\' are valid path
|
||||
// separators. Returns NULL if no path separator was found.
|
||||
const char* FilePath::FindLastPathSeparator() const {
|
||||
const char* const last_sep = strrchr(c_str(), kPathSeparator);
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
|
||||
// Comparing two pointers of which only one is NULL is undefined.
|
||||
if (last_alt_sep != nullptr &&
|
||||
(last_sep == nullptr || last_alt_sep > last_sep)) {
|
||||
return last_alt_sep;
|
||||
}
|
||||
#endif
|
||||
return last_sep;
|
||||
}
|
||||
|
||||
// Returns a copy of the FilePath with the directory part removed.
|
||||
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
|
||||
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
|
||||
// the FilePath unmodified. If there is no file part ("just_a_dir/") it
|
||||
// returns an empty FilePath ("").
|
||||
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
||||
FilePath FilePath::RemoveDirectoryName() const {
|
||||
const char* const last_sep = FindLastPathSeparator();
|
||||
return last_sep ? FilePath(last_sep + 1) : *this;
|
||||
}
|
||||
|
||||
// RemoveFileName returns the directory path with the filename removed.
|
||||
// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
|
||||
// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
|
||||
// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
|
||||
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
|
||||
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
||||
FilePath FilePath::RemoveFileName() const {
|
||||
const char* const last_sep = FindLastPathSeparator();
|
||||
std::string dir;
|
||||
if (last_sep) {
|
||||
dir = std::string(c_str(), static_cast<size_t>(last_sep + 1 - c_str()));
|
||||
} else {
|
||||
dir = kCurrentDirectoryString;
|
||||
}
|
||||
return FilePath(dir);
|
||||
}
|
||||
|
||||
// Helper functions for naming files in a directory for xml output.
|
||||
|
||||
// Given directory = "dir", base_name = "test", number = 0,
|
||||
// extension = "xml", returns "dir/test.xml". If number is greater
|
||||
// than zero (e.g., 12), returns "dir/test_12.xml".
|
||||
// On Windows platform, uses \ as the separator rather than /.
|
||||
FilePath FilePath::MakeFileName(const FilePath& directory,
|
||||
const FilePath& base_name,
|
||||
int number,
|
||||
const char* extension) {
|
||||
std::string file;
|
||||
if (number == 0) {
|
||||
file = base_name.string() + "." + extension;
|
||||
} else {
|
||||
file = base_name.string() + "_" + StreamableToString(number)
|
||||
+ "." + extension;
|
||||
}
|
||||
return ConcatPaths(directory, FilePath(file));
|
||||
}
|
||||
|
||||
// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
|
||||
// On Windows, uses \ as the separator rather than /.
|
||||
FilePath FilePath::ConcatPaths(const FilePath& directory,
|
||||
const FilePath& relative_path) {
|
||||
if (directory.IsEmpty())
|
||||
return relative_path;
|
||||
const FilePath dir(directory.RemoveTrailingPathSeparator());
|
||||
return FilePath(dir.string() + kPathSeparator + relative_path.string());
|
||||
}
|
||||
|
||||
// Returns true if pathname describes something findable in the file-system,
|
||||
// either a file, directory, or whatever.
|
||||
bool FilePath::FileOrDirectoryExists() const {
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
|
||||
const DWORD attributes = GetFileAttributes(unicode);
|
||||
delete [] unicode;
|
||||
return attributes != kInvalidFileAttributes;
|
||||
#else
|
||||
posix::StatStruct file_stat{};
|
||||
return posix::Stat(pathname_.c_str(), &file_stat) == 0;
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
}
|
||||
|
||||
// Returns true if pathname describes a directory in the file-system
|
||||
// that exists.
|
||||
bool FilePath::DirectoryExists() const {
|
||||
bool result = false;
|
||||
#if GTEST_OS_WINDOWS
|
||||
// Don't strip off trailing separator if path is a root directory on
|
||||
// Windows (like "C:\\").
|
||||
const FilePath& path(IsRootDirectory() ? *this :
|
||||
RemoveTrailingPathSeparator());
|
||||
#else
|
||||
const FilePath& path(*this);
|
||||
#endif
|
||||
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
|
||||
const DWORD attributes = GetFileAttributes(unicode);
|
||||
delete [] unicode;
|
||||
if ((attributes != kInvalidFileAttributes) &&
|
||||
(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
result = true;
|
||||
}
|
||||
#else
|
||||
posix::StatStruct file_stat{};
|
||||
result = posix::Stat(path.c_str(), &file_stat) == 0 &&
|
||||
posix::IsDir(file_stat);
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns true if pathname describes a root directory. (Windows has one
|
||||
// root directory per disk drive.)
|
||||
bool FilePath::IsRootDirectory() const {
|
||||
#if GTEST_OS_WINDOWS
|
||||
return pathname_.length() == 3 && IsAbsolutePath();
|
||||
#else
|
||||
return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns true if pathname describes an absolute path.
|
||||
bool FilePath::IsAbsolutePath() const {
|
||||
const char* const name = pathname_.c_str();
|
||||
#if GTEST_OS_WINDOWS
|
||||
return pathname_.length() >= 3 &&
|
||||
((name[0] >= 'a' && name[0] <= 'z') ||
|
||||
(name[0] >= 'A' && name[0] <= 'Z')) &&
|
||||
name[1] == ':' &&
|
||||
IsPathSeparator(name[2]);
|
||||
#else
|
||||
return IsPathSeparator(name[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns a pathname for a file that does not currently exist. The pathname
|
||||
// will be directory/base_name.extension or
|
||||
// directory/base_name_<number>.extension if directory/base_name.extension
|
||||
// already exists. The number will be incremented until a pathname is found
|
||||
// that does not already exist.
|
||||
// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
|
||||
// There could be a race condition if two or more processes are calling this
|
||||
// function at the same time -- they could both pick the same filename.
|
||||
FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
|
||||
const FilePath& base_name,
|
||||
const char* extension) {
|
||||
FilePath full_pathname;
|
||||
int number = 0;
|
||||
do {
|
||||
full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
|
||||
} while (full_pathname.FileOrDirectoryExists());
|
||||
return full_pathname;
|
||||
}
|
||||
|
||||
// Returns true if FilePath ends with a path separator, which indicates that
|
||||
// it is intended to represent a directory. Returns false otherwise.
|
||||
// This does NOT check that a directory (or file) actually exists.
|
||||
bool FilePath::IsDirectory() const {
|
||||
return !pathname_.empty() &&
|
||||
IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
|
||||
}
|
||||
|
||||
// Create directories so that path exists. Returns true if successful or if
|
||||
// the directories already exist; returns false if unable to create directories
|
||||
// for any reason.
|
||||
bool FilePath::CreateDirectoriesRecursively() const {
|
||||
if (!this->IsDirectory()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pathname_.length() == 0 || this->DirectoryExists()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
|
||||
return parent.CreateDirectoriesRecursively() && this->CreateFolder();
|
||||
}
|
||||
|
||||
// Create the directory so that path exists. Returns true if successful or
|
||||
// if the directory already exists; returns false if unable to create the
|
||||
// directory for any reason, including if the parent directory does not
|
||||
// exist. Not named "CreateDirectory" because that's a macro on Windows.
|
||||
bool FilePath::CreateFolder() const {
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
FilePath removed_sep(this->RemoveTrailingPathSeparator());
|
||||
LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
|
||||
int result = CreateDirectory(unicode, nullptr) ? 0 : -1;
|
||||
delete [] unicode;
|
||||
#elif GTEST_OS_WINDOWS
|
||||
int result = _mkdir(pathname_.c_str());
|
||||
#elif GTEST_OS_ESP8266 || GTEST_OS_XTENSA
|
||||
// do nothing
|
||||
int result = 0;
|
||||
#else
|
||||
int result = mkdir(pathname_.c_str(), 0777);
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
|
||||
if (result == -1) {
|
||||
return this->DirectoryExists(); // An error is OK if the directory exists.
|
||||
}
|
||||
return true; // No error.
|
||||
}
|
||||
|
||||
// If input name has a trailing separator character, remove it and return the
|
||||
// name, otherwise return the name string unmodified.
|
||||
// On Windows platform, uses \ as the separator, other platforms use /.
|
||||
FilePath FilePath::RemoveTrailingPathSeparator() const {
|
||||
return IsDirectory()
|
||||
? FilePath(pathname_.substr(0, pathname_.length() - 1))
|
||||
: *this;
|
||||
}
|
||||
|
||||
// Removes any redundant separators that might be in the pathname.
|
||||
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
|
||||
// redundancies that might be in a pathname involving "." or "..".
|
||||
void FilePath::Normalize() {
|
||||
auto out = pathname_.begin();
|
||||
|
||||
for (const char character : pathname_) {
|
||||
if (!IsPathSeparator(character)) {
|
||||
*(out++) = character;
|
||||
} else if (out == pathname_.begin() || *std::prev(out) != kPathSeparator) {
|
||||
*(out++) = kPathSeparator;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
pathname_.erase(out, pathname_.end());
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
1433
tests/gtest/gtest-port.cc
Normal file
1433
tests/gtest/gtest-port.cc
Normal file
File diff suppressed because it is too large
Load Diff
533
tests/gtest/gtest-printers.cc
Normal file
533
tests/gtest/gtest-printers.cc
Normal file
@@ -0,0 +1,533 @@
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Google Test - The Google C++ Testing and Mocking Framework
|
||||
//
|
||||
// This file implements a universal value printer that can print a
|
||||
// value of any type T:
|
||||
//
|
||||
// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
|
||||
//
|
||||
// It uses the << operator when possible, and prints the bytes in the
|
||||
// object otherwise. A user can override its behavior for a class
|
||||
// type Foo by defining either operator<<(::std::ostream&, const Foo&)
|
||||
// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
|
||||
// defines Foo.
|
||||
|
||||
#include "gtest/gtest-printers.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
#include <cwchar>
|
||||
#include <ostream> // NOLINT
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "gtest/gtest-internal-inl.h"
|
||||
|
||||
namespace testing {
|
||||
|
||||
namespace {
|
||||
|
||||
using ::std::ostream;
|
||||
|
||||
// Prints a segment of bytes in the given object.
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
||||
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
|
||||
size_t count, ostream* os) {
|
||||
char text[5] = "";
|
||||
for (size_t i = 0; i != count; i++) {
|
||||
const size_t j = start + i;
|
||||
if (i != 0) {
|
||||
// Organizes the bytes into groups of 2 for easy parsing by
|
||||
// human.
|
||||
if ((j % 2) == 0)
|
||||
*os << ' ';
|
||||
else
|
||||
*os << '-';
|
||||
}
|
||||
GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
|
||||
*os << text;
|
||||
}
|
||||
}
|
||||
|
||||
// Prints the bytes in the given value to the given ostream.
|
||||
void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
|
||||
ostream* os) {
|
||||
// Tells the user how big the object is.
|
||||
*os << count << "-byte object <";
|
||||
|
||||
const size_t kThreshold = 132;
|
||||
const size_t kChunkSize = 64;
|
||||
// If the object size is bigger than kThreshold, we'll have to omit
|
||||
// some details by printing only the first and the last kChunkSize
|
||||
// bytes.
|
||||
if (count < kThreshold) {
|
||||
PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
|
||||
} else {
|
||||
PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
|
||||
*os << " ... ";
|
||||
// Rounds up to 2-byte boundary.
|
||||
const size_t resume_pos = (count - kChunkSize + 1)/2*2;
|
||||
PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
|
||||
}
|
||||
*os << ">";
|
||||
}
|
||||
|
||||
// Helpers for widening a character to char32_t. Since the standard does not
|
||||
// specify if char / wchar_t is signed or unsigned, it is important to first
|
||||
// convert it to the unsigned type of the same width before widening it to
|
||||
// char32_t.
|
||||
template <typename CharType>
|
||||
char32_t ToChar32(CharType in) {
|
||||
return static_cast<char32_t>(
|
||||
static_cast<typename std::make_unsigned<CharType>::type>(in));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
|
||||
// given object. The delegation simplifies the implementation, which
|
||||
// uses the << operator and thus is easier done outside of the
|
||||
// ::testing::internal namespace, which contains a << operator that
|
||||
// sometimes conflicts with the one in STL.
|
||||
void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
|
||||
ostream* os) {
|
||||
PrintBytesInObjectToImpl(obj_bytes, count, os);
|
||||
}
|
||||
|
||||
// Depending on the value of a char (or wchar_t), we print it in one
|
||||
// of three formats:
|
||||
// - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
|
||||
// - as a hexadecimal escape sequence (e.g. '\x7F'), or
|
||||
// - as a special escape sequence (e.g. '\r', '\n').
|
||||
enum CharFormat {
|
||||
kAsIs,
|
||||
kHexEscape,
|
||||
kSpecialEscape
|
||||
};
|
||||
|
||||
// Returns true if c is a printable ASCII character. We test the
|
||||
// value of c directly instead of calling isprint(), which is buggy on
|
||||
// Windows Mobile.
|
||||
inline bool IsPrintableAscii(char32_t c) { return 0x20 <= c && c <= 0x7E; }
|
||||
|
||||
// Prints c (of type char, char8_t, char16_t, char32_t, or wchar_t) as a
|
||||
// character literal without the quotes, escaping it when necessary; returns how
|
||||
// c was formatted.
|
||||
template <typename Char>
|
||||
static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
||||
const char32_t u_c = ToChar32(c);
|
||||
switch (u_c) {
|
||||
case L'\0':
|
||||
*os << "\\0";
|
||||
break;
|
||||
case L'\'':
|
||||
*os << "\\'";
|
||||
break;
|
||||
case L'\\':
|
||||
*os << "\\\\";
|
||||
break;
|
||||
case L'\a':
|
||||
*os << "\\a";
|
||||
break;
|
||||
case L'\b':
|
||||
*os << "\\b";
|
||||
break;
|
||||
case L'\f':
|
||||
*os << "\\f";
|
||||
break;
|
||||
case L'\n':
|
||||
*os << "\\n";
|
||||
break;
|
||||
case L'\r':
|
||||
*os << "\\r";
|
||||
break;
|
||||
case L'\t':
|
||||
*os << "\\t";
|
||||
break;
|
||||
case L'\v':
|
||||
*os << "\\v";
|
||||
break;
|
||||
default:
|
||||
if (IsPrintableAscii(u_c)) {
|
||||
*os << static_cast<char>(c);
|
||||
return kAsIs;
|
||||
} else {
|
||||
ostream::fmtflags flags = os->flags();
|
||||
*os << "\\x" << std::hex << std::uppercase << static_cast<int>(u_c);
|
||||
os->flags(flags);
|
||||
return kHexEscape;
|
||||
}
|
||||
}
|
||||
return kSpecialEscape;
|
||||
}
|
||||
|
||||
// Prints a char32_t c as if it's part of a string literal, escaping it when
|
||||
// necessary; returns how c was formatted.
|
||||
static CharFormat PrintAsStringLiteralTo(char32_t c, ostream* os) {
|
||||
switch (c) {
|
||||
case L'\'':
|
||||
*os << "'";
|
||||
return kAsIs;
|
||||
case L'"':
|
||||
*os << "\\\"";
|
||||
return kSpecialEscape;
|
||||
default:
|
||||
return PrintAsCharLiteralTo(c, os);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(char) {
|
||||
return "";
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(signed char) {
|
||||
return "";
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(unsigned char) {
|
||||
return "";
|
||||
}
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
static const char* GetCharWidthPrefix(char8_t) {
|
||||
return "u8";
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* GetCharWidthPrefix(char16_t) {
|
||||
return "u";
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(char32_t) {
|
||||
return "U";
|
||||
}
|
||||
|
||||
static const char* GetCharWidthPrefix(wchar_t) {
|
||||
return "L";
|
||||
}
|
||||
|
||||
// Prints a char c as if it's part of a string literal, escaping it when
|
||||
// necessary; returns how c was formatted.
|
||||
static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
|
||||
return PrintAsStringLiteralTo(ToChar32(c), os);
|
||||
}
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
static CharFormat PrintAsStringLiteralTo(char8_t c, ostream* os) {
|
||||
return PrintAsStringLiteralTo(ToChar32(c), os);
|
||||
}
|
||||
#endif
|
||||
|
||||
static CharFormat PrintAsStringLiteralTo(char16_t c, ostream* os) {
|
||||
return PrintAsStringLiteralTo(ToChar32(c), os);
|
||||
}
|
||||
|
||||
static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
|
||||
return PrintAsStringLiteralTo(ToChar32(c), os);
|
||||
}
|
||||
|
||||
// Prints a character c (of type char, char8_t, char16_t, char32_t, or wchar_t)
|
||||
// and its code. '\0' is printed as "'\\0'", other unprintable characters are
|
||||
// also properly escaped using the standard C++ escape sequence.
|
||||
template <typename Char>
|
||||
void PrintCharAndCodeTo(Char c, ostream* os) {
|
||||
// First, print c as a literal in the most readable form we can find.
|
||||
*os << GetCharWidthPrefix(c) << "'";
|
||||
const CharFormat format = PrintAsCharLiteralTo(c, os);
|
||||
*os << "'";
|
||||
|
||||
// To aid user debugging, we also print c's code in decimal, unless
|
||||
// it's 0 (in which case c was printed as '\\0', making the code
|
||||
// obvious).
|
||||
if (c == 0)
|
||||
return;
|
||||
*os << " (" << static_cast<int>(c);
|
||||
|
||||
// For more convenience, we print c's code again in hexadecimal,
|
||||
// unless c was already printed in the form '\x##' or the code is in
|
||||
// [1, 9].
|
||||
if (format == kHexEscape || (1 <= c && c <= 9)) {
|
||||
// Do nothing.
|
||||
} else {
|
||||
*os << ", 0x" << String::FormatHexInt(static_cast<int>(c));
|
||||
}
|
||||
*os << ")";
|
||||
}
|
||||
|
||||
void PrintTo(unsigned char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
|
||||
void PrintTo(signed char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
|
||||
|
||||
// Prints a wchar_t as a symbol if it is printable or as its internal
|
||||
// code otherwise and also as its code. L'\0' is printed as "L'\\0'".
|
||||
void PrintTo(wchar_t wc, ostream* os) { PrintCharAndCodeTo(wc, os); }
|
||||
|
||||
// TODO(dcheng): Consider making this delegate to PrintCharAndCodeTo() as well.
|
||||
void PrintTo(char32_t c, ::std::ostream* os) {
|
||||
*os << std::hex << "U+" << std::uppercase << std::setfill('0') << std::setw(4)
|
||||
<< static_cast<uint32_t>(c);
|
||||
}
|
||||
|
||||
// Prints the given array of characters to the ostream. CharType must be either
|
||||
// char, char8_t, char16_t, char32_t, or wchar_t.
|
||||
// The array starts at begin, the length is len, it may include '\0' characters
|
||||
// and may not be NUL-terminated.
|
||||
template <typename CharType>
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
||||
static CharFormat PrintCharsAsStringTo(
|
||||
const CharType* begin, size_t len, ostream* os) {
|
||||
const char* const quote_prefix = GetCharWidthPrefix(*begin);
|
||||
*os << quote_prefix << "\"";
|
||||
bool is_previous_hex = false;
|
||||
CharFormat print_format = kAsIs;
|
||||
for (size_t index = 0; index < len; ++index) {
|
||||
const CharType cur = begin[index];
|
||||
if (is_previous_hex && IsXDigit(cur)) {
|
||||
// Previous character is of '\x..' form and this character can be
|
||||
// interpreted as another hexadecimal digit in its number. Break string to
|
||||
// disambiguate.
|
||||
*os << "\" " << quote_prefix << "\"";
|
||||
}
|
||||
is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
|
||||
// Remember if any characters required hex escaping.
|
||||
if (is_previous_hex) {
|
||||
print_format = kHexEscape;
|
||||
}
|
||||
}
|
||||
*os << "\"";
|
||||
return print_format;
|
||||
}
|
||||
|
||||
// Prints a (const) char/wchar_t array of 'len' elements, starting at address
|
||||
// 'begin'. CharType must be either char or wchar_t.
|
||||
template <typename CharType>
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
||||
static void UniversalPrintCharArray(
|
||||
const CharType* begin, size_t len, ostream* os) {
|
||||
// The code
|
||||
// const char kFoo[] = "foo";
|
||||
// generates an array of 4, not 3, elements, with the last one being '\0'.
|
||||
//
|
||||
// Therefore when printing a char array, we don't print the last element if
|
||||
// it's '\0', such that the output matches the string literal as it's
|
||||
// written in the source code.
|
||||
if (len > 0 && begin[len - 1] == '\0') {
|
||||
PrintCharsAsStringTo(begin, len - 1, os);
|
||||
return;
|
||||
}
|
||||
|
||||
// If, however, the last element in the array is not '\0', e.g.
|
||||
// const char kFoo[] = { 'f', 'o', 'o' };
|
||||
// we must print the entire array. We also print a message to indicate
|
||||
// that the array is not NUL-terminated.
|
||||
PrintCharsAsStringTo(begin, len, os);
|
||||
*os << " (no terminating NUL)";
|
||||
}
|
||||
|
||||
// Prints a (const) char array of 'len' elements, starting at address 'begin'.
|
||||
void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
// Prints a (const) char8_t array of 'len' elements, starting at address
|
||||
// 'begin'.
|
||||
void UniversalPrintArray(const char8_t* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Prints a (const) char16_t array of 'len' elements, starting at address
|
||||
// 'begin'.
|
||||
void UniversalPrintArray(const char16_t* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
// Prints a (const) char32_t array of 'len' elements, starting at address
|
||||
// 'begin'.
|
||||
void UniversalPrintArray(const char32_t* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
// Prints a (const) wchar_t array of 'len' elements, starting at address
|
||||
// 'begin'.
|
||||
void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Prints a null-terminated C-style string to the ostream.
|
||||
template <typename Char>
|
||||
void PrintCStringTo(const Char* s, ostream* os) {
|
||||
if (s == nullptr) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
||||
PrintCharsAsStringTo(s, std::char_traits<Char>::length(s), os);
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void PrintTo(const char* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
void PrintTo(const char8_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
#endif
|
||||
|
||||
void PrintTo(const char16_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
|
||||
void PrintTo(const char32_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
|
||||
// MSVC compiler can be configured to define whar_t as a typedef
|
||||
// of unsigned short. Defining an overload for const wchar_t* in that case
|
||||
// would cause pointers to unsigned shorts be printed as wide strings,
|
||||
// possibly accessing more memory than intended and causing invalid
|
||||
// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
|
||||
// wchar_t is implemented as a native type.
|
||||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
// Prints the given wide C string to the ostream.
|
||||
void PrintTo(const wchar_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
#endif // wchar_t is native
|
||||
|
||||
namespace {
|
||||
|
||||
bool ContainsUnprintableControlCodes(const char* str, size_t length) {
|
||||
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
unsigned char ch = *s++;
|
||||
if (std::iscntrl(ch)) {
|
||||
switch (ch) {
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\r':
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t<= 0xbf; }
|
||||
|
||||
bool IsValidUTF8(const char* str, size_t length) {
|
||||
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
|
||||
|
||||
for (size_t i = 0; i < length;) {
|
||||
unsigned char lead = s[i++];
|
||||
|
||||
if (lead <= 0x7f) {
|
||||
continue; // single-byte character (ASCII) 0..7F
|
||||
}
|
||||
if (lead < 0xc2) {
|
||||
return false; // trail byte or non-shortest form
|
||||
} else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
|
||||
++i; // 2-byte character
|
||||
} else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
|
||||
IsUTF8TrailByte(s[i]) &&
|
||||
IsUTF8TrailByte(s[i + 1]) &&
|
||||
// check for non-shortest form and surrogate
|
||||
(lead != 0xe0 || s[i] >= 0xa0) &&
|
||||
(lead != 0xed || s[i] < 0xa0)) {
|
||||
i += 2; // 3-byte character
|
||||
} else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
|
||||
IsUTF8TrailByte(s[i]) &&
|
||||
IsUTF8TrailByte(s[i + 1]) &&
|
||||
IsUTF8TrailByte(s[i + 2]) &&
|
||||
// check for non-shortest form
|
||||
(lead != 0xf0 || s[i] >= 0x90) &&
|
||||
(lead != 0xf4 || s[i] < 0x90)) {
|
||||
i += 3; // 4-byte character
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
|
||||
if (!ContainsUnprintableControlCodes(str, length) &&
|
||||
IsValidUTF8(str, length)) {
|
||||
*os << "\n As Text: \"" << str << "\"";
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void PrintStringTo(const ::std::string& s, ostream* os) {
|
||||
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
|
||||
if (GTEST_FLAG(print_utf8)) {
|
||||
ConditionalPrintAsText(s.data(), s.size(), os);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
void PrintU8StringTo(const ::std::u8string& s, ostream* os) {
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
}
|
||||
#endif
|
||||
|
||||
void PrintU16StringTo(const ::std::u16string& s, ostream* os) {
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
}
|
||||
|
||||
void PrintU32StringTo(const ::std::u32string& s, ostream* os) {
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
}
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace testing
|
108
tests/gtest/gtest-test-part.cc
Normal file
108
tests/gtest/gtest-test-part.cc
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright 2008, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||
|
||||
#include "gtest/gtest-test-part.h"
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "gtest/gtest-internal-inl.h"
|
||||
|
||||
namespace testing {
|
||||
|
||||
using internal::GetUnitTestImpl;
|
||||
|
||||
// Gets the summary of the failure message by omitting the stack trace
|
||||
// in it.
|
||||
std::string TestPartResult::ExtractSummary(const char* message) {
|
||||
const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
|
||||
return stack_trace == nullptr ? message : std::string(message, stack_trace);
|
||||
}
|
||||
|
||||
// Prints a TestPartResult object.
|
||||
std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
|
||||
return os << internal::FormatFileLocation(result.file_name(),
|
||||
result.line_number())
|
||||
<< " "
|
||||
<< (result.type() == TestPartResult::kSuccess
|
||||
? "Success"
|
||||
: result.type() == TestPartResult::kSkip
|
||||
? "Skipped"
|
||||
: result.type() == TestPartResult::kFatalFailure
|
||||
? "Fatal failure"
|
||||
: "Non-fatal failure")
|
||||
<< ":\n"
|
||||
<< result.message() << std::endl;
|
||||
}
|
||||
|
||||
// Appends a TestPartResult to the array.
|
||||
void TestPartResultArray::Append(const TestPartResult& result) {
|
||||
array_.push_back(result);
|
||||
}
|
||||
|
||||
// Returns the TestPartResult at the given index (0-based).
|
||||
const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
|
||||
if (index < 0 || index >= size()) {
|
||||
printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
|
||||
internal::posix::Abort();
|
||||
}
|
||||
|
||||
return array_[static_cast<size_t>(index)];
|
||||
}
|
||||
|
||||
// Returns the number of TestPartResult objects in the array.
|
||||
int TestPartResultArray::size() const {
|
||||
return static_cast<int>(array_.size());
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
HasNewFatalFailureHelper::HasNewFatalFailureHelper()
|
||||
: has_new_fatal_failure_(false),
|
||||
original_reporter_(GetUnitTestImpl()->
|
||||
GetTestPartResultReporterForCurrentThread()) {
|
||||
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
|
||||
}
|
||||
|
||||
HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
|
||||
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
|
||||
original_reporter_);
|
||||
}
|
||||
|
||||
void HasNewFatalFailureHelper::ReportTestPartResult(
|
||||
const TestPartResult& result) {
|
||||
if (result.fatally_failed())
|
||||
has_new_fatal_failure_ = true;
|
||||
original_reporter_->ReportTestPartResult(result);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace testing
|
6746
tests/gtest/gtest.cc
Normal file
6746
tests/gtest/gtest.cc
Normal file
File diff suppressed because it is too large
Load Diff
54
tests/gtest/gtest_main.cc
Normal file
54
tests/gtest/gtest_main.cc
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2006, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <cstdio>
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#if GTEST_OS_ESP8266 || GTEST_OS_ESP32
|
||||
#if GTEST_OS_ESP8266
|
||||
extern "C" {
|
||||
#endif
|
||||
void setup() {
|
||||
testing::InitGoogleTest();
|
||||
}
|
||||
|
||||
void loop() { RUN_ALL_TESTS(); }
|
||||
|
||||
#if GTEST_OS_ESP8266
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
GTEST_API_ int main(int argc, char **argv) {
|
||||
printf("Running main() from %s\n", __FILE__);
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user