172 lines · cpp
1//===-- HostTest.cpp ------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Host/Host.h"10#include "TestingSupport/SubsystemRAII.h"11#include "lldb/Host/FileSystem.h"12#include "lldb/Host/HostInfo.h"13#include "lldb/Host/Pipe.h"14#include "lldb/Host/ProcessLaunchInfo.h"15#include "lldb/Utility/ProcessInfo.h"16#include "llvm/ADT/ScopeExit.h"17#include "llvm/ADT/Twine.h"18#include "llvm/Support/CommandLine.h"19#include "llvm/Support/FileSystem.h"20#include "llvm/Testing/Support/Error.h"21#include "gtest/gtest.h"22#include <future>23#include <thread>24 25using namespace lldb_private;26using namespace llvm;27 28// From TestMain.cpp.29extern const char *TestMainArgv0;30 31static cl::opt<uint64_t> test_arg("test-arg");32 33TEST(Host, WaitStatusFormat) {34 EXPECT_EQ("W01", formatv("{0:g}", WaitStatus{WaitStatus::Exit, 1}).str());35 EXPECT_EQ("X02", formatv("{0:g}", WaitStatus{WaitStatus::Signal, 2}).str());36 EXPECT_EQ("S03", formatv("{0:g}", WaitStatus{WaitStatus::Stop, 3}).str());37 EXPECT_EQ("Exited with status 4",38 formatv("{0}", WaitStatus{WaitStatus::Exit, 4}).str());39}40 41TEST(Host, GetEnvironment) {42 putenv(const_cast<char *>("LLDB_TEST_ENVIRONMENT_VAR=Host::GetEnvironment"));43 ASSERT_EQ("Host::GetEnvironment",44 Host::GetEnvironment().lookup("LLDB_TEST_ENVIRONMENT_VAR"));45}46 47TEST(Host, ProcessInstanceInfoCumulativeUserTimeIsValid) {48 ProcessInstanceInfo info;49 info.SetCumulativeUserTime(ProcessInstanceInfo::timespec{0, 0});50 EXPECT_FALSE(info.CumulativeUserTimeIsValid());51 info.SetCumulativeUserTime(ProcessInstanceInfo::timespec{0, 1});52 EXPECT_TRUE(info.CumulativeUserTimeIsValid());53 info.SetCumulativeUserTime(ProcessInstanceInfo::timespec{1, 0});54 EXPECT_TRUE(info.CumulativeUserTimeIsValid());55}56 57TEST(Host, ProcessInstanceInfoCumulativeSystemTimeIsValid) {58 ProcessInstanceInfo info;59 info.SetCumulativeSystemTime(ProcessInstanceInfo::timespec{0, 0});60 EXPECT_FALSE(info.CumulativeSystemTimeIsValid());61 info.SetCumulativeSystemTime(ProcessInstanceInfo::timespec{0, 1});62 EXPECT_TRUE(info.CumulativeSystemTimeIsValid());63 info.SetCumulativeSystemTime(ProcessInstanceInfo::timespec{1, 0});64 EXPECT_TRUE(info.CumulativeSystemTimeIsValid());65}66 67TEST(Host, LaunchProcessSetsArgv0) {68 SubsystemRAII<FileSystem> subsystems;69 70 static constexpr StringLiteral TestArgv0 = "HelloArgv0";71 if (test_arg != 0) {72 // In subprocess73 if (TestMainArgv0 != TestArgv0) {74 errs() << formatv("Got '{0}' for argv[0]\n", TestMainArgv0);75 exit(1);76 }77 exit(0);78 }79 80 ProcessLaunchInfo info;81 info.SetExecutableFile(82 FileSpec(llvm::sys::fs::getMainExecutable(TestMainArgv0, &test_arg)),83 /*add_exe_file_as_first_arg=*/false);84 info.GetArguments().AppendArgument("HelloArgv0");85 info.GetArguments().AppendArgument(86 "--gtest_filter=Host.LaunchProcessSetsArgv0");87 info.GetArguments().AppendArgument("--test-arg=47");88 std::promise<int> exit_status;89 info.SetMonitorProcessCallback([&](lldb::pid_t pid, int signal, int status) {90 exit_status.set_value(status);91 });92 ASSERT_THAT_ERROR(Host::LaunchProcess(info).takeError(), Succeeded());93 ASSERT_THAT(exit_status.get_future().get(), 0);94}95 96TEST(Host, FindProcesses) {97 SubsystemRAII<FileSystem, HostInfo> subsystems;98 99 if (test_arg != 0) {100 // Give the parent time to retrieve information about self.101 // It will kill self when it is done.102 std::this_thread::sleep_for(std::chrono::seconds(10));103 exit(0);104 }105 106 bool foundPID = false;107 ProcessLaunchInfo info;108 ProcessInstanceInfoList processes;109 ProcessInstanceInfoMatch match(TestMainArgv0, NameMatch::Equals);110 info.SetExecutableFile(FileSpec(TestMainArgv0),111 /*add_exe_file_as_first_arg=*/true);112 info.GetArguments().AppendArgument("--gtest_filter=Host.FindProcesses");113 info.GetArguments().AppendArgument("--test-arg=48");114 std::promise<int> exit_status;115 info.SetMonitorProcessCallback([&](lldb::pid_t pid, int signal, int status) {116 exit_status.set_value(status);117 });118 ASSERT_THAT_ERROR(Host::LaunchProcess(info).takeError(), Succeeded());119 ASSERT_TRUE(Host::FindProcesses(match, processes));120 for (const auto &process : processes) {121 if (process.GetProcessID() == info.GetProcessID()) {122 ASSERT_EQ(process.GetExecutableFile().GetFilename(),123 info.GetExecutableFile().GetFilename());124 foundPID = true;125 }126 }127 ASSERT_TRUE(foundPID);128 auto clean_up = llvm::make_scope_exit([&] {129 Host::Kill(info.GetProcessID(), SIGKILL);130 exit_status.get_future().get();131 });132}133 134TEST(Host, LaunchProcessDuplicatesHandle) {135 static constexpr llvm::StringLiteral test_msg("Hello subprocess!");136 137 SubsystemRAII<FileSystem> subsystems;138 139 if (test_arg) {140 Pipe pipe(LLDB_INVALID_PIPE, (lldb::pipe_t)test_arg.getValue());141 llvm::Expected<size_t> bytes_written =142 pipe.Write(test_msg.data(), test_msg.size());143 if (bytes_written && *bytes_written == test_msg.size())144 exit(0);145 exit(1);146 }147 Pipe pipe;148 ASSERT_THAT_ERROR(pipe.CreateNew().takeError(), llvm::Succeeded());149 SCOPED_TRACE(llvm::formatv("Pipe handles are: {0}/{1}",150 (uint64_t)pipe.GetReadPipe(),151 (uint64_t)pipe.GetWritePipe())152 .str());153 ProcessLaunchInfo info;154 info.SetExecutableFile(FileSpec(TestMainArgv0),155 /*add_exe_file_as_first_arg=*/true);156 info.GetArguments().AppendArgument(157 "--gtest_filter=Host.LaunchProcessDuplicatesHandle");158 info.GetArguments().AppendArgument(159 ("--test-arg=" + llvm::Twine((uint64_t)pipe.GetWritePipe())).str());160 info.AppendDuplicateFileAction((uint64_t)pipe.GetWritePipe(),161 (uint64_t)pipe.GetWritePipe());162 info.SetMonitorProcessCallback(&ProcessLaunchInfo::NoOpMonitorCallback);163 ASSERT_THAT_ERROR(Host::LaunchProcess(info).takeError(), llvm::Succeeded());164 pipe.CloseWriteFileDescriptor();165 166 char msg[100];167 llvm::Expected<size_t> bytes_read =168 pipe.Read(msg, sizeof(msg), std::chrono::seconds(10));169 ASSERT_THAT_EXPECTED(bytes_read, llvm::Succeeded());170 ASSERT_EQ(llvm::StringRef(msg, *bytes_read), test_msg);171}172