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