Updated gtest to upstream rev616
This commit is contained in:
parent
cfa9aa9206
commit
1ee5c95ee9
File diff suppressed because it is too large
Load Diff
@ -40,6 +40,7 @@
|
||||
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wmissing-declarations"
|
||||
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#endif
|
||||
|
||||
// The following lines pull in the real gtest *.cc files.
|
||||
@ -300,7 +301,7 @@ class GTEST_API_ SingleFailureChecker {
|
||||
(substr));\
|
||||
{\
|
||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
||||
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS,\
|
||||
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
|
||||
>est_failures);\
|
||||
if (::testing::internal::AlwaysTrue()) { statement; }\
|
||||
}\
|
||||
@ -313,6 +314,7 @@ class GTEST_API_ SingleFailureChecker {
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
|
||||
@ -514,6 +516,12 @@ GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
|
||||
// Formats the given time in milliseconds as seconds.
|
||||
GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
|
||||
|
||||
// Converts the given time in milliseconds to a date string in the ISO 8601
|
||||
// format, without the timezone information. N.B.: due to the use the
|
||||
// non-reentrant localtime() function, this function is not thread safe. Do
|
||||
// not use it in any code that can be called from multiple threads.
|
||||
GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms);
|
||||
|
||||
// Parses a string for an Int32 flag, in the form of "--flag=value".
|
||||
//
|
||||
// On success, stores the value of the flag in *value, and returns
|
||||
@ -592,6 +600,7 @@ class GTestFlagSaver {
|
||||
GTEST_FLAG(stream_result_to) = stream_result_to_;
|
||||
GTEST_FLAG(throw_on_failure) = throw_on_failure_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Fields for saving the original values of flags.
|
||||
bool also_run_disabled_tests_;
|
||||
@ -834,8 +843,11 @@ class OsStackTraceGetterInterface {
|
||||
class OsStackTraceGetter : public OsStackTraceGetterInterface {
|
||||
public:
|
||||
OsStackTraceGetter() : caller_frame_(NULL) {}
|
||||
virtual String CurrentStackTrace(int max_depth, int skip_count);
|
||||
virtual void UponLeavingGTest();
|
||||
|
||||
virtual String CurrentStackTrace(int max_depth, int skip_count)
|
||||
GTEST_LOCK_EXCLUDED_(mutex_);
|
||||
|
||||
virtual void UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_);
|
||||
|
||||
// This string is inserted in place of stack frames that are part of
|
||||
// Google Test's implementation.
|
||||
@ -950,6 +962,10 @@ class GTEST_API_ UnitTestImpl {
|
||||
// Gets the number of tests that should run.
|
||||
int test_to_run_count() const;
|
||||
|
||||
// Gets the time of the test program start, in ms from the start of the
|
||||
// UNIX epoch.
|
||||
TimeInMillis start_timestamp() const { return start_timestamp_; }
|
||||
|
||||
// Gets the elapsed time, in milliseconds.
|
||||
TimeInMillis elapsed_time() const { return elapsed_time_; }
|
||||
|
||||
@ -1008,7 +1024,7 @@ class GTEST_API_ UnitTestImpl {
|
||||
// For example, if Foo() calls Bar(), which in turn calls
|
||||
// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
|
||||
// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
|
||||
String CurrentOsStackTraceExceptTop(int skip_count);
|
||||
String CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_;
|
||||
|
||||
// Finds and returns a TestCase with the given name. If one doesn't
|
||||
// exist, creates one and returns it.
|
||||
@ -1282,6 +1298,10 @@ class GTEST_API_ UnitTestImpl {
|
||||
// Our random number generator.
|
||||
internal::Random random_;
|
||||
|
||||
// The time of the test program start, in ms from the start of the
|
||||
// UNIX epoch.
|
||||
TimeInMillis start_timestamp_;
|
||||
|
||||
// How long the test took to run, in milliseconds.
|
||||
TimeInMillis elapsed_time_;
|
||||
|
||||
@ -1613,7 +1633,7 @@ UInt32 Random::Generate(UInt32 range) {
|
||||
// Test. g_init_gtest_count is set to the number of times
|
||||
// InitGoogleTest() has been called. We don't protect this variable
|
||||
// under a mutex as it is only accessed in the main thread.
|
||||
int g_init_gtest_count = 0;
|
||||
GTEST_API_ int g_init_gtest_count = 0;
|
||||
static bool GTestIsInitialized() { return g_init_gtest_count != 0; }
|
||||
|
||||
// Iterates over a vector of TestCases, keeping a running sum of the
|
||||
@ -1668,7 +1688,7 @@ void AssertHelper::operator=(const Message& message) const {
|
||||
}
|
||||
|
||||
// Mutex for linked pointers.
|
||||
GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
|
||||
GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
|
||||
|
||||
// Application pathname gotten in InitGoogleTest.
|
||||
String g_executable_path;
|
||||
@ -2125,17 +2145,6 @@ TimeInMillis GetTimeInMillis() {
|
||||
|
||||
// class String
|
||||
|
||||
// Returns the input enclosed in double quotes if it's not NULL;
|
||||
// otherwise returns "(null)". For example, "\"Hello\"" is returned
|
||||
// for input "Hello".
|
||||
//
|
||||
// This is useful for printing a C string in the syntax of a literal.
|
||||
//
|
||||
// Known issue: escape sequences are not handled yet.
|
||||
String String::ShowCStringQuoted(const char* c_str) {
|
||||
return c_str ? String::Format("\"%s\"", c_str) : String("(null)");
|
||||
}
|
||||
|
||||
// Copies at most length characters from str into a newly-allocated
|
||||
// piece of memory of size length+1. The memory is allocated with new[].
|
||||
// A terminating null byte is written to the memory, and a pointer to it
|
||||
@ -2476,8 +2485,8 @@ AssertionResult CmpHelperSTREQ(const char* expected_expression,
|
||||
|
||||
return EqFailure(expected_expression,
|
||||
actual_expression,
|
||||
String::ShowCStringQuoted(expected),
|
||||
String::ShowCStringQuoted(actual),
|
||||
PrintToString(expected),
|
||||
PrintToString(actual),
|
||||
false);
|
||||
}
|
||||
|
||||
@ -2492,8 +2501,8 @@ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
|
||||
|
||||
return EqFailure(expected_expression,
|
||||
actual_expression,
|
||||
String::ShowCStringQuoted(expected),
|
||||
String::ShowCStringQuoted(actual),
|
||||
PrintToString(expected),
|
||||
PrintToString(actual),
|
||||
true);
|
||||
}
|
||||
|
||||
@ -2841,15 +2850,6 @@ String String::ShowWideCString(const wchar_t * wide_c_str) {
|
||||
return String(internal::WideStringToUtf8(wide_c_str, -1).c_str());
|
||||
}
|
||||
|
||||
// Similar to ShowWideCString(), except that this function encloses
|
||||
// the converted string in double quotes.
|
||||
String String::ShowWideCStringQuoted(const wchar_t* wide_c_str) {
|
||||
if (wide_c_str == NULL) return String("(null)");
|
||||
|
||||
return String::Format("L\"%s\"",
|
||||
String::ShowWideCString(wide_c_str).c_str());
|
||||
}
|
||||
|
||||
// Compares two wide C strings. Returns true iff they have the same
|
||||
// content.
|
||||
//
|
||||
@ -2875,8 +2875,8 @@ AssertionResult CmpHelperSTREQ(const char* expected_expression,
|
||||
|
||||
return EqFailure(expected_expression,
|
||||
actual_expression,
|
||||
String::ShowWideCStringQuoted(expected),
|
||||
String::ShowWideCStringQuoted(actual),
|
||||
PrintToString(expected),
|
||||
PrintToString(actual),
|
||||
false);
|
||||
}
|
||||
|
||||
@ -2891,8 +2891,8 @@ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
||||
|
||||
return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
|
||||
<< s2_expression << "), actual: "
|
||||
<< String::ShowWideCStringQuoted(s1)
|
||||
<< " vs " << String::ShowWideCStringQuoted(s2);
|
||||
<< PrintToString(s1)
|
||||
<< " vs " << PrintToString(s2);
|
||||
}
|
||||
|
||||
// Compares two C strings, ignoring case. Returns true iff they have
|
||||
@ -4015,8 +4015,6 @@ class PrettyUnitTestResultPrinter : public TestEventListener {
|
||||
|
||||
private:
|
||||
static void PrintFailedTests(const UnitTest& unit_test);
|
||||
|
||||
internal::String test_case_name_;
|
||||
};
|
||||
|
||||
// Fired before each iteration of tests starts.
|
||||
@ -4063,11 +4061,10 @@ void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart(
|
||||
}
|
||||
|
||||
void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
|
||||
test_case_name_ = test_case.name();
|
||||
const internal::String counts =
|
||||
FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
|
||||
ColoredPrintf(COLOR_GREEN, "[----------] ");
|
||||
printf("%s from %s", counts.c_str(), test_case_name_.c_str());
|
||||
printf("%s from %s", counts.c_str(), test_case.name());
|
||||
if (test_case.type_param() == NULL) {
|
||||
printf("\n");
|
||||
} else {
|
||||
@ -4078,7 +4075,7 @@ void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
|
||||
|
||||
void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
|
||||
ColoredPrintf(COLOR_GREEN, "[ RUN ] ");
|
||||
PrintTestName(test_case_name_.c_str(), test_info.name());
|
||||
PrintTestName(test_info.test_case_name(), test_info.name());
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
@ -4101,7 +4098,7 @@ void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
|
||||
} else {
|
||||
ColoredPrintf(COLOR_RED, "[ FAILED ] ");
|
||||
}
|
||||
PrintTestName(test_case_name_.c_str(), test_info.name());
|
||||
PrintTestName(test_info.test_case_name(), test_info.name());
|
||||
if (test_info.result()->Failed())
|
||||
PrintFullTestCommentIfPresent(test_info);
|
||||
|
||||
@ -4117,12 +4114,11 @@ void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
|
||||
void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) {
|
||||
if (!GTEST_FLAG(print_time)) return;
|
||||
|
||||
test_case_name_ = test_case.name();
|
||||
const internal::String counts =
|
||||
FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
|
||||
ColoredPrintf(COLOR_GREEN, "[----------] ");
|
||||
printf("%s from %s (%s ms total)\n\n",
|
||||
counts.c_str(), test_case_name_.c_str(),
|
||||
counts.c_str(), test_case.name(),
|
||||
internal::StreamableToString(test_case.elapsed_time()).c_str());
|
||||
fflush(stdout);
|
||||
}
|
||||
@ -4507,6 +4503,32 @@ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Converts the given epoch time in milliseconds to a date string in the ISO
|
||||
// 8601 format, without the timezone information.
|
||||
std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) {
|
||||
// Using non-reentrant version as localtime_r is not portable.
|
||||
time_t seconds = static_cast<time_t>(ms / 1000);
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push) // Saves the current warning state.
|
||||
# pragma warning(disable:4996) // Temporarily disables warning 4996
|
||||
// (function or variable may be unsafe).
|
||||
const struct tm* const time_struct = localtime(&seconds); // NOLINT
|
||||
# pragma warning(pop) // Restores the warning state again.
|
||||
#else
|
||||
const struct tm* const time_struct = localtime(&seconds); // NOLINT
|
||||
#endif
|
||||
if (time_struct == NULL)
|
||||
return ""; // Invalid ms value
|
||||
|
||||
return String::Format("%d-%02d-%02dT%02d:%02d:%02d", // YYYY-MM-DDThh:mm:ss
|
||||
time_struct->tm_year + 1900,
|
||||
time_struct->tm_mon + 1,
|
||||
time_struct->tm_mday,
|
||||
time_struct->tm_hour,
|
||||
time_struct->tm_min,
|
||||
time_struct->tm_sec);
|
||||
}
|
||||
|
||||
// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
|
||||
void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
|
||||
const char* data) {
|
||||
@ -4556,16 +4578,17 @@ void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
|
||||
for (int i = 0; i < result.total_part_count(); ++i) {
|
||||
const TestPartResult& part = result.GetTestPartResult(i);
|
||||
if (part.failed()) {
|
||||
if (++failures == 1)
|
||||
if (++failures == 1) {
|
||||
*stream << ">\n";
|
||||
*stream << " <failure message=\""
|
||||
<< EscapeXmlAttribute(part.summary()).c_str()
|
||||
<< "\" type=\"\">";
|
||||
}
|
||||
const string location = internal::FormatCompilerIndependentFileLocation(
|
||||
part.file_name(), part.line_number());
|
||||
const string message = location + "\n" + part.message();
|
||||
OutputXmlCDataSection(stream,
|
||||
RemoveInvalidXmlCharacters(message).c_str());
|
||||
const string summary = location + "\n" + part.summary();
|
||||
*stream << " <failure message=\""
|
||||
<< EscapeXmlAttribute(summary.c_str())
|
||||
<< "\" type=\"\">";
|
||||
const string detail = location + "\n" + part.message();
|
||||
OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
|
||||
*stream << "</failure>\n";
|
||||
}
|
||||
}
|
||||
@ -4603,10 +4626,11 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
|
||||
fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||
fprintf(out,
|
||||
"<testsuites tests=\"%d\" failures=\"%d\" disabled=\"%d\" "
|
||||
"errors=\"0\" time=\"%s\" ",
|
||||
"errors=\"0\" timestamp=\"%s\" time=\"%s\" ",
|
||||
unit_test.total_test_count(),
|
||||
unit_test.failed_test_count(),
|
||||
unit_test.disabled_test_count(),
|
||||
FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp()).c_str(),
|
||||
FormatTimeInMillisAsSeconds(unit_test.elapsed_time()).c_str());
|
||||
if (GTEST_FLAG(shuffle)) {
|
||||
fprintf(out, "random_seed=\"%d\" ", unit_test.random_seed());
|
||||
@ -4812,8 +4836,8 @@ void StreamingListener::MakeConnection() {
|
||||
|
||||
// Pushes the given source file location and message onto a per-thread
|
||||
// trace stack maintained by Google Test.
|
||||
// L < UnitTest::mutex_
|
||||
ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) {
|
||||
ScopedTrace::ScopedTrace(const char* file, int line, const Message& message)
|
||||
GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
|
||||
TraceInfo trace;
|
||||
trace.file = file;
|
||||
trace.line = line;
|
||||
@ -4823,8 +4847,8 @@ ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) {
|
||||
}
|
||||
|
||||
// Pops the info pushed by the c'tor.
|
||||
// L < UnitTest::mutex_
|
||||
ScopedTrace::~ScopedTrace() {
|
||||
ScopedTrace::~ScopedTrace()
|
||||
GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
|
||||
UnitTest::GetInstance()->PopGTestTrace();
|
||||
}
|
||||
|
||||
@ -4838,14 +4862,14 @@ ScopedTrace::~ScopedTrace() {
|
||||
// skip_count - the number of top frames to be skipped; doesn't count
|
||||
// against max_depth.
|
||||
//
|
||||
// L < mutex_
|
||||
// We use "L < mutex_" to denote that the function may acquire mutex_.
|
||||
String OsStackTraceGetter::CurrentStackTrace(int, int) {
|
||||
String OsStackTraceGetter::CurrentStackTrace(int /* max_depth */,
|
||||
int /* skip_count */)
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
return String("");
|
||||
}
|
||||
|
||||
// L < mutex_
|
||||
void OsStackTraceGetter::UponLeavingGTest() {
|
||||
void OsStackTraceGetter::UponLeavingGTest()
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
}
|
||||
|
||||
const char* const
|
||||
@ -4999,6 +5023,12 @@ int UnitTest::total_test_count() const { return impl()->total_test_count(); }
|
||||
// Gets the number of tests that should run.
|
||||
int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); }
|
||||
|
||||
// Gets the time of the test program start, in ms from the start of the
|
||||
// UNIX epoch.
|
||||
internal::TimeInMillis UnitTest::start_timestamp() const {
|
||||
return impl()->start_timestamp();
|
||||
}
|
||||
|
||||
// Gets the elapsed time, in milliseconds.
|
||||
internal::TimeInMillis UnitTest::elapsed_time() const {
|
||||
return impl()->elapsed_time();
|
||||
@ -5052,12 +5082,13 @@ Environment* UnitTest::AddEnvironment(Environment* env) {
|
||||
// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
|
||||
// this to report their results. The user code should use the
|
||||
// assertion macros instead of calling this directly.
|
||||
// L < mutex_
|
||||
void UnitTest::AddTestPartResult(TestPartResult::Type result_type,
|
||||
const char* file_name,
|
||||
int line_number,
|
||||
const internal::String& message,
|
||||
const internal::String& os_stack_trace) {
|
||||
void UnitTest::AddTestPartResult(
|
||||
TestPartResult::Type result_type,
|
||||
const char* file_name,
|
||||
int line_number,
|
||||
const internal::String& message,
|
||||
const internal::String& os_stack_trace)
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
Message msg;
|
||||
msg << message;
|
||||
|
||||
@ -5141,7 +5172,6 @@ int UnitTest::Run() {
|
||||
// process. In either case the user does not want to see pop-up dialogs
|
||||
// about crashes - they are expected.
|
||||
if (impl()->catch_exceptions() || in_death_test_child_process) {
|
||||
|
||||
# if !GTEST_OS_WINDOWS_MOBILE
|
||||
// SetErrorMode doesn't exist on CE.
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
|
||||
@ -5172,7 +5202,6 @@ int UnitTest::Run() {
|
||||
0x0, // Clear the following flags:
|
||||
_WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump.
|
||||
# endif
|
||||
|
||||
}
|
||||
#endif // GTEST_HAS_SEH
|
||||
|
||||
@ -5190,16 +5219,16 @@ const char* UnitTest::original_working_dir() const {
|
||||
|
||||
// Returns the TestCase object for the test that's currently running,
|
||||
// or NULL if no test is running.
|
||||
// L < mutex_
|
||||
const TestCase* UnitTest::current_test_case() const {
|
||||
const TestCase* UnitTest::current_test_case() const
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
return impl_->current_test_case();
|
||||
}
|
||||
|
||||
// Returns the TestInfo object for the test that's currently running,
|
||||
// or NULL if no test is running.
|
||||
// L < mutex_
|
||||
const TestInfo* UnitTest::current_test_info() const {
|
||||
const TestInfo* UnitTest::current_test_info() const
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
return impl_->current_test_info();
|
||||
}
|
||||
@ -5210,9 +5239,9 @@ int UnitTest::random_seed() const { return impl_->random_seed(); }
|
||||
#if GTEST_HAS_PARAM_TEST
|
||||
// Returns ParameterizedTestCaseRegistry object used to keep track of
|
||||
// value-parameterized tests and instantiate and register them.
|
||||
// L < mutex_
|
||||
internal::ParameterizedTestCaseRegistry&
|
||||
UnitTest::parameterized_test_registry() {
|
||||
UnitTest::parameterized_test_registry()
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
return impl_->parameterized_test_registry();
|
||||
}
|
||||
#endif // GTEST_HAS_PARAM_TEST
|
||||
@ -5229,15 +5258,15 @@ UnitTest::~UnitTest() {
|
||||
|
||||
// Pushes a trace defined by SCOPED_TRACE() on to the per-thread
|
||||
// Google Test trace stack.
|
||||
// L < mutex_
|
||||
void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) {
|
||||
void UnitTest::PushGTestTrace(const internal::TraceInfo& trace)
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
impl_->gtest_trace_stack().push_back(trace);
|
||||
}
|
||||
|
||||
// Pops a trace from the per-thread Google Test trace stack.
|
||||
// L < mutex_
|
||||
void UnitTest::PopGTestTrace() {
|
||||
void UnitTest::PopGTestTrace()
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
impl_->gtest_trace_stack().pop_back();
|
||||
}
|
||||
@ -5273,6 +5302,7 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent)
|
||||
post_flag_parse_init_performed_(false),
|
||||
random_seed_(0), // Will be overridden by the flag before first use.
|
||||
random_(0), // Will be reseeded before first use.
|
||||
start_timestamp_(0),
|
||||
elapsed_time_(0),
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
internal_run_death_test_flag_(NULL),
|
||||
@ -5504,6 +5534,7 @@ bool UnitTestImpl::RunAllTests() {
|
||||
|
||||
TestEventListener* repeater = listeners()->repeater();
|
||||
|
||||
start_timestamp_ = GetTimeInMillis();
|
||||
repeater->OnTestProgramStart(*parent_);
|
||||
|
||||
// How many times to repeat the tests? We don't want to repeat them
|
||||
@ -5865,7 +5896,7 @@ bool SkipPrefix(const char* prefix, const char** pstr) {
|
||||
// part can be omitted.
|
||||
//
|
||||
// Returns the value of the flag, or NULL if the parsing failed.
|
||||
static const char* ParseFlagValue(const char* str,
|
||||
const char* ParseFlagValue(const char* str,
|
||||
const char* flag,
|
||||
bool def_optional) {
|
||||
// str and flag must not be NULL.
|
||||
@ -6240,13 +6271,18 @@ void InitGoogleTest(int* argc, wchar_t** argv) {
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
# if GTEST_OS_MAC && !GTEST_OS_MAC_IOS
|
||||
# if GTEST_OS_MAC
|
||||
# include <crt_externs.h>
|
||||
# endif // GTEST_OS_MAC
|
||||
|
||||
# include <errno.h>
|
||||
# include <fcntl.h>
|
||||
# include <limits.h>
|
||||
|
||||
# if GTEST_OS_LINUX
|
||||
# include <signal.h>
|
||||
# endif // GTEST_OS_LINUX
|
||||
|
||||
# include <stdarg.h>
|
||||
|
||||
# if GTEST_OS_WINDOWS
|
||||
@ -6256,6 +6292,10 @@ void InitGoogleTest(int* argc, wchar_t** argv) {
|
||||
# include <sys/wait.h>
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
|
||||
# if GTEST_OS_QNX
|
||||
# include <spawn.h>
|
||||
# endif // GTEST_OS_QNX
|
||||
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
|
||||
@ -6301,13 +6341,42 @@ GTEST_DEFINE_string_(
|
||||
"Indicates the file, line number, temporal index of "
|
||||
"the single death test to run, and a file descriptor to "
|
||||
"which a success code may be sent, all separated by "
|
||||
"colons. This flag is specified if and only if the current "
|
||||
"the '|' characters. This flag is specified if and only if the current "
|
||||
"process is a sub-process launched for running a thread-safe "
|
||||
"death test. FOR INTERNAL USE ONLY.");
|
||||
} // namespace internal
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Valid only for fast death tests. Indicates the code is running in the
|
||||
// child process of a fast style death test.
|
||||
static bool g_in_fast_death_test_child = false;
|
||||
|
||||
// Returns a Boolean value indicating whether the caller is currently
|
||||
// executing in the context of the death test child process. Tools such as
|
||||
// Valgrind heap checkers may need this to modify their behavior in death
|
||||
// tests. IMPORTANT: This is an internal utility. Using it may break the
|
||||
// implementation of death tests. User code MUST NOT use it.
|
||||
bool InDeathTestChild() {
|
||||
# if GTEST_OS_WINDOWS
|
||||
|
||||
// On Windows, death tests are thread-safe regardless of the value of the
|
||||
// death_test_style flag.
|
||||
return !GTEST_FLAG(internal_run_death_test).empty();
|
||||
|
||||
# else
|
||||
|
||||
if (GTEST_FLAG(death_test_style) == "threadsafe")
|
||||
return !GTEST_FLAG(internal_run_death_test).empty();
|
||||
else
|
||||
return g_in_fast_death_test_child;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// ExitedWithCode constructor.
|
||||
ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
|
||||
}
|
||||
@ -7017,6 +7086,7 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() {
|
||||
// Event forwarding to the listeners of event listener API mush be shut
|
||||
// down in death test subprocesses.
|
||||
GetUnitTestImpl()->listeners()->SuppressEventForwarding();
|
||||
g_in_fast_death_test_child = true;
|
||||
return EXECUTE_TEST;
|
||||
} else {
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
|
||||
@ -7036,6 +7106,11 @@ class ExecDeathTest : public ForkingDeathTest {
|
||||
ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
|
||||
virtual TestRole AssumeRole();
|
||||
private:
|
||||
static ::std::vector<testing::internal::string>
|
||||
GetArgvsForDeathTestChildProcess() {
|
||||
::std::vector<testing::internal::string> args = GetInjectableArgvs();
|
||||
return args;
|
||||
}
|
||||
// The name of the file in which the death test is located.
|
||||
const char* const file_;
|
||||
// The line number on which the death test is located.
|
||||
@ -7070,6 +7145,7 @@ class Arguments {
|
||||
char* const* Argv() {
|
||||
return &args_[0];
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<char*> args_;
|
||||
};
|
||||
@ -7081,7 +7157,7 @@ struct ExecDeathTestArgs {
|
||||
int close_fd; // File descriptor to close; the read end of a pipe
|
||||
};
|
||||
|
||||
# if GTEST_OS_MAC && !GTEST_OS_MAC_IOS
|
||||
# if GTEST_OS_MAC
|
||||
inline char** GetEnviron() {
|
||||
// When Google Test is built as a framework on MacOS X, the environ variable
|
||||
// is unavailable. Apple's documentation (man environ) recommends using
|
||||
@ -7095,6 +7171,7 @@ extern "C" char** environ;
|
||||
inline char** GetEnviron() { return environ; }
|
||||
# endif // GTEST_OS_MAC
|
||||
|
||||
# if !GTEST_OS_QNX
|
||||
// The main function for a threadsafe-style death test child process.
|
||||
// This function is called in a clone()-ed process and thus must avoid
|
||||
// any potentially unsafe operations like malloc or libc functions.
|
||||
@ -7127,6 +7204,7 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
||||
GetLastErrnoDescription().c_str()));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
# endif // !GTEST_OS_QNX
|
||||
|
||||
// Two utility routines that together determine the direction the stack
|
||||
// grows.
|
||||
@ -7137,25 +7215,76 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
||||
// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
|
||||
// StackLowerThanAddress into StackGrowsDown, which then doesn't give
|
||||
// correct answer.
|
||||
bool StackLowerThanAddress(const void* ptr) GTEST_NO_INLINE_;
|
||||
bool StackLowerThanAddress(const void* ptr) {
|
||||
void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_;
|
||||
void StackLowerThanAddress(const void* ptr, bool* result) {
|
||||
int dummy;
|
||||
return &dummy < ptr;
|
||||
*result = (&dummy < ptr);
|
||||
}
|
||||
|
||||
static bool StackGrowsDown() {
|
||||
int dummy;
|
||||
return StackLowerThanAddress(&dummy);
|
||||
bool result;
|
||||
StackLowerThanAddress(&dummy, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// A threadsafe implementation of fork(2) for threadsafe-style death tests
|
||||
// that uses clone(2). It dies with an error message if anything goes
|
||||
// wrong.
|
||||
static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
|
||||
// Spawns a child process with the same executable as the current process in
|
||||
// a thread-safe manner and instructs it to run the death test. The
|
||||
// implementation uses fork(2) + exec. On systems where clone(2) is
|
||||
// available, it is used instead, being slightly more thread-safe. On QNX,
|
||||
// fork supports only single-threaded environments, so this function uses
|
||||
// spawn(2) there instead. The function dies with an error message if
|
||||
// anything goes wrong.
|
||||
static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||
ExecDeathTestArgs args = { argv, close_fd };
|
||||
pid_t child_pid = -1;
|
||||
|
||||
# if GTEST_HAS_CLONE
|
||||
# if GTEST_OS_QNX
|
||||
// Obtains the current directory and sets it to be closed in the child
|
||||
// process.
|
||||
const int cwd_fd = open(".", O_RDONLY);
|
||||
GTEST_DEATH_TEST_CHECK_(cwd_fd != -1);
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC));
|
||||
// We need to execute the test program in the same environment where
|
||||
// it was originally invoked. Therefore we change to the original
|
||||
// working directory first.
|
||||
const char* const original_dir =
|
||||
UnitTest::GetInstance()->original_working_dir();
|
||||
// We can safely call chdir() as it's a direct system call.
|
||||
if (chdir(original_dir) != 0) {
|
||||
DeathTestAbort(String::Format("chdir(\"%s\") failed: %s",
|
||||
original_dir,
|
||||
GetLastErrnoDescription().c_str()));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int fd_flags;
|
||||
// Set close_fd to be closed after spawn.
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD,
|
||||
fd_flags | FD_CLOEXEC));
|
||||
struct inheritance inherit = {0};
|
||||
// spawn is a system call.
|
||||
child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron());
|
||||
// Restores the current working directory.
|
||||
GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
|
||||
|
||||
# else // GTEST_OS_QNX
|
||||
# if GTEST_OS_LINUX
|
||||
// When a SIGPROF signal is received while fork() or clone() are executing,
|
||||
// the process may hang. To avoid this, we ignore SIGPROF here and re-enable
|
||||
// it after the call to fork()/clone() is complete.
|
||||
struct sigaction saved_sigprof_action;
|
||||
struct sigaction ignore_sigprof_action;
|
||||
memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action));
|
||||
sigemptyset(&ignore_sigprof_action.sa_mask);
|
||||
ignore_sigprof_action.sa_handler = SIG_IGN;
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction(
|
||||
SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
|
||||
# endif // GTEST_OS_LINUX
|
||||
|
||||
# if GTEST_HAS_CLONE
|
||||
const bool use_fork = GTEST_FLAG(death_test_use_fork);
|
||||
|
||||
if (!use_fork) {
|
||||
@ -7172,14 +7301,19 @@ static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
|
||||
|
||||
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
|
||||
}
|
||||
# else
|
||||
# else
|
||||
const bool use_fork = true;
|
||||
# endif // GTEST_HAS_CLONE
|
||||
# endif // GTEST_HAS_CLONE
|
||||
|
||||
if (use_fork && (child_pid = fork()) == 0) {
|
||||
ExecDeathTestChildMain(&args);
|
||||
_exit(0);
|
||||
}
|
||||
# endif // GTEST_OS_QNX
|
||||
# if GTEST_OS_LINUX
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(
|
||||
sigaction(SIGPROF, &saved_sigprof_action, NULL));
|
||||
# endif // GTEST_OS_LINUX
|
||||
|
||||
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
|
||||
return child_pid;
|
||||
@ -7216,7 +7350,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
||||
GTEST_FLAG_PREFIX_, kInternalRunDeathTestFlag,
|
||||
file_, line_, death_test_index, pipe_fd[1]);
|
||||
Arguments args;
|
||||
args.AddArguments(GetArgvs());
|
||||
args.AddArguments(GetArgvsForDeathTestChildProcess());
|
||||
args.AddArgument(filter_flag.c_str());
|
||||
args.AddArgument(internal_flag.c_str());
|
||||
|
||||
@ -7227,7 +7361,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
||||
// is necessary.
|
||||
FlushInfoLog();
|
||||
|
||||
const pid_t child_pid = ExecDeathTestFork(args.Argv(), pipe_fd[0]);
|
||||
const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]);
|
||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
|
||||
set_child_pid(child_pid);
|
||||
set_read_fd(pipe_fd[0]);
|
||||
@ -7862,6 +7996,11 @@ void FilePath::Normalize() {
|
||||
# include <mach/vm_map.h>
|
||||
#endif // GTEST_OS_MAC
|
||||
|
||||
#if GTEST_OS_QNX
|
||||
# include <devctl.h>
|
||||
# include <sys/procfs.h>
|
||||
#endif // GTEST_OS_QNX
|
||||
|
||||
|
||||
// Indicates that this translation unit is part of Google Test's
|
||||
// implementation. It must come before gtest-internal-inl.h is
|
||||
@ -7904,6 +8043,26 @@ size_t GetThreadCount() {
|
||||
}
|
||||
}
|
||||
|
||||
#elif GTEST_OS_QNX
|
||||
|
||||
// Returns the number of threads running in the process, or 0 to indicate that
|
||||
// we cannot detect it.
|
||||
size_t GetThreadCount() {
|
||||
const int fd = open("/proc/self/as", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return 0;
|
||||
}
|
||||
procfs_info process_info;
|
||||
const int status =
|
||||
devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL);
|
||||
close(fd);
|
||||
if (status == EOK) {
|
||||
return static_cast<size_t>(process_info.num_threads);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
size_t GetThreadCount() {
|
||||
@ -8295,7 +8454,6 @@ class CapturedStream {
|
||||
public:
|
||||
// The ctor redirects the stream to a temporary file.
|
||||
CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
|
||||
|
||||
# if GTEST_OS_WINDOWS
|
||||
char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT
|
||||
char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT
|
||||
@ -8312,10 +8470,15 @@ class CapturedStream {
|
||||
<< temp_file_path;
|
||||
filename_ = temp_file_path;
|
||||
# else
|
||||
// There's no guarantee that a test has write access to the
|
||||
// current directory, so we create the temporary file in the /tmp
|
||||
// directory instead.
|
||||
// There's no guarantee that a test has write access to the current
|
||||
// directory, so we create the temporary file in the /tmp directory instead.
|
||||
// We use /tmp on most systems, and /mnt/sdcard on Android. That's because
|
||||
// Android doesn't have /tmp.
|
||||
# if GTEST_OS_LINUX_ANDROID
|
||||
char name_template[] = "/mnt/sdcard/gtest_captured_stream.XXXXXX";
|
||||
# else
|
||||
char name_template[] = "/tmp/captured_stream.XXXXXX";
|
||||
# endif // GTEST_OS_LINUX_ANDROID
|
||||
const int captured_fd = mkstemp(name_template);
|
||||
filename_ = name_template;
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
@ -8434,11 +8597,23 @@ String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); }
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
// A copy of all command line arguments. Set by InitGoogleTest().
|
||||
::std::vector<String> g_argvs;
|
||||
::std::vector<testing::internal::string> g_argvs;
|
||||
|
||||
// Returns the command line as a vector of strings.
|
||||
const ::std::vector<String>& GetArgvs() { return g_argvs; }
|
||||
static const ::std::vector<testing::internal::string>* g_injected_test_argvs =
|
||||
NULL; // Owned.
|
||||
|
||||
void SetInjectableArgvs(const ::std::vector<testing::internal::string>* argvs) {
|
||||
if (g_injected_test_argvs != argvs)
|
||||
delete g_injected_test_argvs;
|
||||
g_injected_test_argvs = argvs;
|
||||
}
|
||||
|
||||
const ::std::vector<testing::internal::string>& GetInjectableArgvs() {
|
||||
if (g_injected_test_argvs != NULL) {
|
||||
return *g_injected_test_argvs;
|
||||
}
|
||||
return g_argvs;
|
||||
}
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
@ -8605,14 +8780,6 @@ namespace {
|
||||
|
||||
using ::std::ostream;
|
||||
|
||||
#if GTEST_OS_WINDOWS_MOBILE // Windows CE does not define _snprintf_s.
|
||||
# define snprintf _snprintf
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1400 // VC 8.0 and later deprecate snprintf and _snprintf.
|
||||
# define snprintf _snprintf_s
|
||||
#elif defined(_MSC_VER) && _MSC_VER
|
||||
# define snprintf _snprintf
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
|
||||
// Prints a segment of bytes in the given object.
|
||||
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
|
||||
size_t count, ostream* os) {
|
||||
@ -8627,7 +8794,7 @@ void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
|
||||
else
|
||||
*os << '-';
|
||||
}
|
||||
snprintf(text, sizeof(text), "%02X", obj_bytes[j]);
|
||||
GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
|
||||
*os << text;
|
||||
}
|
||||
}
|
||||
@ -8741,9 +8908,9 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
||||
return kSpecialEscape;
|
||||
}
|
||||
|
||||
// Prints a char c as if it's part of a string literal, escaping it when
|
||||
// Prints a wchar_t c as if it's part of a string literal, escaping it when
|
||||
// necessary; returns how c was formatted.
|
||||
static CharFormat PrintAsWideStringLiteralTo(wchar_t c, ostream* os) {
|
||||
static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
|
||||
switch (c) {
|
||||
case L'\'':
|
||||
*os << "'";
|
||||
@ -8758,8 +8925,9 @@ static CharFormat PrintAsWideStringLiteralTo(wchar_t c, ostream* os) {
|
||||
|
||||
// Prints a char c as if it's part of a string literal, escaping it when
|
||||
// necessary; returns how c was formatted.
|
||||
static CharFormat PrintAsNarrowStringLiteralTo(char c, ostream* os) {
|
||||
return PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os);
|
||||
static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
|
||||
return PrintAsStringLiteralTo(
|
||||
static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
|
||||
}
|
||||
|
||||
// Prints a wide or narrow character c and its code. '\0' is printed
|
||||
@ -8805,48 +8973,63 @@ void PrintTo(wchar_t wc, ostream* os) {
|
||||
PrintCharAndCodeTo<wchar_t>(wc, os);
|
||||
}
|
||||
|
||||
// Prints the given array of characters to the ostream.
|
||||
// The array starts at *begin, the length is len, it may include '\0' characters
|
||||
// and may not be null-terminated.
|
||||
static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) {
|
||||
*os << "\"";
|
||||
// Prints the given array of characters to the ostream. CharType must be either
|
||||
// char 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>
|
||||
static void PrintCharsAsStringTo(
|
||||
const CharType* begin, size_t len, ostream* os) {
|
||||
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
|
||||
*os << kQuoteBegin;
|
||||
bool is_previous_hex = false;
|
||||
for (size_t index = 0; index < len; ++index) {
|
||||
const char cur = begin[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 << "\" \"";
|
||||
*os << "\" " << kQuoteBegin;
|
||||
}
|
||||
is_previous_hex = PrintAsNarrowStringLiteralTo(cur, os) == kHexEscape;
|
||||
is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
|
||||
}
|
||||
*os << "\"";
|
||||
}
|
||||
|
||||
// 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>
|
||||
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) {
|
||||
PrintCharsAsStringTo(begin, len, os);
|
||||
UniversalPrintCharArray(begin, len, os);
|
||||
}
|
||||
|
||||
// Prints the given array of wide characters to the ostream.
|
||||
// The array starts at *begin, the length is len, it may include L'\0'
|
||||
// characters and may not be null-terminated.
|
||||
static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len,
|
||||
ostream* os) {
|
||||
*os << "L\"";
|
||||
bool is_previous_hex = false;
|
||||
for (size_t index = 0; index < len; ++index) {
|
||||
const wchar_t cur = begin[index];
|
||||
if (is_previous_hex && isascii(cur) && IsXDigit(static_cast<char>(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 << "\" L\"";
|
||||
}
|
||||
is_previous_hex = PrintAsWideStringLiteralTo(cur, os) == kHexEscape;
|
||||
}
|
||||
*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);
|
||||
}
|
||||
|
||||
// Prints the given C string to the ostream.
|
||||
@ -8872,7 +9055,7 @@ void PrintTo(const wchar_t* s, ostream* os) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
||||
PrintWideCharsAsStringTo(s, wcslen(s), os);
|
||||
PrintCharsAsStringTo(s, wcslen(s), os);
|
||||
}
|
||||
}
|
||||
#endif // wchar_t is native
|
||||
@ -8891,13 +9074,13 @@ void PrintStringTo(const ::std::string& s, ostream* os) {
|
||||
// Prints a ::wstring object.
|
||||
#if GTEST_HAS_GLOBAL_WSTRING
|
||||
void PrintWideStringTo(const ::wstring& s, ostream* os) {
|
||||
PrintWideCharsAsStringTo(s.data(), s.size(), os);
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
}
|
||||
#endif // GTEST_HAS_GLOBAL_WSTRING
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
|
||||
PrintWideCharsAsStringTo(s.data(), s.size(), os);
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
}
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user