Merge branch 'master' of https://github.com/google/googletest
This commit is contained in:
		
						commit
						1b8945fbac
					
				@ -64,6 +64,10 @@
 | 
			
		||||
# if GTEST_OS_FUCHSIA
 | 
			
		||||
#  include <lib/fdio/io.h>
 | 
			
		||||
#  include <lib/fdio/spawn.h>
 | 
			
		||||
#  include <lib/fdio/util.h>
 | 
			
		||||
#  include <lib/zx/socket.h>
 | 
			
		||||
#  include <lib/zx/port.h>
 | 
			
		||||
#  include <lib/zx/process.h>
 | 
			
		||||
#  include <zircon/processargs.h>
 | 
			
		||||
#  include <zircon/syscalls.h>
 | 
			
		||||
#  include <zircon/syscalls/port.h>
 | 
			
		||||
@ -422,6 +426,9 @@ class DeathTestImpl : public DeathTest {
 | 
			
		||||
  // case of unexpected codes.
 | 
			
		||||
  void ReadAndInterpretStatusByte();
 | 
			
		||||
 | 
			
		||||
  // Returns stderr output from the child process.
 | 
			
		||||
  virtual std::string GetErrorLogs();
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  // The textual content of the code this object is testing.  This class
 | 
			
		||||
  // doesn't own this string and should not attempt to delete it.
 | 
			
		||||
@ -490,6 +497,10 @@ void DeathTestImpl::ReadAndInterpretStatusByte() {
 | 
			
		||||
  set_read_fd(-1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string DeathTestImpl::GetErrorLogs() {
 | 
			
		||||
  return GetCapturedStderr();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Signals that the death test code which should have exited, didn't.
 | 
			
		||||
// Should be called only in a death test child process.
 | 
			
		||||
// Writes a status byte to the child's status file descriptor, then
 | 
			
		||||
@ -558,7 +569,7 @@ bool DeathTestImpl::Passed(bool status_ok) {
 | 
			
		||||
  if (!spawned())
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
  const std::string error_message = GetCapturedStderr();
 | 
			
		||||
  const std::string error_message = GetErrorLogs();
 | 
			
		||||
 | 
			
		||||
  bool success = false;
 | 
			
		||||
  Message buffer;
 | 
			
		||||
@ -810,12 +821,6 @@ class FuchsiaDeathTest : public DeathTestImpl {
 | 
			
		||||
                   const char* file,
 | 
			
		||||
                   int line)
 | 
			
		||||
      : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
 | 
			
		||||
  virtual ~FuchsiaDeathTest() {
 | 
			
		||||
    zx_status_t status = zx_handle_close(child_process_);
 | 
			
		||||
    GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
 | 
			
		||||
    status = zx_handle_close(port_);
 | 
			
		||||
    GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // All of these virtual functions are inherited from DeathTest.
 | 
			
		||||
  virtual int Wait();
 | 
			
		||||
@ -826,9 +831,12 @@ class FuchsiaDeathTest : public DeathTestImpl {
 | 
			
		||||
  const char* const file_;
 | 
			
		||||
  // The line number on which the death test is located.
 | 
			
		||||
  const int line_;
 | 
			
		||||
  // The stderr data captured by the child process.
 | 
			
		||||
  std::string captured_stderr_;
 | 
			
		||||
 | 
			
		||||
  zx_handle_t child_process_ = ZX_HANDLE_INVALID;
 | 
			
		||||
  zx_handle_t port_ = ZX_HANDLE_INVALID;
 | 
			
		||||
  zx::process child_process_;
 | 
			
		||||
  zx::port port_;
 | 
			
		||||
  zx::socket stderr_socket_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Utility class for accumulating command-line arguments.
 | 
			
		||||
@ -872,51 +880,74 @@ class Arguments {
 | 
			
		||||
// status, or 0 if no child process exists.  As a side effect, sets the
 | 
			
		||||
// outcome data member.
 | 
			
		||||
int FuchsiaDeathTest::Wait() {
 | 
			
		||||
  const int kProcessKey = 0;
 | 
			
		||||
  const int kSocketKey = 1;
 | 
			
		||||
 | 
			
		||||
  if (!spawned())
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
  // Register to wait for the child process to terminate.
 | 
			
		||||
  zx_status_t status_zx;
 | 
			
		||||
  status_zx = zx_object_wait_async(child_process_,
 | 
			
		||||
                                   port_,
 | 
			
		||||
                                   0 /* key */,
 | 
			
		||||
                                   ZX_PROCESS_TERMINATED,
 | 
			
		||||
                                   ZX_WAIT_ASYNC_ONCE);
 | 
			
		||||
  status_zx = child_process_.wait_async(
 | 
			
		||||
      port_, kProcessKey, ZX_PROCESS_TERMINATED, ZX_WAIT_ASYNC_ONCE);
 | 
			
		||||
  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
 | 
			
		||||
  // Register to wait for the socket to be readable or closed.
 | 
			
		||||
  status_zx = stderr_socket_.wait_async(
 | 
			
		||||
      port_, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
 | 
			
		||||
      ZX_WAIT_ASYNC_REPEATING);
 | 
			
		||||
  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
 | 
			
		||||
 | 
			
		||||
  // Wait for it to terminate, or an exception to be received.
 | 
			
		||||
  zx_port_packet_t packet;
 | 
			
		||||
  status_zx = zx_port_wait(port_, ZX_TIME_INFINITE, &packet);
 | 
			
		||||
  bool process_terminated = false;
 | 
			
		||||
  bool socket_closed = false;
 | 
			
		||||
  do {
 | 
			
		||||
    zx_port_packet_t packet = {};
 | 
			
		||||
    status_zx = port_.wait(zx::time::infinite(), &packet);
 | 
			
		||||
    GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
 | 
			
		||||
 | 
			
		||||
    if (packet.key == kProcessKey) {
 | 
			
		||||
      if (ZX_PKT_IS_EXCEPTION(packet.type)) {
 | 
			
		||||
    // Process encountered an exception. Kill it directly rather than letting
 | 
			
		||||
    // other handlers process the event.
 | 
			
		||||
    status_zx = zx_task_kill(child_process_);
 | 
			
		||||
        // Process encountered an exception. Kill it directly rather than
 | 
			
		||||
        // letting other handlers process the event. We will get a second
 | 
			
		||||
        // kProcessKey event when the process actually terminates.
 | 
			
		||||
        status_zx = child_process_.kill();
 | 
			
		||||
        GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
 | 
			
		||||
 | 
			
		||||
    // Now wait for |child_process_| to terminate.
 | 
			
		||||
    zx_signals_t signals = 0;
 | 
			
		||||
    status_zx = zx_object_wait_one(
 | 
			
		||||
        child_process_, ZX_PROCESS_TERMINATED, ZX_TIME_INFINITE, &signals);
 | 
			
		||||
    GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
 | 
			
		||||
    GTEST_DEATH_TEST_CHECK_(signals & ZX_PROCESS_TERMINATED);
 | 
			
		||||
      } else {
 | 
			
		||||
        // Process terminated.
 | 
			
		||||
        GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
 | 
			
		||||
        GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED);
 | 
			
		||||
        process_terminated = true;
 | 
			
		||||
      }
 | 
			
		||||
    } else if (packet.key == kSocketKey) {
 | 
			
		||||
      GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_REP(packet.type));
 | 
			
		||||
      if (packet.signal.observed & ZX_SOCKET_READABLE) {
 | 
			
		||||
        // Read data from the socket.
 | 
			
		||||
        constexpr size_t kBufferSize = 1024;
 | 
			
		||||
        do {
 | 
			
		||||
          size_t old_length = captured_stderr_.length();
 | 
			
		||||
          size_t bytes_read = 0;
 | 
			
		||||
          captured_stderr_.resize(old_length + kBufferSize);
 | 
			
		||||
          status_zx = stderr_socket_.read(
 | 
			
		||||
              0, &captured_stderr_.front() + old_length, kBufferSize,
 | 
			
		||||
              &bytes_read);
 | 
			
		||||
          captured_stderr_.resize(old_length + bytes_read);
 | 
			
		||||
        } while (status_zx == ZX_OK);
 | 
			
		||||
        if (status_zx == ZX_ERR_PEER_CLOSED) {
 | 
			
		||||
          socket_closed = true;
 | 
			
		||||
        } else {
 | 
			
		||||
          GTEST_DEATH_TEST_CHECK_(status_zx == ZX_ERR_SHOULD_WAIT);
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_SOCKET_PEER_CLOSED);
 | 
			
		||||
        socket_closed = true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  } while (!process_terminated && !socket_closed);
 | 
			
		||||
 | 
			
		||||
  ReadAndInterpretStatusByte();
 | 
			
		||||
 | 
			
		||||
  zx_info_process_t buffer;
 | 
			
		||||
  status_zx = zx_object_get_info(
 | 
			
		||||
      child_process_,
 | 
			
		||||
      ZX_INFO_PROCESS,
 | 
			
		||||
      &buffer,
 | 
			
		||||
      sizeof(buffer),
 | 
			
		||||
      nullptr,
 | 
			
		||||
      nullptr);
 | 
			
		||||
  status_zx = child_process_.get_info(
 | 
			
		||||
      ZX_INFO_PROCESS, &buffer, sizeof(buffer), nullptr, nullptr);
 | 
			
		||||
  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
 | 
			
		||||
 | 
			
		||||
  GTEST_DEATH_TEST_CHECK_(buffer.exited);
 | 
			
		||||
@ -943,7 +974,6 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
 | 
			
		||||
    return EXECUTE_TEST;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  CaptureStderr();
 | 
			
		||||
  // Flush the log buffers since the log streams are shared with the child.
 | 
			
		||||
  FlushInfoLog();
 | 
			
		||||
 | 
			
		||||
@ -970,29 +1000,55 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
 | 
			
		||||
  set_read_fd(status);
 | 
			
		||||
 | 
			
		||||
  // Set the pipe handle for the child.
 | 
			
		||||
  fdio_spawn_action_t add_handle_action = {};
 | 
			
		||||
  add_handle_action.action = FDIO_SPAWN_ACTION_ADD_HANDLE;
 | 
			
		||||
  add_handle_action.h.id = PA_HND(type, kFuchsiaReadPipeFd);
 | 
			
		||||
  add_handle_action.h.handle = child_pipe_handle;
 | 
			
		||||
  fdio_spawn_action_t spawn_actions[2] = {};
 | 
			
		||||
  fdio_spawn_action_t* add_handle_action = &spawn_actions[0];
 | 
			
		||||
  add_handle_action->action = FDIO_SPAWN_ACTION_ADD_HANDLE;
 | 
			
		||||
  add_handle_action->h.id = PA_HND(type, kFuchsiaReadPipeFd);
 | 
			
		||||
  add_handle_action->h.handle = child_pipe_handle;
 | 
			
		||||
 | 
			
		||||
  // Create a socket pair will be used to receive the child process' stderr.
 | 
			
		||||
  zx::socket stderr_producer_socket;
 | 
			
		||||
  status =
 | 
			
		||||
      zx::socket::create(0, &stderr_producer_socket, &stderr_socket_);
 | 
			
		||||
  GTEST_DEATH_TEST_CHECK_(status >= 0);
 | 
			
		||||
  int stderr_producer_fd = -1;
 | 
			
		||||
  zx_handle_t producer_handle[1] = { stderr_producer_socket.release() };
 | 
			
		||||
  uint32_t producer_handle_type[1] = { PA_FDIO_SOCKET };
 | 
			
		||||
  status = fdio_create_fd(
 | 
			
		||||
      producer_handle, producer_handle_type, 1, &stderr_producer_fd);
 | 
			
		||||
  GTEST_DEATH_TEST_CHECK_(status >= 0);
 | 
			
		||||
 | 
			
		||||
  // Make the stderr socket nonblocking.
 | 
			
		||||
  GTEST_DEATH_TEST_CHECK_(fcntl(stderr_producer_fd, F_SETFL, 0) == 0);
 | 
			
		||||
 | 
			
		||||
  fdio_spawn_action_t* add_stderr_action = &spawn_actions[1];
 | 
			
		||||
  add_stderr_action->action = FDIO_SPAWN_ACTION_CLONE_FD;
 | 
			
		||||
  add_stderr_action->fd.local_fd = stderr_producer_fd;
 | 
			
		||||
  add_stderr_action->fd.target_fd = STDERR_FILENO;
 | 
			
		||||
 | 
			
		||||
  // Spawn the child process.
 | 
			
		||||
  status = fdio_spawn_etc(ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL,
 | 
			
		||||
                          args.Argv()[0], args.Argv(), nullptr, 1,
 | 
			
		||||
                          &add_handle_action, &child_process_, nullptr);
 | 
			
		||||
  status = fdio_spawn_etc(
 | 
			
		||||
      ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL, args.Argv()[0], args.Argv(),
 | 
			
		||||
      nullptr, 2, spawn_actions, child_process_.reset_and_get_address(),
 | 
			
		||||
      nullptr);
 | 
			
		||||
  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
 | 
			
		||||
 | 
			
		||||
  // Create an exception port and attach it to the |child_process_|, to allow
 | 
			
		||||
  // us to suppress the system default exception handler from firing.
 | 
			
		||||
  status = zx_port_create(0, &port_);
 | 
			
		||||
  status = zx::port::create(0, &port_);
 | 
			
		||||
  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
 | 
			
		||||
  status = zx_task_bind_exception_port(
 | 
			
		||||
      child_process_, port_, 0 /* key */, 0 /*options */);
 | 
			
		||||
  status = child_process_.bind_exception_port(
 | 
			
		||||
      port_, 0 /* key */, 0 /*options */);
 | 
			
		||||
  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
 | 
			
		||||
 | 
			
		||||
  set_spawned(true);
 | 
			
		||||
  return OVERSEE_TEST;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string FuchsiaDeathTest::GetErrorLogs() {
 | 
			
		||||
  return captured_stderr_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else  // We are neither on Windows, nor on Fuchsia.
 | 
			
		||||
 | 
			
		||||
// ForkingDeathTest provides implementations for most of the abstract
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user