blob: 50702a282144a14816caf97519519dd1a2cc10b7 [file]
// Copyright 2026 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/io.h>
#include <lib/fdio/spawn.h>
#include <lib/zx/process.h>
#include <lib/zx/socket.h>
#include <unistd.h>
#include <zircon/processargs.h>
#include <string>
#include <zxtest/zxtest.h>
namespace {
void RunSpawnTest(const char* path, const char** argv, const std::string& expected) {
int fd;
zx::socket socket;
zx_status_t status = fdio_pipe_half(&fd, socket.reset_and_get_address());
ASSERT_OK(status);
fdio_spawn_action_t action = {
.action = FDIO_SPAWN_ACTION_TRANSFER_FD,
.fd = {.local_fd = fd, .target_fd = STDOUT_FILENO},
};
zx::process process;
char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
int flags = FDIO_SPAWN_CLONE_ALL & ~FDIO_SPAWN_CLONE_STDIO;
status = fdio_spawn_etc(ZX_HANDLE_INVALID, flags, path, argv, nullptr, 1, &action,
process.reset_and_get_address(), err_msg);
ASSERT_OK(status, "fdio_spawn_etc failed: %s", err_msg);
status = process.wait_one(ZX_PROCESS_TERMINATED, zx::time::infinite(), nullptr);
ASSERT_OK(status);
zx_info_process_t info;
status = process.get_info(ZX_INFO_PROCESS, &info, sizeof(info), nullptr, nullptr);
ASSERT_OK(status);
ASSERT_EQ(info.return_code, 0);
std::string output;
char buf[1024];
while (true) {
size_t actual;
status = socket.read(0, buf, sizeof(buf), &actual);
if (status == ZX_OK) {
output.append(buf, actual);
} else if (status == ZX_ERR_PEER_CLOSED) {
break;
} else {
ASSERT_OK(status);
}
}
ASSERT_EQ(output, expected);
}
TEST(FdioSpawnTest, ShebangAbsoluteArgv0) {
const char* path = "/pkg/bin/shebang_test_script";
const char* argv[] = {path, "arg1", "arg2", nullptr};
std::string expected =
"/pkg/bin/echo-args\n"
"/pkg/bin/shebang_test_script\n"
"arg1\n"
"arg2\n";
RunSpawnTest(path, argv, expected);
}
TEST(FdioSpawnTest, ShebangRelativeArgv0) {
const char* path = "/pkg/bin/shebang_test_script";
const char* argv[] = {"shebang_test_script", "arg1", "arg2", nullptr};
std::string expected =
"/pkg/bin/echo-args\n"
"/pkg/bin/shebang_test_script\n"
"arg1\n"
"arg2\n";
RunSpawnTest(path, argv, expected);
}
} // namespace