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_RESULTS_TRACKER_H_ 6 #define BASE_TEST_LAUNCHER_TEST_RESULTS_TRACKER_H_ 7 8 #include <map> 9 #include <set> 10 #include <string> 11 #include <utility> 12 #include <vector> 13 14 #include "base/functional/callback.h" 15 #include "base/gtest_prod_util.h" 16 #include "base/memory/raw_ptr.h" 17 #include "base/test/launcher/test_result.h" 18 #include "base/threading/thread_checker.h" 19 20 namespace base { 21 22 class CommandLine; 23 class FilePath; 24 25 // A helper class to output results. 26 // Note: as currently XML is the only supported format by gtest, we don't 27 // check output format (e.g. "xml:" prefix) here and output an XML file 28 // unconditionally. 29 // Note: we don't output per-test-case or total summary info like 30 // total failed_test_count, disabled_test_count, elapsed_time and so on. 31 // Only each test (testcase element in the XML) will have the correct 32 // failed/disabled/elapsed_time information. Each test won't include 33 // detailed failure messages either. 34 class TestResultsTracker { 35 public: 36 TestResultsTracker(); 37 38 TestResultsTracker(const TestResultsTracker&) = delete; 39 TestResultsTracker& operator=(const TestResultsTracker&) = delete; 40 41 ~TestResultsTracker(); 42 43 // Initialize the result tracker. Must be called exactly once before 44 // calling any other methods. Returns true on success. 45 [[nodiscard]] bool Init(const CommandLine& command_line); 46 47 // Called when a test iteration is starting. 48 void OnTestIterationStarting(); 49 50 // Adds |test_name| to the set of discovered tests (this includes all tests 51 // present in the executable, not necessarily run). 52 void AddTest(const std::string& test_name); 53 54 // Adds |test_name| to the set of disabled tests. 55 void AddDisabledTest(const std::string& test_name); 56 57 // Adds location for the |test_name|. Locations are required for all tests run 58 // in a given shard, by both the TestLauncher and its delegate. 59 void AddTestLocation(const std::string& test_name, 60 const std::string& file, 61 int line); 62 63 // Adds placeholder for the |test_name|. Placeholders are required for all 64 // tests that are expected to produce results in a given shard. 65 void AddTestPlaceholder(const std::string& test_name); 66 67 // Adds |result| to the stored test results. 68 void AddTestResult(const TestResult& result); 69 70 // Adds to the current iteration the fact that |count| items were leaked by 71 // one or more tests in |test_names| in its temporary directory. 72 void AddLeakedItems(int count, const std::vector<std::string>& test_names); 73 74 // Even when no iterations have occurred, we still want to generate output 75 // data with "NOTRUN" status for each test. This method generates a 76 // placeholder iteration. The first iteration will overwrite the data in the 77 // placeholder iteration. 78 void GeneratePlaceholderIteration(); 79 80 // Prints a summary of current test iteration to stdout. 81 void PrintSummaryOfCurrentIteration() const; 82 83 // Prints a summary of all test iterations (not just the last one) to stdout. 84 void PrintSummaryOfAllIterations() const; 85 86 // Adds a string tag to the JSON summary. This is intended to indicate 87 // conditions that affect the entire test run, as opposed to individual tests. 88 void AddGlobalTag(const std::string& tag); 89 90 // Saves a JSON summary of all test iterations results to |path|. Adds 91 // |additional_tags| to the summary (just for this invocation). Returns 92 // true on success. 93 [[nodiscard]] bool SaveSummaryAsJSON( 94 const FilePath& path, 95 const std::vector<std::string>& additional_tags) const; 96 97 // Map where keys are test result statuses, and values are sets of tests 98 // which finished with that status. 99 typedef std::map<TestResult::Status, std::set<std::string> > TestStatusMap; 100 101 // Returns a test status map (see above) for current test iteration. 102 TestStatusMap GetTestStatusMapForCurrentIteration() const; 103 104 // Returns a test status map (see above) for all test iterations. 105 TestStatusMap GetTestStatusMapForAllIterations() const; 106 107 private: 108 FRIEND_TEST_ALL_PREFIXES(TestResultsTrackerTest, 109 SaveSummaryAsJSONWithLinkInResult); 110 FRIEND_TEST_ALL_PREFIXES(TestResultsTrackerTest, 111 SaveSummaryAsJSONWithTagInResult); 112 FRIEND_TEST_ALL_PREFIXES(TestResultsTrackerTest, 113 SaveSummaryAsJSONWithMultiTagsInResult); 114 FRIEND_TEST_ALL_PREFIXES(TestResultsTrackerTest, 115 SaveSummaryAsJSONWithMultiTagsSameNameInResult); 116 FRIEND_TEST_ALL_PREFIXES(TestResultsTrackerTest, 117 SaveSummaryAsJSONWithPropertyInResult); 118 FRIEND_TEST_ALL_PREFIXES(TestResultsTrackerTest, 119 SaveSummaryAsJSONWithOutTimestampInResult); 120 FRIEND_TEST_ALL_PREFIXES(TestResultsTrackerTest, 121 SaveSummaryAsJSONWithTimestampInResult); 122 void GetTestStatusForIteration(int iteration, TestStatusMap* map) const; 123 124 template<typename InputIterator> 125 void PrintTests(InputIterator first, 126 InputIterator last, 127 const std::string& description) const; 128 void PrintLeaks(int count, const std::vector<std::string>& test_names) const; 129 130 struct AggregateTestResult { 131 AggregateTestResult(); 132 AggregateTestResult(const AggregateTestResult& other); 133 ~AggregateTestResult(); 134 135 std::vector<TestResult> test_results; 136 }; 137 138 struct PerIterationData { 139 PerIterationData(); 140 PerIterationData(const PerIterationData& other); 141 ~PerIterationData(); 142 143 // Aggregate test results grouped by full test name. 144 typedef std::map<std::string, AggregateTestResult> ResultsMap; 145 ResultsMap results; 146 147 // A sequence of tests that leaked files/dirs in their temp directory. 148 std::vector<std::pair<int, std::vector<std::string>>> leaked_temp_items; 149 }; 150 151 struct CodeLocation { CodeLocationCodeLocation152 CodeLocation(const std::string& f, int l) : file(f), line(l) { 153 } 154 155 std::string file; 156 int line; 157 }; 158 159 ThreadChecker thread_checker_; 160 161 // Print tests that leak files and/or directories in their temp dir. 162 bool print_temp_leaks_ = false; 163 164 // Set of global tags, i.e. strings indicating conditions that apply to 165 // the entire test run. 166 std::set<std::string> global_tags_; 167 168 // Set of all test names discovered in the current executable. 169 std::set<std::string> all_tests_; 170 171 // CodeLocation for all tests that will be run as a part of this shard. 172 std::map<std::string, CodeLocation> test_locations_; 173 174 // Name of tests that will run and produce results. 175 std::set<std::string> test_placeholders_; 176 177 // Set of all disabled tests in the current executable. 178 std::set<std::string> disabled_tests_; 179 180 // Store test results for each iteration. 181 std::vector<PerIterationData> per_iteration_data_; 182 183 // Index of current iteration (starting from 0). -1 before the first 184 // iteration. 185 int iteration_; 186 187 // File handle of output file (can be NULL if no file). 188 raw_ptr<FILE> out_; 189 }; 190 191 } // namespace base 192 193 #endif // BASE_TEST_LAUNCHER_TEST_RESULTS_TRACKER_H_ 194