blob: 62ad9ecefb23a42aac4baa18e6ae6af705ae91fb [file] [edit]
// Copyright 2022 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 "src/sys/fuzzing/common/testing/integration-test-base.h"
#include <lib/fdio/spawn.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
namespace fuzzing {
ZxResult<> IntegrationTestBase::Start(const std::string& path, zx::channel registrar) {
const char* argv[2] = {path.c_str(), nullptr};
fdio_spawn_action_t actions[] = {
{
.action = FDIO_SPAWN_ACTION_ADD_HANDLE,
.h =
{
.id = PA_HND(PA_USER0, 0),
.handle = registrar.release(),
},
},
};
char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
auto status = fdio_spawn_etc(ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL, argv[0], argv, nullptr,
sizeof(actions) / sizeof(actions[0]), actions,
process_.reset_and_get_address(), err_msg);
EXPECT_EQ(status, ZX_OK) << err_msg;
return AsZxResult(status);
}
ZxPromise<> IntegrationTestBase::AwaitTermination() {
return fpromise::make_promise([this, terminated = ZxFuture<zx_packet_signal_t>()](
Context& context) mutable -> ZxResult<> {
auto status = process_.wait_one(ZX_PROCESS_TERMINATED, zx::time::infinite_past(), nullptr);
if (status == ZX_OK) {
return fpromise::ok();
}
if (status != ZX_ERR_TIMED_OUT) {
FX_LOGS(WARNING) << "failed to check if process terminated: " << zx_status_get_string(status);
return fpromise::error(status);
}
if (!terminated) {
terminated = executor()->MakePromiseWaitHandle(zx::unowned_handle(process_.get()),
ZX_PROCESS_TERMINATED);
}
if (!terminated(context)) {
return fpromise::pending();
}
if (terminated.is_error()) {
FX_LOGS(WARNING) << "failed to wait for process to terminate: "
<< zx_status_get_string(status);
return fpromise::error(terminated.error());
}
zx_info_process_t info;
status = process_.get_info(ZX_INFO_PROCESS, &info, sizeof(info), nullptr, nullptr);
if (status != ZX_OK) {
FX_LOGS(WARNING) << "failed to get info from terminated process: "
<< zx_status_get_string(status);
return fpromise::error(status);
}
EXPECT_EQ(info.return_code, 0);
process_.reset();
return fpromise::ok();
});
}
void IntegrationTestBase::TearDown() {
process_.kill();
AsyncTest::TearDown();
}
} // namespace fuzzing