| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <lib/fdio/spawn.h> |
| #include <src/lib/fxl/arraysize.h> |
| #include <src/lib/fxl/logging.h> |
| #include <zircon/processargs.h> |
| |
| #include "test_helper.h" |
| #include "test_helper_fixture.h" |
| #include "util.h" |
| |
| namespace debugger_utils { |
| |
| const char* const TestWithHelper::kWaitPeerClosedArgv[] = { |
| kTestHelperPath, |
| "wait-peer-closed", |
| nullptr, |
| }; |
| |
| void TestWithHelper::SetUp() { |
| } |
| |
| void TestWithHelper::TearDown() { |
| // Closing the channel should cause the helper to terminate, if it |
| // hasn't already. |
| channel_.reset(); |
| |
| zx_signals_t pending; |
| zx_status_t status = |
| process_.wait_one(ZX_PROCESS_TERMINATED, zx::time::infinite(), &pending); |
| ASSERT_EQ(status, ZX_OK); |
| } |
| |
| zx_status_t TestWithHelper::RunHelperProgram(const zx::job& job, |
| const char* const argv[]) { |
| zx::channel our_channel, their_channel; |
| zx_status_t status = zx::channel::create(0, &our_channel, &their_channel); |
| if (status != ZX_OK) { |
| FXL_LOG(ERROR) << "zx::channel::create failed: " << ZxErrorString(status); |
| return status; |
| } |
| fdio_spawn_action actions[1]; |
| actions[0].action = FDIO_SPAWN_ACTION_ADD_HANDLE; |
| actions[0].h.id = PA_HND(PA_USER0, 0); |
| actions[0].h.handle = their_channel.release(); |
| uint32_t flags = FDIO_SPAWN_CLONE_ALL; |
| char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH]; |
| |
| zx::process process; |
| status = fdio_spawn_etc(job.get(), flags, kTestHelperPath, argv, nullptr, |
| arraysize(actions), actions, |
| process.reset_and_get_address(), err_msg); |
| if (status != ZX_OK) { |
| FXL_LOG(ERROR) << "fdio_spawn_etc failed: " << ZxErrorString(status) |
| << ", " << err_msg; |
| return status; |
| } |
| |
| process_ = std::move(process); |
| channel_ = std::move(our_channel); |
| return status; |
| } |
| |
| zx_status_t TestWithHelper::GetHelperThread(zx::thread* out_thread) { |
| zx_signals_t pending; |
| zx_status_t status = |
| channel_.wait_one(ZX_CHANNEL_READABLE, zx::time::infinite(), &pending); |
| if (status != ZX_OK) { |
| FXL_LOG(ERROR) << "channel->wait_one failed: " << ZxErrorString(status); |
| return status; |
| } |
| |
| uint32_t actual_bytes, actual_handles; |
| status = channel_.rea2(0u, nullptr, out_thread->reset_and_get_address(), |
| 0u, 1u, &actual_bytes, &actual_handles); |
| if (status != ZX_OK) { |
| FXL_LOG(ERROR) << "channel->read failed: " << ZxErrorString(status); |
| return status; |
| } |
| EXPECT_EQ(actual_bytes, 0u); |
| EXPECT_EQ(actual_handles, 1u); |
| |
| // At this point the inferior is generally waiting for us to close the |
| // channel. |
| return ZX_OK; |
| } |
| |
| } // namespace debugger_utils |