blob: ea73089e06572c6d3e16d39f07d091e01aaeef07 [file] [log] [blame]
// Copyright 2018 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 <stdlib.h>
#include <zircon/process.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <gtest/gtest.h>
#include "src/lib/files/file.h"
static constexpr char kRunPath[] = "/bin/run";
static constexpr char kExiter[] =
"fuchsia-pkg://fuchsia.com/run_test_exiter#meta/run_test_exiter.cmx";
static constexpr char kExiterV2Ext[] =
"fuchsia-pkg://fuchsia.com/run_test_exiter#meta/run_test_exiter.cm";
static constexpr char kExiterNoExt[] =
"fuchsia-pkg://fuchsia.com/run_test_exiter#meta/run_test_exiter";
static constexpr char kExiterShort[] = "run_test_exiter.cmx";
static constexpr char kStdout[] =
"Found fuchsia-pkg://fuchsia.com/run_test_exiter#meta/run_test_exiter.cmx, "
"executing.\n";
void test_case(const char* url, const char* value, bool daemonize) {
std::FILE* outf = std::tmpfile();
int out_fd = fileno(outf);
fdio_spawn_action_t actions[] = {
{.action = FDIO_SPAWN_ACTION_CLONE_FD,
.fd = {.local_fd = STDIN_FILENO, .target_fd = STDIN_FILENO}},
{.action = FDIO_SPAWN_ACTION_CLONE_FD,
.fd = {.local_fd = dup(out_fd), .target_fd = STDOUT_FILENO}},
{.action = FDIO_SPAWN_ACTION_CLONE_FD,
.fd = {.local_fd = STDERR_FILENO, .target_fd = STDERR_FILENO}},
};
// Spawn "run run_test_exiter <value>"
uint32_t flags = FDIO_SPAWN_CLONE_ALL;
const char** argv;
if (daemonize) {
argv = new const char* [] { kRunPath, "-d", url, value, NULL };
} else {
argv = new const char* [] { kRunPath, url, value, NULL };
}
zx_handle_t process = ZX_HANDLE_INVALID;
zx_status_t status =
fdio_spawn_etc(ZX_HANDLE_INVALID, flags, kRunPath, argv, NULL, 2, actions, &process, nullptr);
ASSERT_EQ(ZX_OK, status);
// Wait for `run` to terminate
status = zx_object_wait_one(process, ZX_TASK_TERMINATED, ZX_TIME_INFINITE, NULL);
ASSERT_EQ(ZX_OK, status);
std::string output;
ASSERT_TRUE(files::ReadFileDescriptorToString(out_fd, &output));
if (url == kExiterShort) {
ASSERT_EQ(kStdout, output);
}
// Verify `run` return code
zx_info_process_t proc_info;
status = zx_object_get_info(process, ZX_INFO_PROCESS, &proc_info, sizeof(proc_info), NULL, NULL);
ASSERT_EQ(ZX_OK, status);
if (daemonize) {
// If we run daemonize, the return code for run is going to be 0.
ASSERT_EQ(ZX_OK, proc_info.return_code);
} else {
ASSERT_EQ(strtoll(value, NULL, 0), proc_info.return_code);
}
}
TEST(RunReturnValueTest, Zero) { test_case(kExiter, "0", false); }
TEST(RunReturnValueTest, OneTwoThree) { test_case(kExiter, "123", false); }
TEST(RunReturnValueTest, Negative) { test_case(kExiter, "-99999", false); }
TEST(RunReturnValueTest, LongValue) { test_case(kExiter, "1152921504606846976", false); }
TEST(RunReturnValueTest, FuzzySearchZero) { test_case(kExiterShort, "0", false); }
TEST(RunReturnValueTest, FuzzySearchOneTwoThree) { test_case(kExiterShort, "123", false); }
TEST(RunReturnValueTest, FuzzySearchNegative) { test_case(kExiterShort, "-99999", false); }
TEST(RunReturnValueTest, FuzzySearchLongValue) {
test_case(kExiterShort, "1152921504606846976", false);
}
TEST(RunReturnValueTest, ZeroD) { test_case(kExiter, "0", true); }
TEST(RunReturnValueTest, FuzzySearchZeroD) { test_case(kExiterShort, "0", true); }
TEST(RunReturnValueTest, V2Ext) { test_case(kExiterV2Ext, "1", false); }
TEST(RunReturnValueTest, NoExt) { test_case(kExiterNoExt, "1", false); }