1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
10 #include "base/command_line.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/path_service.h"
15 #include "base/process/launch.h"
16 #include "base/strings/string_piece.h"
17 #include "base/strings/string_tokenizer.h"
18 #include "base/strings/string_util.h"
19 #include "base/sys_info.h"
20 #include "base/test/launcher/test_launcher.h"
21 #include "base/test/launcher/unit_test_launcher.h"
22 #include "base/test/test_switches.h"
23 #include "base/test/test_timeouts.h"
29 const char kHelpFlag
[] = "help";
33 "Runs tests using the gtest framework, each batch of tests being\n"
34 "run in their own process. Supported command-line flags:\n"
37 " --gtest_filter=...\n"
38 " Runs a subset of tests (see --gtest_help for more info).\n"
41 " Shows this message.\n"
44 " --test-launcher-retry-limit=N\n"
45 " Sets the limit of test retries on failures to N.\n"
47 " --test-launcher-summary-output=PATH\n"
48 " Saves a JSON machine-readable summary of the run.\n"
50 " --test-launcher-print-test-stdio=auto|always|never\n"
51 " Controls when full test output is printed.\n"
52 " auto means to print it when the test failed.\n"
54 " --test-launcher-total-shards=N\n"
55 " Sets the total number of shards to N.\n"
57 " --test-launcher-shard-index=N\n"
58 " Sets the shard index to run to N (from 0 to TOTAL - 1).\n");
62 class NonSfiUnitTestPlatformDelegate
: public base::UnitTestPlatformDelegate
{
64 NonSfiUnitTestPlatformDelegate() {
67 bool Init(const std::string
& test_binary
) {
68 base::FilePath dir_exe
;
69 if (!PathService::Get(base::DIR_EXE
, &dir_exe
)) {
70 LOG(ERROR
) << "Failed to get directory of the current executable.";
74 test_path_
= dir_exe
.AppendASCII(test_binary
);
79 bool CreateTemporaryFile(base::FilePath
* path
) override
{
80 if (!base::CreateNewTempDirectory(base::FilePath::StringType(), path
))
82 *path
= path
->AppendASCII("test_results.xml");
86 bool GetTests(std::vector
<base::SplitTestName
>* output
) override
{
87 base::FilePath output_file
;
88 if (!base::CreateTemporaryFile(&output_file
)) {
89 LOG(ERROR
) << "Failed to create a temp file.";
93 base::CommandLine
cmd_line(test_path_
);
94 cmd_line
.AppendSwitchPath(switches::kTestLauncherListTests
, output_file
);
96 base::LaunchOptions launch_options
;
97 launch_options
.wait
= true;
99 if (!base::LaunchProcess(cmd_line
, launch_options
).IsValid())
102 return base::ReadTestNamesFromFile(output_file
, output
);
105 std::string
GetWrapperForChildGTestProcess() override
{
106 return std::string();
109 base::CommandLine
GetCommandLineForChildGTestProcess(
110 const std::vector
<std::string
>& test_names
,
111 const base::FilePath
& output_file
) override
{
112 base::CommandLine
cmd_line(test_path_
);
113 cmd_line
.AppendSwitchPath(
114 switches::kTestLauncherOutput
, output_file
);
115 cmd_line
.AppendSwitchASCII(
116 base::kGTestFilterFlag
, JoinString(test_names
, ":"));
120 void RelaunchTests(base::TestLauncher
* test_launcher
,
121 const std::vector
<std::string
>& test_names
,
122 int launch_flags
) override
{
123 RunUnitTestsBatch(test_launcher
, this, test_names
, launch_flags
);
126 base::FilePath test_path_
;
131 int TestLauncherNonSfiMain(const std::string
& test_binary
) {
132 if (base::CommandLine::ForCurrentProcess()->HasSwitch(kHelpFlag
)) {
137 base::TimeTicks
start_time(base::TimeTicks::Now());
139 TestTimeouts::Initialize();
141 base::MessageLoopForIO message_loop
;
143 NonSfiUnitTestPlatformDelegate platform_delegate
;
144 if (!platform_delegate
.Init(test_binary
)) {
145 fprintf(stderr
, "Failed to initialize test launcher.\n");
150 base::UnitTestLauncherDelegate
delegate(&platform_delegate
, 10, true);
151 base::TestLauncher
launcher(&delegate
, base::SysInfo::NumberOfProcessors());
152 bool success
= launcher
.Run();
154 fprintf(stdout
, "Tests took %" PRId64
" seconds.\n",
155 (base::TimeTicks::Now() - start_time
).InSeconds());
157 return success
? 0 : 1;