From d4b5281d110f0c8e7cb794737a7832a2408e8e0c Mon Sep 17 00:00:00 2001 From: Fabrice de Gans-Riberi Date: Tue, 1 May 2018 16:20:31 -0700 Subject: [PATCH 1/9] Add Fuchsia support for death test. --- googletest/include/gtest/gtest.h | 2 + .../include/gtest/internal/gtest-port.h | 3 +- googletest/src/gtest-death-test.cc | 189 +++++++++++++++++- googletest/src/gtest-port.cc | 10 + 4 files changed, 200 insertions(+), 4 deletions(-) diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h index a0592a82..e1e9c1bb 100644 --- a/googletest/include/gtest/gtest.h +++ b/googletest/include/gtest/gtest.h @@ -172,6 +172,7 @@ class TestEventListenersAccessor; class TestEventRepeater; class UnitTestRecordPropertyTestHelper; class WindowsDeathTest; +class FuchsiaDeathTest; class UnitTestImpl* GetUnitTestImpl(); void ReportFailureInUnknownLocation(TestPartResult::Type result_type, const std::string& message); @@ -593,6 +594,7 @@ class GTEST_API_ TestResult { friend class internal::TestResultAccessor; friend class internal::UnitTestImpl; friend class internal::WindowsDeathTest; + friend class internal::FuchsiaDeathTest; // Gets the vector of TestPartResults. const std::vector& test_part_results() const { diff --git a/googletest/include/gtest/internal/gtest-port.h b/googletest/include/gtest/internal/gtest-port.h index e677cd97..fafb134b 100644 --- a/googletest/include/gtest/internal/gtest-port.h +++ b/googletest/include/gtest/internal/gtest-port.h @@ -813,7 +813,8 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; (GTEST_OS_MAC && !GTEST_OS_IOS) || \ (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \ GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \ - GTEST_OS_OPENBSD || GTEST_OS_QNX || GTEST_OS_FREEBSD || GTEST_OS_NETBSD) + GTEST_OS_OPENBSD || GTEST_OS_QNX || GTEST_OS_FREEBSD || \ + GTEST_OS_NETBSD || GTEST_OS_FUCHSIA) # define GTEST_HAS_DEATH_TEST 1 #endif diff --git a/googletest/src/gtest-death-test.cc b/googletest/src/gtest-death-test.cc index 9ecab8f9..eef6ed29 100644 --- a/googletest/src/gtest-death-test.cc +++ b/googletest/src/gtest-death-test.cc @@ -62,6 +62,11 @@ # include # endif // GTEST_OS_QNX +# if GTEST_OS_FUCHSIA +# include +# include +# endif // GTEST_OS_FUCHSIA + #endif // GTEST_HAS_DEATH_TEST #include "gtest/gtest-message.h" @@ -127,7 +132,7 @@ static bool g_in_fast_death_test_child = false; // 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 +# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA // On Windows, death tests are thread-safe regardless of the value of the // death_test_style flag. @@ -216,7 +221,7 @@ bool ExitedUnsuccessfully(int exit_status) { return !ExitedWithCode(0)(exit_status); } -# if !GTEST_OS_WINDOWS +# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA // Generates a textual failure message when a death test finds more than // one thread running, or cannot determine the number of threads, prior // to executing the given statement. It is the responsibility of the @@ -781,7 +786,178 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() { set_spawned(true); return OVERSEE_TEST; } -# else // We are not on Windows. + +# elif GTEST_OS_FUCHSIA + +class FuchsiaDeathTest : public DeathTestImpl { + public: + FuchsiaDeathTest(const char* a_statement, + const RE* a_regex, + const char* file, + int line) + : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {} + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + virtual TestRole AssumeRole(); + + private: + // 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. + const int line_; + + zx_handle_t child_process_; + // zx_handle_t crash_port_; +}; + +// Utility class for accumulating command-line arguments. +class Arguments { + public: + Arguments() { + args_.push_back(NULL); + } + + ~Arguments() { + for (std::vector::iterator i = args_.begin(); i != args_.end(); + ++i) { + free(*i); + } + } + void AddArgument(const char* argument) { + args_.insert(args_.end() - 1, posix::StrDup(argument)); + } + + template + void AddArguments(const ::std::vector& arguments) { + for (typename ::std::vector::const_iterator i = arguments.begin(); + i != arguments.end(); + ++i) { + args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); + } + } + char* const* Argv() { + return &args_[0]; + } + + private: + std::vector args_; +}; + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int FuchsiaDeathTest::Wait() { + if (!spawned()) + return 0; + + ReadAndInterpretStatusByte(); + + // Wait for child process to terminate. + zx_status_t status_zx; + zx_signals_t signals; + status_zx = zx_object_wait_one( + child_process_, + ZX_PROCESS_TERMINATED, + ZX_TIME_INFINITE, + &signals); + GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); + + // Do we need this? + // // Attempt to read the crash port. + // zx_port_packet_t packet; + // status = zx_port_wait(crash_port_, past, &packet, 1) + // if (status == ZX_ERR_TIMED_OUT) { + // // Process did not crash. + // set_outcome(LIVED); + // return status(); + // } + + zx_info_process_t buffer; + size_t actual; + size_t avail; + status_zx = zx_object_get_info(child_process_, ZX_INFO_PROCESS, &buffer, sizeof(buffer), &actual, &avail); + GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); + + GTEST_DEATH_TEST_CHECK_(buffer.exited); + set_status(buffer.return_code); + return status(); +} + +// The AssumeRole process for a Fuchsia death test. It creates a child +// process with the same executable as the current process to run the +// death test. The child process is given the --gtest_filter and +// --gtest_internal_run_death_test flags such that it knows to run the +// current death test only. +DeathTest::TestRole FuchsiaDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + // ParseInternalRunDeathTestFlag() has performed all the necessary + // processing. + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + // Create the crash port to report on. + // zx_status_t status = zx_port_create(0, &crash_port_); + // GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + + CaptureStderr(); + // Flush the log buffers since the log streams are shared with the child. + FlushInfoLog(); + + // Build the child process launcher. + launchpad_t* lp; + zx_status_t status; + status = launchpad_create(ZX_HANDLE_INVALID, "processname", &lp); + GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + + // Build the writing pipe for the child. + int write_fd; + status = launchpad_add_pipe(lp, &write_fd, read_fd()); + GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + + // Build the child command line. + const std::string filter_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + + info->test_case_name() + "." + info->name(); + const std::string internal_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" + + file_ + "|" + StreamableToString(line_) + "|" + + StreamableToString(death_test_index) + "|" + + StreamableToString(write_fd); + Arguments args; + args.AddArguments(GetInjectableArgvs()); + args.AddArgument(filter_flag.c_str()); + args.AddArgument(internal_flag.c_str()); + + status = launchpad_load_from_file(lp, args.Argv()[0]); + GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + status = launchpad_set_args(lp, GetArgvs().size() + 2, args.Argv()); + GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + + // Launch the child process. + zx_handle_t proc; + const char* errmsg; + status = launchpad_go(lp, &proc, &errmsg); + GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + child_process_ = proc; + + // bind the crash port. This should be moved to before launching the process. + // FIXME: I don't think this is necessary + // status = zx_task_bind_exception_port(child_process_, crash_port_, 0xabcabc, 0); + // GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + + set_spawned(true); + return OVERSEE_TEST; +} + +#else // We are neither on Windows, nor on Fuchsia. // ForkingDeathTest provides implementations for most of the abstract // methods of the DeathTest interface. Only the AssumeRole method is @@ -1204,6 +1380,13 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, *test = new WindowsDeathTest(statement, regex, file, line); } +# elif GTEST_OS_FUCHSIA + + if (GTEST_FLAG(death_test_style) == "threadsafe" || + GTEST_FLAG(death_test_style) == "fast") { + *test = new FuchsiaDeathTest(statement, regex, file, line); + } + # else if (GTEST_FLAG(death_test_style) == "threadsafe") { diff --git a/googletest/src/gtest-port.cc b/googletest/src/gtest-port.cc index d32afb1f..d6320894 100644 --- a/googletest/src/gtest-port.cc +++ b/googletest/src/gtest-port.cc @@ -63,6 +63,10 @@ # include #endif // GTEST_OS_AIX +#if GTEST_OS_FUCHSIA +# include +#endif + #include "gtest/gtest-spi.h" #include "gtest/gtest-message.h" #include "gtest/internal/gtest-internal.h" @@ -156,6 +160,12 @@ size_t GetThreadCount() { } } +#elif GTEST_OS_FUCHSIA + +size_t GetThreadCount() { + return static_cast(zx_system_get_num_cpus()); +} + #else size_t GetThreadCount() { From b6cb5c3e40acfe7c3d64429280dfd48a02379683 Mon Sep 17 00:00:00 2001 From: Fabrice de Gans-Riberi Date: Tue, 1 May 2018 18:41:03 -0700 Subject: [PATCH 2/9] Fix stuff --- googletest/src/gtest-death-test.cc | 56 ++++++++++++++---------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/googletest/src/gtest-death-test.cc b/googletest/src/gtest-death-test.cc index eef6ed29..bcfed4e7 100644 --- a/googletest/src/gtest-death-test.cc +++ b/googletest/src/gtest-death-test.cc @@ -63,6 +63,7 @@ # endif // GTEST_OS_QNX # if GTEST_OS_FUCHSIA +# include # include # include # endif // GTEST_OS_FUCHSIA @@ -543,7 +544,9 @@ bool DeathTestImpl::Passed(bool status_ok) { if (!spawned()) return false; - const std::string error_message = GetCapturedStderr(); + // FIXME: This isn't working. + //const std::string error_message = GetCapturedStderr(); + const std::string error_message = ""; bool success = false; Message buffer; @@ -808,7 +811,7 @@ class FuchsiaDeathTest : public DeathTestImpl { const int line_; zx_handle_t child_process_; - // zx_handle_t crash_port_; + zx_handle_t pipe_handle_; }; // Utility class for accumulating command-line arguments. @@ -840,6 +843,10 @@ class Arguments { return &args_[0]; } + int size() { + return args_.size() - 1; + } + private: std::vector args_; }; @@ -851,8 +858,6 @@ int FuchsiaDeathTest::Wait() { if (!spawned()) return 0; - ReadAndInterpretStatusByte(); - // Wait for child process to terminate. zx_status_t status_zx; zx_signals_t signals; @@ -863,15 +868,11 @@ int FuchsiaDeathTest::Wait() { &signals); GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); - // Do we need this? - // // Attempt to read the crash port. - // zx_port_packet_t packet; - // status = zx_port_wait(crash_port_, past, &packet, 1) - // if (status == ZX_ERR_TIMED_OUT) { - // // Process did not crash. - // set_outcome(LIVED); - // return status(); - // } + // Close the pipe. + status_zx = zx_handle_close(pipe_handle_); + GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); + + ReadAndInterpretStatusByte(); zx_info_process_t buffer; size_t actual; @@ -903,17 +904,21 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() { return EXECUTE_TEST; } - // Create the crash port to report on. - // zx_status_t status = zx_port_create(0, &crash_port_); - // GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + // FIXME: This isn't working on Fuchsia. + // CaptureStderr(); - CaptureStderr(); // Flush the log buffers since the log streams are shared with the child. FlushInfoLog(); + // Create the pipe + zx_status_t status; + uint32_t id; + status = fdio_pipe_half(&pipe_handle_, &id); + GTEST_DEATH_TEST_CHECK_(status >= 0); + set_read_fd(status); + // Build the child process launcher. launchpad_t* lp; - zx_status_t status; status = launchpad_create(ZX_HANDLE_INVALID, "processname", &lp); GTEST_DEATH_TEST_CHECK_(status == ZX_OK); @@ -922,7 +927,7 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() { status = launchpad_add_pipe(lp, &write_fd, read_fd()); GTEST_DEATH_TEST_CHECK_(status == ZX_OK); - // Build the child command line. + // Build the child process command line. const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + info->test_case_name() + "." + info->name(); @@ -936,22 +941,15 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() { args.AddArgument(filter_flag.c_str()); args.AddArgument(internal_flag.c_str()); + // Set the command line arguments. status = launchpad_load_from_file(lp, args.Argv()[0]); GTEST_DEATH_TEST_CHECK_(status == ZX_OK); - status = launchpad_set_args(lp, GetArgvs().size() + 2, args.Argv()); + status = launchpad_set_args(lp, args.size(), args.Argv()); GTEST_DEATH_TEST_CHECK_(status == ZX_OK); // Launch the child process. - zx_handle_t proc; - const char* errmsg; - status = launchpad_go(lp, &proc, &errmsg); + status = launchpad_go(lp, &child_process_, nullptr); GTEST_DEATH_TEST_CHECK_(status == ZX_OK); - child_process_ = proc; - - // bind the crash port. This should be moved to before launching the process. - // FIXME: I don't think this is necessary - // status = zx_task_bind_exception_port(child_process_, crash_port_, 0xabcabc, 0); - // GTEST_DEATH_TEST_CHECK_(status == ZX_OK); set_spawned(true); return OVERSEE_TEST; From 96c3c422ad1e1bd06da37e88cdd8e200b812f8f3 Mon Sep 17 00:00:00 2001 From: Fabrice de Gans-Riberi Date: Wed, 2 May 2018 14:57:56 -0700 Subject: [PATCH 3/9] Get all the things to work. --- googletest/src/gtest-death-test.cc | 80 +++++++++++++++++------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/googletest/src/gtest-death-test.cc b/googletest/src/gtest-death-test.cc index bcfed4e7..50c15edd 100644 --- a/googletest/src/gtest-death-test.cc +++ b/googletest/src/gtest-death-test.cc @@ -245,6 +245,13 @@ static const char kDeathTestReturned = 'R'; static const char kDeathTestThrew = 'T'; static const char kDeathTestInternalError = 'I'; +#if GTEST_OS_FUCHSIA + +// File descriptor used for the pipe in the child process. +static const int kFuchsiaReadPipeFd = 3; + +#endif + // An enumeration describing all of the possible ways that a death test can // conclude. DIED means that the process died while executing the test // code; LIVED means that process lived beyond the end of the test code; @@ -544,9 +551,7 @@ bool DeathTestImpl::Passed(bool status_ok) { if (!spawned()) return false; - // FIXME: This isn't working. - //const std::string error_message = GetCapturedStderr(); - const std::string error_message = ""; + const std::string error_message = GetCapturedStderr(); bool success = false; Message buffer; @@ -811,7 +816,6 @@ class FuchsiaDeathTest : public DeathTestImpl { const int line_; zx_handle_t child_process_; - zx_handle_t pipe_handle_; }; // Utility class for accumulating command-line arguments. @@ -868,16 +872,16 @@ int FuchsiaDeathTest::Wait() { &signals); GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); - // Close the pipe. - status_zx = zx_handle_close(pipe_handle_); - GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); - ReadAndInterpretStatusByte(); zx_info_process_t buffer; - size_t actual; - size_t avail; - status_zx = zx_object_get_info(child_process_, ZX_INFO_PROCESS, &buffer, sizeof(buffer), &actual, &avail); + status_zx = zx_object_get_info( + child_process_, + ZX_INFO_PROCESS, + &buffer, + sizeof(buffer), + nullptr, + nullptr); GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); GTEST_DEATH_TEST_CHECK_(buffer.exited); @@ -900,53 +904,49 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() { if (flag != NULL) { // ParseInternalRunDeathTestFlag() has performed all the necessary // processing. - set_write_fd(flag->write_fd()); + set_write_fd(kFuchsiaReadPipeFd); return EXECUTE_TEST; } - // FIXME: This isn't working on Fuchsia. - // CaptureStderr(); - + CaptureStderr(); // Flush the log buffers since the log streams are shared with the child. FlushInfoLog(); - // Create the pipe - zx_status_t status; - uint32_t id; - status = fdio_pipe_half(&pipe_handle_, &id); - GTEST_DEATH_TEST_CHECK_(status >= 0); - set_read_fd(status); - - // Build the child process launcher. - launchpad_t* lp; - status = launchpad_create(ZX_HANDLE_INVALID, "processname", &lp); - GTEST_DEATH_TEST_CHECK_(status == ZX_OK); - - // Build the writing pipe for the child. - int write_fd; - status = launchpad_add_pipe(lp, &write_fd, read_fd()); - GTEST_DEATH_TEST_CHECK_(status == ZX_OK); - // Build the child process command line. const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + info->test_case_name() + "." + info->name(); const std::string internal_flag = std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" - + file_ + "|" + StreamableToString(line_) + "|" - + StreamableToString(death_test_index) + "|" - + StreamableToString(write_fd); + + file_ + "|" + + StreamableToString(line_) + "|" + + StreamableToString(death_test_index); Arguments args; args.AddArguments(GetInjectableArgvs()); args.AddArgument(filter_flag.c_str()); args.AddArgument(internal_flag.c_str()); + // Build the child process launcher. + zx_status_t status; + launchpad_t* lp; + status = launchpad_create(ZX_HANDLE_INVALID, args.Argv()[0], &lp); + GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + + // Build the pipe for communication with the child. + int read_fd; + status = launchpad_add_pipe(lp, &read_fd, 3); + GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + set_read_fd(read_fd); + // Set the command line arguments. status = launchpad_load_from_file(lp, args.Argv()[0]); GTEST_DEATH_TEST_CHECK_(status == ZX_OK); status = launchpad_set_args(lp, args.size(), args.Argv()); GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + // Clone all the things (environment, stdio, namespace, ...). + launchpad_clone(lp, LP_CLONE_ALL); + // Launch the child process. status = launchpad_go(lp, &child_process_, nullptr); GTEST_DEATH_TEST_CHECK_(status == ZX_OK); @@ -1505,6 +1505,16 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { write_fd = GetStatusFileDescriptor(parent_process_id, write_handle_as_size_t, event_handle_as_size_t); + +# elif GTEST_OS_FUCHSIA + + if (fields.size() != 3 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index)) { + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + + GTEST_FLAG(internal_run_death_test)); + } + # else if (fields.size() != 4 From 13af91faff5aaec0a622601713bc4f8b89a8e108 Mon Sep 17 00:00:00 2001 From: Fabrice de Gans-Riberi Date: Thu, 3 May 2018 12:06:45 -0700 Subject: [PATCH 4/9] Fix more stuff and get tests to pass --- googletest/include/gtest/gtest-death-test.h | 2 +- googletest/src/gtest-death-test.cc | 14 +++++++------- googletest/src/gtest-port.cc | 16 +++++++++++++++- googletest/test/gtest-death-test_test.cc | 7 ++++--- googletest/test/gtest-options_test.cc | 6 ++++++ googletest/test/gtest-port_test.cc | 4 ++-- 6 files changed, 35 insertions(+), 14 deletions(-) diff --git a/googletest/include/gtest/gtest-death-test.h b/googletest/include/gtest/gtest-death-test.h index 6a216bcb..3834292f 100644 --- a/googletest/include/gtest/gtest-death-test.h +++ b/googletest/include/gtest/gtest-death-test.h @@ -198,7 +198,7 @@ class GTEST_API_ ExitedWithCode { const int exit_code_; }; -# if !GTEST_OS_WINDOWS +# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA // Tests that an exit code describes an exit due to termination by a // given signal. class GTEST_API_ KilledBySignal { diff --git a/googletest/src/gtest-death-test.cc b/googletest/src/gtest-death-test.cc index 50c15edd..a02d8100 100644 --- a/googletest/src/gtest-death-test.cc +++ b/googletest/src/gtest-death-test.cc @@ -156,7 +156,7 @@ ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { // ExitedWithCode function-call operator. bool ExitedWithCode::operator()(int exit_status) const { -# if GTEST_OS_WINDOWS +# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA return exit_status == exit_code_; @@ -167,7 +167,7 @@ bool ExitedWithCode::operator()(int exit_status) const { # endif // GTEST_OS_WINDOWS } -# if !GTEST_OS_WINDOWS +# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA // KilledBySignal constructor. KilledBySignal::KilledBySignal(int signum) : signum_(signum) { } @@ -195,7 +195,7 @@ namespace internal { static std::string ExitSummary(int exit_code) { Message m; -# if GTEST_OS_WINDOWS +# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA m << "Exited with exit status " << exit_code; @@ -866,10 +866,10 @@ int FuchsiaDeathTest::Wait() { zx_status_t status_zx; zx_signals_t signals; status_zx = zx_object_wait_one( - child_process_, - ZX_PROCESS_TERMINATED, - ZX_TIME_INFINITE, - &signals); + child_process_, + ZX_PROCESS_TERMINATED, + ZX_TIME_INFINITE, + &signals); GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); ReadAndInterpretStatusByte(); diff --git a/googletest/src/gtest-port.cc b/googletest/src/gtest-port.cc index d6320894..ce59586f 100644 --- a/googletest/src/gtest-port.cc +++ b/googletest/src/gtest-port.cc @@ -64,6 +64,7 @@ #endif // GTEST_OS_AIX #if GTEST_OS_FUCHSIA +# include # include #endif @@ -163,7 +164,20 @@ size_t GetThreadCount() { #elif GTEST_OS_FUCHSIA size_t GetThreadCount() { - return static_cast(zx_system_get_num_cpus()); + int dummy_buffer; + size_t avail; + zx_status_t status = zx_object_get_info( + zx_process_self(), + ZX_INFO_PROCESS_THREADS, + &dummy_buffer, + 0, + nullptr, + &avail); + if(status == ZX_OK) { + return avail; + } else { + return 0; + } } #else diff --git a/googletest/test/gtest-death-test_test.cc b/googletest/test/gtest-death-test_test.cc index 21573c77..37261cb6 100644 --- a/googletest/test/gtest-death-test_test.cc +++ b/googletest/test/gtest-death-test_test.cc @@ -200,7 +200,7 @@ int DieInDebugElse12(int* sideeffect) { return 12; } -# if GTEST_OS_WINDOWS +# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA // Tests the ExitedWithCode predicate. TEST(ExitStatusPredicateTest, ExitedWithCode) { @@ -272,7 +272,7 @@ TEST(ExitStatusPredicateTest, KilledBySignal) { EXPECT_FALSE(pred_kill(status_segv)); } -# endif // GTEST_OS_WINDOWS +# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA // Tests that the death test macros expand to code which may or may not // be followed by operator<<, and that in either case the complete text @@ -787,8 +787,9 @@ static void TestExitMacros() { // See http://msdn.microsoft.com/en-us/library/dwwzkt4c(VS.71).aspx. EXPECT_EXIT(raise(SIGABRT), testing::ExitedWithCode(3), "") << "b_ar"; -# else +# elif !GTEST_OS_FUCHSIA + // Fuchsia has no unix signals. EXPECT_EXIT(raise(SIGKILL), testing::KilledBySignal(SIGKILL), "") << "foo"; ASSERT_EXIT(raise(SIGUSR2), testing::KilledBySignal(SIGUSR2), "") << "bar"; diff --git a/googletest/test/gtest-options_test.cc b/googletest/test/gtest-options_test.cc index 25c9f394..10cb1df7 100644 --- a/googletest/test/gtest-options_test.cc +++ b/googletest/test/gtest-options_test.cc @@ -103,6 +103,8 @@ TEST(OutputFileHelpersTest, GetCurrentExecutableName) { _strcmpi("gtest-options-ex_test", exe_str.c_str()) == 0 || _strcmpi("gtest_all_test", exe_str.c_str()) == 0 || _strcmpi("gtest_dll_test", exe_str.c_str()) == 0; +#elif GTEST_OS_FUCHSIA + const bool success = exe_str == "app"; #else // TODO(wan@google.com): remove the hard-coded "lt-" prefix when // Chandler Carruth's libtool replacement is ready. @@ -116,6 +118,8 @@ TEST(OutputFileHelpersTest, GetCurrentExecutableName) { FAIL() << "GetCurrentExecutableName() returns " << exe_str; } +#if !GTEST_OS_FUCHSIA + class XmlOutputChangeDirTest : public Test { protected: virtual void SetUp() { @@ -202,6 +206,8 @@ TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithAbsolutePath) { #endif } +#endif // !GTEST_OS_FUCHSIA + } // namespace } // namespace internal } // namespace testing diff --git a/googletest/test/gtest-port_test.cc b/googletest/test/gtest-port_test.cc index 51956f05..3801e5ee 100644 --- a/googletest/test/gtest-port_test.cc +++ b/googletest/test/gtest-port_test.cc @@ -296,7 +296,7 @@ TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) { EXPECT_EQ("unknown file", FormatCompilerIndependentFileLocation(NULL, -1)); } -#if GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX +#if GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX || GTEST_OS_FUCHSIA void* ThreadFunc(void* data) { internal::Mutex* mutex = static_cast(data); mutex->Lock(); @@ -340,7 +340,7 @@ TEST(GetThreadCountTest, ReturnsCorrectValue) { TEST(GetThreadCountTest, ReturnsZeroWhenUnableToCountThreads) { EXPECT_EQ(0U, GetThreadCount()); } -#endif // GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX +#endif // GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX || GTEST_OS_FUCHSIA TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) { const bool a_false_condition = false; From 8497540f396f91768a5bb825b1b6a408aae2a836 Mon Sep 17 00:00:00 2001 From: Fabrice de Gans-Riberi Date: Thu, 3 May 2018 13:42:31 -0700 Subject: [PATCH 5/9] Fix comments --- googletest/src/gtest-death-test.cc | 10 +++++----- googletest/src/gtest-port.cc | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/googletest/src/gtest-death-test.cc b/googletest/src/gtest-death-test.cc index a02d8100..4da9e1ca 100644 --- a/googletest/src/gtest-death-test.cc +++ b/googletest/src/gtest-death-test.cc @@ -135,8 +135,8 @@ static bool g_in_fast_death_test_child = false; bool InDeathTestChild() { # if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA - // On Windows, death tests are thread-safe regardless of the value of the - // death_test_style flag. + // On Windows and Fuchsia, death tests are thread-safe regardless of the value + // of the death_test_style flag. return !GTEST_FLAG(internal_run_death_test).empty(); # else @@ -164,7 +164,7 @@ bool ExitedWithCode::operator()(int exit_status) const { return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; -# endif // GTEST_OS_WINDOWS +# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA } # if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA @@ -211,7 +211,7 @@ static std::string ExitSummary(int exit_code) { m << " (core dumped)"; } # endif -# endif // GTEST_OS_WINDOWS +# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA return m.GetString(); } @@ -237,7 +237,7 @@ static std::string DeathTestThreadWarning(size_t thread_count) { msg << "detected " << thread_count << " threads."; return msg.GetString(); } -# endif // !GTEST_OS_WINDOWS +# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA // Flag characters for reporting a death test that did not die. static const char kDeathTestLived = 'L'; diff --git a/googletest/src/gtest-port.cc b/googletest/src/gtest-port.cc index ce59586f..fa25fcc5 100644 --- a/googletest/src/gtest-port.cc +++ b/googletest/src/gtest-port.cc @@ -66,7 +66,7 @@ #if GTEST_OS_FUCHSIA # include # include -#endif +#endif // GTEST_OS_FUCHSIA #include "gtest/gtest-spi.h" #include "gtest/gtest-message.h" From 242f0f623cec3001adf653da21ee470b2863518c Mon Sep 17 00:00:00 2001 From: Fabrice de Gans-Riberi Date: Thu, 3 May 2018 13:44:42 -0700 Subject: [PATCH 6/9] Style fix --- googletest/src/gtest-port.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/googletest/src/gtest-port.cc b/googletest/src/gtest-port.cc index fa25fcc5..f8a0ad65 100644 --- a/googletest/src/gtest-port.cc +++ b/googletest/src/gtest-port.cc @@ -173,7 +173,7 @@ size_t GetThreadCount() { 0, nullptr, &avail); - if(status == ZX_OK) { + if (status == ZX_OK) { return avail; } else { return 0; From 960149f913c8c754e4c73da186b8d61c7c78409b Mon Sep 17 00:00:00 2001 From: Fabrice de Gans-Riberi Date: Thu, 3 May 2018 13:57:51 -0700 Subject: [PATCH 7/9] Remove magic number --- googletest/src/gtest-death-test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/googletest/src/gtest-death-test.cc b/googletest/src/gtest-death-test.cc index 4da9e1ca..792fe46a 100644 --- a/googletest/src/gtest-death-test.cc +++ b/googletest/src/gtest-death-test.cc @@ -934,7 +934,7 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() { // Build the pipe for communication with the child. int read_fd; - status = launchpad_add_pipe(lp, &read_fd, 3); + status = launchpad_add_pipe(lp, &read_fd, kFuchsiaReadPipeFd); GTEST_DEATH_TEST_CHECK_(status == ZX_OK); set_read_fd(read_fd); From ec5ad0f8698881ea99b2fcda8c244b876b334afe Mon Sep 17 00:00:00 2001 From: Jae Heon Lee Date: Mon, 7 May 2018 14:09:37 -0700 Subject: [PATCH 8/9] Fix the bug where ad_hoc_test_result() functions of UnitTest and TestCase objects would return failures registered at TestCase and UnitTest scopes, respectively. --- googletest/src/gtest.cc | 12 ++++++++---- googletest/test/gtest_unittest.cc | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc index 73e9bf86..4fcd9b53 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -5340,11 +5340,15 @@ OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { return os_stack_trace_getter_; } -// Returns the TestResult for the test that's currently running, or -// the TestResult for the ad hoc test if no test is running. +// Returns the most specific TestResult currently running. TestResult* UnitTestImpl::current_test_result() { - return current_test_info_ ? - &(current_test_info_->result_) : &ad_hoc_test_result_; + if (current_test_info_ != nullptr) { + return ¤t_test_info_->result_; + } + if (current_test_case_ != nullptr) { + return ¤t_test_case_->ad_hoc_test_result_; + } + return &ad_hoc_test_result_; } // Shuffles all test cases, and the tests within each test case, diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc index 58995a4f..8dc89329 100644 --- a/googletest/test/gtest_unittest.cc +++ b/googletest/test/gtest_unittest.cc @@ -7748,3 +7748,25 @@ TEST(SkipPrefixTest, DoesNotSkipWhenPrefixDoesNotMatch) { EXPECT_FALSE(SkipPrefix("world!", &p)); EXPECT_EQ(str, p); } + +// Tests ad_hoc_test_result(). + +class AdHocTestResultTest : public testing::Test { + protected: + static void SetUpTestCase() { + FAIL() << "A failure happened inside SetUpTestCase()."; + } +}; + +TEST_F(AdHocTestResultTest, AdHocTestResultForTestCaseShowsFailure) { + const testing::TestResult& test_result = testing::UnitTest::GetInstance() + ->current_test_case() + ->ad_hoc_test_result(); + EXPECT_TRUE(test_result.Failed()); +} + +TEST_F(AdHocTestResultTest, AdHocTestResultTestForUnitTestDoesNotShowFailure) { + const testing::TestResult& test_result = + testing::UnitTest::GetInstance()->ad_hoc_test_result(); + EXPECT_FALSE(test_result.Failed()); +} From 18abd8f51281461fe4f29cc0e7c18e9ed0888c9f Mon Sep 17 00:00:00 2001 From: Jae Heon Lee Date: Wed, 9 May 2018 13:03:57 -0700 Subject: [PATCH 9/9] Use NULL instead of nullptr, for pre-C++11 builds. --- googletest/src/gtest.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc index 4fcd9b53..1b2aad24 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -5342,10 +5342,10 @@ OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { // Returns the most specific TestResult currently running. TestResult* UnitTestImpl::current_test_result() { - if (current_test_info_ != nullptr) { + if (current_test_info_ != NULL) { return ¤t_test_info_->result_; } - if (current_test_case_ != nullptr) { + if (current_test_case_ != NULL) { return ¤t_test_case_->ad_hoc_test_result_; } return &ad_hoc_test_result_;