1 // Copyright 2013 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TEST_LAUNCHER_TEST_LAUNCHER_H_ 6 #define BASE_TEST_LAUNCHER_TEST_LAUNCHER_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <memory> 12 #include <set> 13 #include <string> 14 #include <string_view> 15 #include <unordered_set> 16 #include <vector> 17 18 #include "base/command_line.h" 19 #include "base/memory/raw_ptr.h" 20 #include "base/process/launch.h" 21 #include "base/test/gtest_util.h" 22 #include "base/test/launcher/test_result.h" 23 #include "base/test/launcher/test_results_tracker.h" 24 #include "base/threading/platform_thread.h" 25 #include "base/threading/thread_checker.h" 26 #include "base/time/time.h" 27 #include "base/timer/timer.h" 28 #include "build/build_config.h" 29 30 namespace base { 31 32 // Constants for GTest command-line flags. 33 extern const char kGTestFilterFlag[]; 34 extern const char kGTestFlagfileFlag[]; 35 extern const char kGTestHelpFlag[]; 36 extern const char kGTestListTestsFlag[]; 37 extern const char kGTestRepeatFlag[]; 38 extern const char kGTestRunDisabledTestsFlag[]; 39 extern const char kGTestOutputFlag[]; 40 extern const char kGTestShuffleFlag[]; 41 extern const char kGTestRandomSeedFlag[]; 42 extern const char kIsolatedScriptRunDisabledTestsFlag[]; 43 extern const char kIsolatedScriptTestFilterFlag[]; 44 extern const char kIsolatedScriptTestRepeatFlag[]; 45 46 // Interface for use with LaunchTests that abstracts away exact details 47 // which tests and how are run. 48 class TestLauncherDelegate { 49 public: 50 // Called to get names of tests available for running. The delegate 51 // must put the result in |output| and return true on success. 52 virtual bool GetTests(std::vector<TestIdentifier>* output) = 0; 53 54 // Additional delegate TestResult processing. ProcessTestResults(std::vector<TestResult> & test_results,TimeDelta elapsed_time)55 virtual void ProcessTestResults(std::vector<TestResult>& test_results, 56 TimeDelta elapsed_time) {} 57 58 // Called to get the command line for the specified tests. 59 // |output_file_| is populated with the path to the result file, and must 60 // be inside |temp_dir|. 61 virtual CommandLine GetCommandLine(const std::vector<std::string>& test_names, 62 const FilePath& temp_dir, 63 FilePath* output_file) = 0; 64 65 // Invoked when a test process exceeds its runtime, immediately before it is 66 // terminated. |command_line| is the command line used to launch the process. 67 // NOTE: this method is invoked on the thread the process is launched on. OnTestTimedOut(const CommandLine & cmd_line)68 virtual void OnTestTimedOut(const CommandLine& cmd_line) {} 69 70 // Returns the delegate specific wrapper for command line. 71 // If it is not empty, it is prepended to the final command line. 72 virtual std::string GetWrapper() = 0; 73 74 // Returns the delegate specific flags for launch options. 75 // The flags are specified in LaunchChildGTestProcessFlags. 76 virtual int GetLaunchOptions() = 0; 77 78 // Returns the delegate specific timeout per test. 79 virtual TimeDelta GetTimeout() = 0; 80 81 // Returns the delegate specific batch size. 82 virtual size_t GetBatchSize() = 0; 83 84 // Returns true if test should run. 85 virtual bool ShouldRunTest(const TestIdentifier& test); 86 87 protected: 88 virtual ~TestLauncherDelegate(); 89 }; 90 91 // Launches tests using a TestLauncherDelegate. 92 class TestLauncher { 93 public: 94 // Flags controlling behavior of LaunchChildGTestProcess. 95 enum LaunchChildGTestProcessFlags { 96 // Allows usage of job objects on Windows. Helps properly clean up child 97 // processes. 98 USE_JOB_OBJECTS = (1 << 0), 99 100 // Allows breakaway from job on Windows. May result in some child processes 101 // not being properly terminated after launcher dies if these processes 102 // fail to cooperate. 103 ALLOW_BREAKAWAY_FROM_JOB = (1 << 1), 104 }; 105 106 // Enum for subprocess stdio redirect. 107 enum StdioRedirect { AUTO, ALWAYS, NEVER }; 108 109 struct LaunchOptions { 110 LaunchOptions(); 111 LaunchOptions(const LaunchOptions& other); 112 ~LaunchOptions(); 113 114 int flags = 0; 115 // These mirror values in base::LaunchOptions, see it for details. 116 #if BUILDFLAG(IS_WIN) 117 base::LaunchOptions::Inherit inherit_mode = 118 base::LaunchOptions::Inherit::kSpecific; 119 base::HandlesToInheritVector handles_to_inherit; 120 #else 121 FileHandleMappingVector fds_to_remap; 122 #endif 123 }; 124 125 // Constructor. |parallel_jobs| is the limit of simultaneous parallel test 126 // jobs. |retry_limit| is the default limit of retries for bots or all tests. 127 TestLauncher(TestLauncherDelegate* launcher_delegate, 128 size_t parallel_jobs, 129 size_t retry_limit = 1U); 130 131 TestLauncher(const TestLauncher&) = delete; 132 TestLauncher& operator=(const TestLauncher&) = delete; 133 134 // virtual to mock in testing. 135 virtual ~TestLauncher(); 136 137 // Runs the launcher. Must be called at most once. 138 // command_line is null by default. 139 // if null, uses command line for current process. 140 [[nodiscard]] bool Run(CommandLine* command_line = nullptr); 141 142 // Launches a child process (assumed to be gtest-based binary) which runs 143 // tests indicated by |test_names|. 144 // |task_runner| is used to post results back to the launcher on the main 145 // thread. |task_temp_dir| is used for child process files such as user data, 146 // result file, and flag_file. |child_temp_dir|, if not empty, specifies a 147 // directory (within task_temp_dir) that the child process will use as its 148 // process-wide temporary directory. 149 // virtual to mock in testing. 150 virtual void LaunchChildGTestProcess( 151 scoped_refptr<TaskRunner> task_runner, 152 const std::vector<std::string>& test_names, 153 const FilePath& task_temp_dir, 154 const FilePath& child_temp_dir); 155 156 // Called when a test has finished running. 157 void OnTestFinished(const TestResult& result); 158 159 // Returns true if child test processes should have dedicated temporary 160 // directories. SupportsPerChildTempDirs()161 static constexpr bool SupportsPerChildTempDirs() { 162 #if BUILDFLAG(IS_WIN) 163 return true; 164 #else 165 // TODO(https://crbug.com/1038857): Enable for macOS, Linux, and Fuchsia. 166 return false; 167 #endif 168 } 169 170 private: 171 [[nodiscard]] bool Init(CommandLine* command_line); 172 173 // Gets tests from the delegate, and converts to TestInfo objects. 174 // Catches and logs uninstantiated parameterized tests. 175 // Returns false if delegate fails to return tests. 176 bool InitTests(); 177 178 // Some of the TestLauncherDelegate implementations don't call into gtest 179 // until they've already split into test-specific processes. This results 180 // in gtest's native shuffle implementation attempting to shuffle one test. 181 // Shuffling the list of tests in the test launcher (before the delegate 182 // gets involved) ensures that the entire shard is shuffled. 183 bool ShuffleTests(CommandLine* command_line); 184 185 // Move all PRE_ tests prior to the final test in order. 186 // Validate tests names. This includes no name conflict between tests 187 // without DISABLED_ prefix, and orphaned PRE_ tests. 188 // Add all tests and disabled tests names to result tracker. 189 // Filter Disabled tests if not flagged to run. 190 // Returns false if any violation is found. 191 bool ProcessAndValidateTests(); 192 193 // Runs all tests in current iteration. 194 void RunTests(); 195 196 // Print test names that almost match a filter (matches *<filter>*). 197 void PrintFuzzyMatchingTestNames(); 198 199 // Retry to run tests that failed during RunTests. 200 // Returns false if retry still fails or unable to start. 201 bool RunRetryTests(); 202 203 void CombinePositiveTestFilters(std::vector<std::string> filter_a, 204 std::vector<std::string> filter_b); 205 206 // Rest counters, retry tests list, and test result tracker. 207 void OnTestIterationStart(); 208 209 #if BUILDFLAG(IS_POSIX) 210 void OnShutdownPipeReadable(); 211 #endif 212 213 // Saves test results summary as JSON if requested from command line. 214 void MaybeSaveSummaryAsJSON(const std::vector<std::string>& additional_tags); 215 216 // Called when a test iteration is finished. 217 void OnTestIterationFinished(); 218 219 // Called by the delay timer when no output was made for a while. 220 void OnOutputTimeout(); 221 222 // Creates and starts a ThreadPoolInstance with |num_parallel_jobs| dedicated 223 // to foreground blocking tasks (corresponds to the traits used to launch and 224 // wait for child processes). virtual to mock in testing. 225 virtual void CreateAndStartThreadPool(size_t num_parallel_jobs); 226 227 // Callback to receive result of a test. 228 // |result_file| is a path to xml file written by child process. 229 // It contains information about test and failed 230 // EXPECT/ASSERT/DCHECK statements. Test launcher parses that 231 // file to get additional information about test run (status, 232 // error-messages, stack-traces and file/line for failures). 233 // |thread_id| is the actual worker thread that launching the child process. 234 // |process_num| is a sequence number of the process executed in the run. 235 // |leaked_items| is the number of files and/or directories remaining in the 236 // child process's temporary directory upon its termination. 237 void ProcessTestResults(const std::vector<std::string>& test_names, 238 const FilePath& result_file, 239 const std::string& output, 240 TimeDelta elapsed_time, 241 int exit_code, 242 bool was_timeout, 243 PlatformThreadId thread_id, 244 int process_num, 245 int leaked_items); 246 247 std::vector<std::string> CollectTests(); 248 249 // Helper to tell if the test runs in current shard. 250 // `prefix_stripped_name` is the test name excluding DISABLED_ and 251 // PRE_ prefixes. 252 bool ShouldRunInCurrentShard(std::string_view prefix_stripped_name) const; 253 254 // Helper to check whether only exact positive filter is passed via 255 // a filter file. 256 bool IsOnlyExactPositiveFilterFromFile(const CommandLine* command_line) const; 257 258 // Make sure we don't accidentally call the wrong methods e.g. on the worker 259 // pool thread. Should be the first member so that it's destroyed last: when 260 // destroying other members, especially the worker pool, we may check the code 261 // is running on the correct thread. 262 ThreadChecker thread_checker_; 263 264 raw_ptr<TestLauncherDelegate> launcher_delegate_; 265 266 // Support for outer sharding, just like gtest does. 267 int32_t total_shards_; // Total number of outer shards, at least one. 268 int32_t shard_index_; // Index of shard the launcher is to run. 269 270 int cycles_; // Number of remaining test iterations, or -1 for infinite. 271 272 // Test filters (empty means no filter). 273 bool has_at_least_one_positive_filter_; 274 std::vector<std::string> positive_test_filter_; 275 std::vector<std::string> negative_test_filter_; 276 277 // Enforce to run all test cases listed in exact positive filter. 278 bool enforce_exact_postive_filter_; 279 280 // Class to encapsulate gtest information. 281 class TestInfo; 282 283 // Tests to use (cached result of TestLauncherDelegate::GetTests). 284 std::vector<TestInfo> tests_; 285 286 // Threshold for number of broken tests. 287 size_t broken_threshold_; 288 289 // Number of tests started in this iteration. 290 size_t test_started_count_; 291 292 // Number of tests finished in this iteration. 293 size_t test_finished_count_; 294 295 // Number of tests successfully finished in this iteration. 296 size_t test_success_count_; 297 298 // Number of tests either timing out or having an unknown result, 299 // likely indicating a more systemic problem if widespread. 300 size_t test_broken_count_; 301 302 // How many retries are left. 303 size_t retries_left_; 304 305 // Maximum number of retries per iteration. 306 size_t retry_limit_; 307 308 // Maximum number of output bytes per test. 309 size_t output_bytes_limit_; 310 311 // If true will not early exit nor skip retries even if too many tests are 312 // broken. 313 bool force_run_broken_tests_; 314 315 // Tests to retry in this iteration. 316 std::unordered_set<std::string> tests_to_retry_; 317 318 TestResultsTracker results_tracker_; 319 320 // Watchdog timer to make sure we do not go without output for too long. 321 DelayTimer watchdog_timer_; 322 323 // Number of jobs to run in parallel. 324 size_t parallel_jobs_; 325 326 // Switch to control tests stdio :{auto, always, never} 327 StdioRedirect print_test_stdio_; 328 329 // Skip disabled tests unless explicitly requested. 330 bool skip_disabled_tests_; 331 332 // Stop test iterations due to failure. 333 bool stop_on_failure_; 334 335 // Path to JSON summary result file. 336 FilePath summary_path_; 337 338 // Path to trace file. 339 FilePath trace_path_; 340 341 // redirect stdio of subprocess 342 bool redirect_stdio_; 343 344 // Number of times all tests should be repeated during each iteration. 345 // 1 if gtest_repeat is not specified or gtest_break_on_failure is specified. 346 // Otherwise it matches gtest_repeat value. 347 int repeats_per_iteration_ = 1; 348 }; 349 350 // Watch a gtest XML result file for tests run in a batch to complete. 351 class ResultWatcher { 352 public: 353 ResultWatcher(FilePath result_file, size_t num_tests); 354 355 // Poll the incomplete result file, blocking until the batch completes or a 356 // test timed out. Returns true iff no tests timed out. 357 bool PollUntilDone(TimeDelta timeout_per_test); 358 359 // Wait and block for up to `timeout` before we poll the result file again. 360 // Returns true iff we should stop polling the results early. 361 virtual bool WaitWithTimeout(TimeDelta timeout) = 0; 362 363 private: 364 // Read the results, check if a timeout occurred, and then return how long 365 // the polling loop should wait for. A nonpositive return value indicates a 366 // timeout (i.e., the next check is overdue). 367 // 368 // If a timeout did not occur, this method tries to schedule the next check 369 // for `timeout_per_test` since the last test completed. 370 TimeDelta PollOnce(TimeDelta timeout_per_test); 371 372 // Get the timestamp of the test that completed most recently. If no tests 373 // have completed, return the null time. 374 Time LatestCompletionTimestamp(const std::vector<TestResult>& test_results); 375 376 // Path to the results file. 377 FilePath result_file_; 378 379 // The number of tests that run in this batch. 380 size_t num_tests_; 381 382 // The threshold past which we attribute a large time since latest completion 383 // to daylight savings time instead of a timed out test. 384 static constexpr TimeDelta kDaylightSavingsThreshold = Minutes(50); 385 }; 386 387 // Return the number of parallel jobs to use, or 0U in case of error. 388 size_t NumParallelJobs(unsigned int cores_per_job); 389 390 // Extract part from |full_output| that applies to |result|. 391 std::string GetTestOutputSnippet(const TestResult& result, 392 const std::string& full_output); 393 394 // Truncates a snippet to approximately the allowed length, while trying to 395 // retain fatal messages. Exposed for testing only. 396 std::string TruncateSnippetFocused(const std::string_view snippet, 397 size_t byte_limit); 398 399 } // namespace base 400 401 #endif // BASE_TEST_LAUNCHER_TEST_LAUNCHER_H_ 402