#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "base/test/launcher/test_launcher.h"
#include <stdio.h>
#include <algorithm>
#include <map>
#include <random>
#include <string_view>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include "base/at_exit.h"
#include "base/clang_profiling_buildflags.h"
#include "base/command_line.h"
#include "base/containers/adapters.h"
#include "base/containers/contains.h"
#include "base/environment.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/format_macros.h"
#include "base/functional/bind.h"
#include "base/hash/hash.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/numerics/safe_conversions.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/strings/pattern.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringize_macros.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
#include "base/task/post_job.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/test/gtest_util.h"
#include "base/test/gtest_xml_util.h"
#include "base/test/launcher/test_launcher_tracer.h"
#include "base/test/launcher/test_results_tracker.h"
#include "base/test/scoped_logging_settings.h"
#include "base/test/test_file_util.h"
#include "base/test/test_switches.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_POSIX)
#include <fcntl.h>
#include "base/files/file_descriptor_watcher_posix.h"
#endif
#if BUILDFLAG(IS_APPLE)
#include "base/apple/scoped_nsautorelease_pool.h"
#endif
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#include "base/strings/string_util_win.h"
#undef GetCommandLine
#endif
#if BUILDFLAG(IS_FUCHSIA)
#include <lib/fdio/namespace.h>
#include <lib/zx/job.h>
#include <lib/zx/time.h>
#include "base/atomic_sequence_num.h"
#include "base/fuchsia/default_job.h"
#include "base/fuchsia/file_utils.h"
#include "base/fuchsia/fuchsia_logging.h"
#endif
#if BUILDFLAG(IS_IOS)
#include "base/path_service.h"
#endif
namespace base {
operator<<;
const char kTestTotalShards[] = …;
const char kTestShardIndex[] = …;
const char kPreTestPrefix[] = …;
const char kDisabledTestPrefix[] = …;
ResultWatcher::ResultWatcher(FilePath result_file, size_t num_tests)
: … { … }
bool ResultWatcher::PollUntilDone(TimeDelta timeout_per_test) { … }
TimeDelta ResultWatcher::PollOnce(TimeDelta timeout_per_test) { … }
Time ResultWatcher::LatestCompletionTimestamp(
const std::vector<TestResult>& test_results) { … }
class ProcessResultWatcher : public ResultWatcher { … };
int ProcessResultWatcher::GetExitCode() { … }
bool ProcessResultWatcher::WaitWithTimeout(TimeDelta timeout) { … }
namespace {
const char kUnreliableResultsTag[] = …;
constexpr TimeDelta kOutputTimeout = …;
const size_t kOutputSnippetLinesLimit = …;
const size_t kOutputSnippetBytesLimit = …;
const uint32_t kRandomSeedUpperBound = …;
Lock* GetLiveProcessesLock() { … }
std::map<ProcessHandle, CommandLine>* GetLiveProcesses() { … }
TestLauncherTracer* GetTestLauncherTracer() { … }
#if BUILDFLAG(IS_FUCHSIA)
zx_status_t WaitForJobExit(const zx::job& job) {
zx::time deadline =
zx::deadline_after(zx::duration(kOutputTimeout.ToZxDuration()));
zx_signals_t to_wait_for = ZX_JOB_NO_JOBS | ZX_JOB_NO_PROCESSES;
while (to_wait_for) {
zx_signals_t observed = 0;
zx_status_t status = job.wait_one(to_wait_for, deadline, &observed);
if (status != ZX_OK)
return status;
to_wait_for &= ~observed;
}
return ZX_OK;
}
#endif
#if BUILDFLAG(IS_POSIX)
int g_shutdown_pipe[2] = …;
void ShutdownPipeSignalHandler(int signal) { … }
void KillSpawnedTestProcesses() { … }
#endif
bool TakeInt32FromEnvironment(const char* const var, int32_t* result) { … }
bool UnsetEnvironmentVariableIfExists(const std::string& name) { … }
bool BotModeEnabled(const CommandLine* command_line) { … }
CommandLine PrepareCommandLineForGTest(const CommandLine& command_line,
const std::string& wrapper,
const size_t retries_left) { … }
int LaunchChildTestProcessWithOptions(const CommandLine& command_line,
const LaunchOptions& options,
int flags,
const FilePath& result_file,
TimeDelta timeout_per_test,
size_t num_tests,
TestLauncherDelegate* delegate,
bool* was_timeout) { … }
struct ChildProcessResults { … };
FilePath CreateChildTempDirIfSupported(const FilePath& task_temp_dir,
int child_index) { … }
void SetTemporaryDirectory(const FilePath& temp_dir,
EnvironmentMap* environment) { … }
ChildProcessResults DoLaunchChildTestProcess(
const CommandLine& command_line,
const FilePath& process_temp_dir,
const FilePath& result_file,
TimeDelta timeout_per_test,
size_t num_tests,
const TestLauncher::LaunchOptions& test_launch_options,
bool redirect_stdio,
TestLauncherDelegate* delegate) { … }
std::vector<std::string> ExtractTestsFromFilter(const std::string& filter,
bool double_colon_supported) { … }
class TestRunner { … };
void TestRunner::Run(const std::vector<std::string>& test_names) { … }
void TestRunner::WorkerTask(scoped_refptr<TaskRunner> main_task_runner,
base::JobDelegate* delegate) { … }
void TestRunner::CleanupTask(base::ScopedTempDir task_temp_dir, bool done) { … }
int CountItemsInDirectory(const FilePath& dir) { … }
std::string TruncateSnippet(const std::string_view snippet, size_t byte_limit) { … }
}
const char kGTestBreakOnFailure[] = …;
const char kGTestFilterFlag[] = …;
const char kGTestFlagfileFlag[] = …;
const char kGTestHelpFlag[] = …;
const char kGTestListTestsFlag[] = …;
const char kGTestRepeatFlag[] = …;
const char kGTestRunDisabledTestsFlag[] = …;
const char kGTestOutputFlag[] = …;
const char kGTestShuffleFlag[] = …;
const char kGTestRandomSeedFlag[] = …;
const char kIsolatedScriptRunDisabledTestsFlag[] = …;
const char kIsolatedScriptTestFilterFlag[] = …;
const char kIsolatedScriptTestRepeatFlag[] = …;
class TestLauncher::TestInfo { … };
TestLauncher::TestInfo::TestInfo(const TestIdentifier& test_id)
: … { … }
std::string TestLauncher::TestInfo::GetDisabledStrippedName() const { … }
std::string TestLauncher::TestInfo::GetFullName() const { … }
std::string TestLauncher::TestInfo::GetPreName() const { … }
std::string TestLauncher::TestInfo::GetPrefixStrippedName() const { … }
TestLauncherDelegate::~TestLauncherDelegate() = default;
bool TestLauncherDelegate::ShouldRunTest(const TestIdentifier& test) { … }
TestLauncher::LaunchOptions::LaunchOptions() = default;
TestLauncher::LaunchOptions::LaunchOptions(const LaunchOptions& other) =
default;
TestLauncher::LaunchOptions::~LaunchOptions() = default;
TestLauncher::TestLauncher(TestLauncherDelegate* launcher_delegate,
size_t parallel_jobs,
size_t retry_limit)
: … { … }
TestLauncher::~TestLauncher() { … }
bool TestLauncher::Run(CommandLine* command_line) { … }
void TestLauncher::LaunchChildGTestProcess(
scoped_refptr<TaskRunner> task_runner,
const std::vector<std::string>& test_names,
const FilePath& task_temp_dir,
const FilePath& child_temp_dir) { … }
TestResult::Status MissingResultStatus(size_t tests_to_run_count,
bool was_timeout,
bool exit_code) { … }
void TestLauncher::ProcessTestResults(
const std::vector<std::string>& test_names,
const FilePath& result_file,
const std::string& output,
TimeDelta elapsed_time,
int exit_code,
bool was_timeout,
PlatformThreadId thread_id,
int process_num,
int leaked_items) { … }
void TestLauncher::OnTestFinished(const TestResult& original_result) { … }
bool LoadFilterFile(const FilePath& file_path,
std::vector<std::string>* positive_filter,
std::vector<std::string>* negative_filter) { … }
bool TestLauncher::IsOnlyExactPositiveFilterFromFile(
const CommandLine* command_line) const { … }
bool TestLauncher::Init(CommandLine* command_line) { … }
bool TestLauncher::InitTests() { … }
bool TestLauncher::ShuffleTests(CommandLine* command_line) { … }
bool TestLauncher::ProcessAndValidateTests() { … }
void TestLauncher::CreateAndStartThreadPool(size_t num_parallel_jobs) { … }
void TestLauncher::CombinePositiveTestFilters(
std::vector<std::string> filter_a,
std::vector<std::string> filter_b) { … }
bool TestLauncher::ShouldRunInCurrentShard(
std::string_view prefix_stripped_name) const { … }
std::vector<std::string> TestLauncher::CollectTests() { … }
void TestLauncher::RunTests() { … }
void TestLauncher::PrintFuzzyMatchingTestNames() { … }
bool TestLauncher::RunRetryTests() { … }
void TestLauncher::OnTestIterationStart() { … }
#if BUILDFLAG(IS_POSIX)
void TestLauncher::OnShutdownPipeReadable() { … }
#endif
void TestLauncher::MaybeSaveSummaryAsJSON(
const std::vector<std::string>& additional_tags) { … }
void TestLauncher::OnTestIterationFinished() { … }
void TestLauncher::OnOutputTimeout() { … }
size_t NumParallelJobs(unsigned int cores_per_job) { … }
std::string GetTestOutputSnippet(const TestResult& result,
const std::string& full_output) { … }
std::string TruncateSnippetFocused(const std::string_view snippet,
size_t byte_limit) { … }
}