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