xref: /aosp_15_r20/external/cronet/base/test/launcher/test_launcher_test_utils.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2019 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 #include "base/test/launcher/test_launcher_test_utils.h"
6 
7 #include <optional>
8 
9 #include "base/files/file_util.h"
10 #include "base/json/json_reader.h"
11 #include "base/json/json_writer.h"
12 #include "base/test/gtest_util.h"
13 #include "base/test/launcher/test_result.h"
14 
15 namespace base {
16 
17 namespace test_launcher_utils {
18 
19 namespace {
20 
21 // Helper function to return |Value::Dict::FindString| by value instead of
22 // pointer to string, or empty string if nullptr.
FindStringKeyOrEmpty(const Value::Dict & dict,const std::string & key)23 std::string FindStringKeyOrEmpty(const Value::Dict& dict,
24                                  const std::string& key) {
25   const std::string* value = dict.FindString(key);
26   return value ? *value : std::string();
27 }
28 
29 // Find and return test case with name |test_suite_name|,
30 // return null if missing.
GetTestSuite(const std::string & test_suite_name)31 const testing::TestSuite* GetTestSuite(const std::string& test_suite_name) {
32   testing::UnitTest* const unit_test = testing::UnitTest::GetInstance();
33   for (int i = 0; i < unit_test->total_test_suite_count(); ++i) {
34     const testing::TestSuite* test_case = unit_test->GetTestSuite(i);
35     if (test_case->name() == test_suite_name) {
36       return test_case;
37     }
38   }
39   return nullptr;
40 }
41 
42 }  // namespace
43 
ValidateKeyValue(const Value::Dict & dict,const std::string & key,const std::string & expected_value)44 bool ValidateKeyValue(const Value::Dict& dict,
45                       const std::string& key,
46                       const std::string& expected_value) {
47   std::string actual_value = FindStringKeyOrEmpty(dict, key);
48   bool result = !actual_value.compare(expected_value);
49   if (!result)
50     ADD_FAILURE() << key << " expected value: " << expected_value
51                   << ", actual: " << actual_value;
52   return result;
53 }
54 
ValidateKeyValue(const Value::Dict & dict,const std::string & key,int64_t expected_value)55 bool ValidateKeyValue(const Value::Dict& dict,
56                       const std::string& key,
57                       int64_t expected_value) {
58   int actual_value = dict.FindInt(key).value_or(0);
59   bool result = (actual_value == expected_value);
60   if (!result)
61     ADD_FAILURE() << key << " expected value: " << expected_value
62                   << ", actual: " << actual_value;
63   return result;
64 }
65 
ValidateTestResult(const Value::Dict & iteration_data,const std::string & test_name,const std::string & status,size_t result_part_count,bool have_running_info)66 bool ValidateTestResult(const Value::Dict& iteration_data,
67                         const std::string& test_name,
68                         const std::string& status,
69                         size_t result_part_count,
70                         bool have_running_info) {
71   const Value::List* results = iteration_data.FindList(test_name);
72   if (!results) {
73     ADD_FAILURE() << "Cannot find result";
74     return false;
75   }
76   if (1u != results->size()) {
77     ADD_FAILURE() << "Expected one result";
78     return false;
79   }
80 
81   const Value::Dict* dict = (*results)[0].GetIfDict();
82   if (!dict) {
83     ADD_FAILURE() << "Value must be of type DICTIONARY";
84     return false;
85   }
86 
87   if (!ValidateKeyValue(*dict, "status", status))
88     return false;
89 
90   // Verify the keys that only exists when have_running_info, if the test didn't
91   // run, it wouldn't have these information.
92   for (auto* key : {"process_num", "thread_id", "timestamp"}) {
93     bool have_key = dict->Find(key);
94     if (have_running_info && !have_key) {
95       ADD_FAILURE() << "Result must contain '" << key << "' key";
96       return false;
97     }
98     if (!have_running_info && have_key) {
99       ADD_FAILURE() << "Result shouldn't contain '" << key << "' key";
100       return false;
101     }
102   }
103 
104   const Value::List* list = dict->FindList("result_parts");
105   if (!list) {
106     ADD_FAILURE() << "Result must contain 'result_parts' key";
107     return false;
108   }
109 
110   if (result_part_count != list->size()) {
111     ADD_FAILURE() << "result_parts count expected: " << result_part_count
112                   << ", actual:" << list->size();
113     return false;
114   }
115   return true;
116 }
117 
ValidateTestLocations(const Value::Dict & test_locations,const std::string & test_suite_name)118 bool ValidateTestLocations(const Value::Dict& test_locations,
119                            const std::string& test_suite_name) {
120   const testing::TestSuite* test_suite = GetTestSuite(test_suite_name);
121   if (test_suite == nullptr) {
122     ADD_FAILURE() << "Could not find test suite " << test_suite_name;
123     return false;
124   }
125   bool result = true;
126   for (int j = 0; j < test_suite->total_test_count(); ++j) {
127     const testing::TestInfo* test_info = test_suite->GetTestInfo(j);
128     std::string full_name =
129         FormatFullTestName(test_suite->name(), test_info->name());
130     result &= ValidateTestLocation(test_locations, full_name, test_info->file(),
131                                    test_info->line());
132   }
133   return result;
134 }
135 
ValidateTestLocation(const Value::Dict & test_locations,const std::string & test_name,const std::string & file,int line)136 bool ValidateTestLocation(const Value::Dict& test_locations,
137                           const std::string& test_name,
138                           const std::string& file,
139                           int line) {
140   const Value::Dict* dict =
141       test_locations.FindDict(TestNameWithoutDisabledPrefix(test_name));
142   if (!dict) {
143     ADD_FAILURE() << "|test_locations| missing location for " << test_name;
144     return false;
145   }
146 
147   bool result = ValidateKeyValue(*dict, "file", file);
148   result &= ValidateKeyValue(*dict, "line", line);
149   return result;
150 }
151 
ReadSummary(const FilePath & path)152 std::optional<Value::Dict> ReadSummary(const FilePath& path) {
153   std::optional<Value::Dict> result;
154   File resultFile(path, File::FLAG_OPEN | File::FLAG_READ);
155   const int size = 2e7;
156   std::string json;
157   CHECK(ReadFileToStringWithMaxSize(path, &json, size));
158   std::optional<Value> value = JSONReader::Read(json);
159   if (value && value->is_dict())
160     result = std::move(*value).TakeDict();
161 
162   return result;
163 }
164 
165 }  // namespace test_launcher_utils
166 
167 }  // namespace base
168