1 /*
2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "OveruseConfigurationTestUtils.h"
18 #include "OveruseConfigurationXmlHelper.h"
19 
20 #include <aidl/android/automotive/watchdog/internal/ApplicationCategoryType.h>
21 #include <aidl/android/automotive/watchdog/internal/ComponentType.h>
22 #include <android-base/file.h>
23 #include <android-base/result.h>
24 #include <gmock/gmock.h>
25 
26 namespace android {
27 namespace automotive {
28 namespace watchdog {
29 
30 using ::aidl::android::automotive::watchdog::internal::ApplicationCategoryType;
31 using ::aidl::android::automotive::watchdog::internal::ComponentType;
32 using ::aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration;
33 
34 namespace {
35 
36 constexpr const char* kTestDataDir = "/tests/data/";
37 
38 constexpr const char* kValidSystemConfiguration = "valid_overuse_system_configuration.xml";
39 constexpr const char* kValidVendorConfiguration = "valid_overuse_vendor_configuration.xml";
40 constexpr const char* kValidThirdPartyConfiguration = "valid_overuse_third_party_configuration.xml";
41 
42 const std::vector<const char*> kInvalidOveruseConfigurations =
43         {"duplicate_component_io_thresholds_overuse_configuration.xml",
44          "duplicate_component_type_overuse_configuration.xml",
45          "duplicate_io_config_overuse_configuration.xml",
46          "incomplete_app_category_io_thresholds_overuse_configuration.xml",
47          "incomplete_component_io_thresholds_overuse_configuration.xml",
48          "incomplete_pkg_io_thresholds_overuse_configuration.xml",
49          "incomplete_systemwide_io_thresholds_overuse_configuration.xml",
50          "invalid_component_type_overuse_configuration.xml",
51          "invalid_param_systemwide_io_thresholds_overuse_configuration.xml",
52          "invalid_state_app_category_io_thresholds_overuse_configuration.xml",
53          "invalid_state_component_io_thresholds_overuse_configuration.xml",
54          "invalid_state_pkg_io_thresholds_overuse_configuration.xml",
55          "invalid_type_app_category_mapping_overuse_configuration.xml",
56          "missing_component_io_thresholds_overuse_configuration.xml",
57          "missing_io_config_overuse_configuration.xml",
58          "missing_pkg_name_app_category_mapping_overuse_configuration.xml",
59          "missing_pkg_name_pkg_io_thresholds_overuse_configuration.xml",
60          "missing_pkg_name_safe_to_kill_entry_overuse_configuration.xml",
61          "missing_threshold_app_category_io_thresholds_overuse_configuration.xml",
62          "missing_threshold_component_io_thresholds_overuse_configuration.xml",
63          "missing_threshold_pkg_io_thresholds_overuse_configuration.xml",
64          "missing_threshold_systemwide_io_thresholds_overuse_configuration.xml"};
65 
getTestFilePath(const char * filename)66 std::string getTestFilePath(const char* filename) {
67     static std::string baseDir = android::base::GetExecutableDirectory();
68     return baseDir + kTestDataDir + filename;
69 }
70 
71 }  // namespace
72 
TEST(OveruseConfigurationXmlHelperTest,TestValidSystemConfiguration)73 TEST(OveruseConfigurationXmlHelperTest, TestValidSystemConfiguration) {
74     auto ioConfig = constructIoOveruseConfig(
75             /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::SYSTEM,
76                                                             300 * kOneMegaByte, 150 * kOneMegaByte,
77                                                             500 * kOneMegaByte),
78             /*packageSpecific=*/
79             {toPerStateIoOveruseThreshold("system.package.C", 400 * kOneMegaByte,
80                                           100 * kOneMegaByte, 200 * kOneMegaByte),
81              toPerStateIoOveruseThreshold("system.package.D", 1024 * kOneMegaByte,
82                                           500 * kOneMegaByte, 2048 * kOneMegaByte)},
83             /*categorySpecific=*/{},
84             /*systemWide=*/{toIoOveruseAlertThreshold(10, 200), toIoOveruseAlertThreshold(5, 50)});
85     ResourceOveruseConfiguration expected =
86             constructResourceOveruseConfig(ComponentType::SYSTEM,
87                                            /*safeToKill=*/{"system.package.A", "system.package.B"},
88                                            /*vendorPrefixes=*/{},
89                                            /*packageMetadata=*/
90                                            {toPackageMetadata("system.package.A",
91                                                               ApplicationCategoryType::MEDIA),
92                                             toPackageMetadata("system.package.B",
93                                                               ApplicationCategoryType::MAPS)},
94                                            ioConfig);
95     auto actual = OveruseConfigurationXmlHelper::parseXmlFile(
96             getTestFilePath(kValidSystemConfiguration).c_str());
97     ASSERT_RESULT_OK(actual);
98     EXPECT_THAT(*actual, ResourceOveruseConfigurationMatcher(expected))
99             << "Expected: " << expected.toString() << "\nActual: " << actual->toString();
100 }
101 
TEST(OveruseConfigurationXmlHelperTest,TestValidVendorConfiguration)102 TEST(OveruseConfigurationXmlHelperTest, TestValidVendorConfiguration) {
103     auto ioConfig = constructIoOveruseConfig(
104             /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::VENDOR,
105                                                             1024 * kOneMegaByte, 512 * kOneMegaByte,
106                                                             3072 * kOneMegaByte),
107             /*packageSpecific=*/
108             {toPerStateIoOveruseThreshold("com.vendor.package.C", 400 * kOneMegaByte,
109                                           100 * kOneMegaByte, 200 * kOneMegaByte),
110              toPerStateIoOveruseThreshold("com.vendor.package.D", 1024 * kOneMegaByte,
111                                           500 * kOneMegaByte, 2048 * kOneMegaByte)},
112             /*categorySpecific=*/
113             {toPerStateIoOveruseThreshold("MAPS", 800 * kOneMegaByte, 900 * kOneMegaByte,
114                                           2048 * kOneMegaByte),
115              toPerStateIoOveruseThreshold("MEDIA", 600 * kOneMegaByte, 700 * kOneMegaByte,
116                                           1024 * kOneMegaByte)},
117             /*systemWide=*/{});
118     ResourceOveruseConfiguration expected =
119             constructResourceOveruseConfig(ComponentType::VENDOR,
120                                            /*safeToKill=*/
121                                            {"com.vendor.package.A", "com.vendor.package.B"},
122                                            /*vendorPrefixes=*/{"com.vendor.package"},
123                                            /*packageMetadata=*/
124                                            {toPackageMetadata("com.vendor.package.A",
125                                                               ApplicationCategoryType::MEDIA),
126                                             toPackageMetadata("com.vendor.package.B",
127                                                               ApplicationCategoryType::MAPS),
128                                             toPackageMetadata("com.third.party.package.C",
129                                                               ApplicationCategoryType::MEDIA),
130                                             toPackageMetadata("system.package.D",
131                                                               ApplicationCategoryType::MAPS)},
132                                            ioConfig);
133     auto actual = OveruseConfigurationXmlHelper::parseXmlFile(
134             getTestFilePath(kValidVendorConfiguration).c_str());
135     ASSERT_RESULT_OK(actual);
136     EXPECT_THAT(*actual, ResourceOveruseConfigurationMatcher(expected))
137             << "Expected: " << expected.toString() << "\nActual: " << actual->toString();
138 }
139 
TEST(OveruseConfigurationXmlHelperTest,TestValidThirdPartyConfiguration)140 TEST(OveruseConfigurationXmlHelperTest, TestValidThirdPartyConfiguration) {
141     auto ioConfig = constructIoOveruseConfig(
142             /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::THIRD_PARTY,
143                                                             300 * kOneMegaByte, 150 * kOneMegaByte,
144                                                             500 * kOneMegaByte),
145             /*packageSpecific=*/{},
146             /*categorySpecific=*/{},
147             /*systemWide=*/{});
148     ResourceOveruseConfiguration expected =
149             constructResourceOveruseConfig(ComponentType::THIRD_PARTY,
150                                            /*safeToKill=*/{},
151                                            /*vendorPrefixes=*/{},
152                                            /*packageMetadata=*/{}, ioConfig);
153     auto actual = OveruseConfigurationXmlHelper::parseXmlFile(
154             getTestFilePath(kValidThirdPartyConfiguration).c_str());
155     ASSERT_RESULT_OK(actual);
156     EXPECT_THAT(*actual, ResourceOveruseConfigurationMatcher(expected))
157             << "Expected: " << expected.toString() << "\nActual: " << actual->toString();
158 }
159 
TEST(OveruseConfigurationXmlHelperTest,TestInvalidOveruseConfigurations)160 TEST(OveruseConfigurationXmlHelperTest, TestInvalidOveruseConfigurations) {
161     for (const auto& filename : kInvalidOveruseConfigurations) {
162         ASSERT_FALSE(
163                 OveruseConfigurationXmlHelper::parseXmlFile(getTestFilePath(filename).c_str()).ok())
164                 << "Must return error on parsing '" << filename << "'";
165     }
166 }
167 
TEST(OveruseConfigurationXmlHelperTest,TestWriteXmlFileWithSystemConfiguration)168 TEST(OveruseConfigurationXmlHelperTest, TestWriteXmlFileWithSystemConfiguration) {
169     auto ioConfig = constructIoOveruseConfig(
170             /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::SYSTEM,
171                                                             300 * kOneMegaByte, 150 * kOneMegaByte,
172                                                             500 * kOneMegaByte),
173             /*packageSpecific=*/
174             {toPerStateIoOveruseThreshold("system.package.C", 400 * kOneMegaByte,
175                                           100 * kOneMegaByte, 200 * kOneMegaByte),
176              toPerStateIoOveruseThreshold("system.package.D", 1024 * kOneMegaByte,
177                                           500 * kOneMegaByte, 2048 * kOneMegaByte)},
178             /*categorySpecific=*/{},
179             /*systemWide=*/{toIoOveruseAlertThreshold(10, 200), toIoOveruseAlertThreshold(5, 50)});
180     ResourceOveruseConfiguration expected =
181             constructResourceOveruseConfig(ComponentType::SYSTEM,
182                                            /*safeToKill=*/{"system.package.A", "system.package.B"},
183                                            /*vendorPrefixes=*/{},
184                                            /*packageMetadata=*/
185                                            {toPackageMetadata("system.package.A",
186                                                               ApplicationCategoryType::MEDIA),
187                                             toPackageMetadata("system.package.B",
188                                                               ApplicationCategoryType::MAPS)},
189                                            ioConfig);
190     TemporaryFile temporaryFile;
191     ASSERT_NE(temporaryFile.fd, -1);
192 
193     ASSERT_RESULT_OK(OveruseConfigurationXmlHelper::writeXmlFile(expected, temporaryFile.path));
194 
195     auto actual = OveruseConfigurationXmlHelper::parseXmlFile(temporaryFile.path);
196 
197     ASSERT_RESULT_OK(actual);
198 
199     EXPECT_THAT(*actual, ResourceOveruseConfigurationMatcher(expected))
200             << "Expected: " << expected.toString() << "\nActual: " << actual->toString();
201 
202     temporaryFile.release();
203 }
204 
TEST(OveruseConfigurationXmlHelperTest,TestWriteXmlFileWithVendorConfiguration)205 TEST(OveruseConfigurationXmlHelperTest, TestWriteXmlFileWithVendorConfiguration) {
206     auto ioConfig = constructIoOveruseConfig(
207             /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::VENDOR,
208                                                             1024 * kOneMegaByte, 512 * kOneMegaByte,
209                                                             3072 * kOneMegaByte),
210             /*packageSpecific=*/
211             {toPerStateIoOveruseThreshold("com.vendor.package.C", 400 * kOneMegaByte,
212                                           100 * kOneMegaByte, 200 * kOneMegaByte),
213              toPerStateIoOveruseThreshold("com.vendor.package.D", 1024 * kOneMegaByte,
214                                           500 * kOneMegaByte, 2048 * kOneMegaByte)},
215             /*categorySpecific=*/
216             {toPerStateIoOveruseThreshold("MAPS", 800 * kOneMegaByte, 900 * kOneMegaByte,
217                                           2048 * kOneMegaByte),
218              toPerStateIoOveruseThreshold("MEDIA", 600 * kOneMegaByte, 700 * kOneMegaByte,
219                                           1024 * kOneMegaByte)},
220             /*systemWide=*/{});
221     ResourceOveruseConfiguration expected =
222             constructResourceOveruseConfig(ComponentType::VENDOR,
223                                            /*safeToKill=*/
224                                            {"com.vendor.package.A", "com.vendor.package.B"},
225                                            /*vendorPrefixes=*/{"com.vendor.package"},
226                                            /*packageMetadata=*/
227                                            {toPackageMetadata("com.vendor.package.A",
228                                                               ApplicationCategoryType::MEDIA),
229                                             toPackageMetadata("com.vendor.package.B",
230                                                               ApplicationCategoryType::MAPS),
231                                             toPackageMetadata("com.third.party.package.C",
232                                                               ApplicationCategoryType::MEDIA),
233                                             toPackageMetadata("system.package.D",
234                                                               ApplicationCategoryType::MAPS)},
235                                            ioConfig);
236     TemporaryFile temporaryFile;
237     ASSERT_NE(temporaryFile.fd, -1);
238 
239     ASSERT_RESULT_OK(OveruseConfigurationXmlHelper::writeXmlFile(expected, temporaryFile.path));
240 
241     auto actual = OveruseConfigurationXmlHelper::parseXmlFile(temporaryFile.path);
242 
243     ASSERT_RESULT_OK(actual);
244 
245     EXPECT_THAT(*actual, ResourceOveruseConfigurationMatcher(expected))
246             << "Expected: " << expected.toString() << "\nActual: " << actual->toString();
247 
248     temporaryFile.release();
249 }
250 
TEST(OveruseConfigurationXmlHelperTest,TestWriteXmlFileWithThirdPartyConfiguration)251 TEST(OveruseConfigurationXmlHelperTest, TestWriteXmlFileWithThirdPartyConfiguration) {
252     auto ioConfig = constructIoOveruseConfig(
253             /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::THIRD_PARTY,
254                                                             300 * kOneMegaByte, 150 * kOneMegaByte,
255                                                             500 * kOneMegaByte),
256             /*packageSpecific=*/{},
257             /*categorySpecific=*/{},
258             /*systemWide=*/{});
259     ResourceOveruseConfiguration expected =
260             constructResourceOveruseConfig(ComponentType::THIRD_PARTY,
261                                            /*safeToKill=*/{},
262                                            /*vendorPrefixes=*/{},
263                                            /*packageMetadata=*/{}, ioConfig);
264     TemporaryFile temporaryFile;
265     ASSERT_NE(temporaryFile.fd, -1);
266 
267     ASSERT_RESULT_OK(OveruseConfigurationXmlHelper::writeXmlFile(expected, temporaryFile.path));
268 
269     auto actual = OveruseConfigurationXmlHelper::parseXmlFile(temporaryFile.path);
270 
271     ASSERT_RESULT_OK(actual);
272 
273     EXPECT_THAT(*actual, ResourceOveruseConfigurationMatcher(expected))
274             << "Expected: " << expected.toString() << "\nActual: " << actual->toString();
275 
276     temporaryFile.release();
277 }
278 
TEST(OveruseConfigurationXmlHelperTest,TestFailsWriteXmlFileWithInvalidConfig)279 TEST(OveruseConfigurationXmlHelperTest, TestFailsWriteXmlFileWithInvalidConfig) {
280     ResourceOveruseConfiguration resourceOveruseConfig;
281     resourceOveruseConfig.componentType = ComponentType::THIRD_PARTY;
282 
283     TemporaryFile temporaryFile;
284     ASSERT_NE(temporaryFile.fd, -1);
285 
286     ASSERT_FALSE(
287             OveruseConfigurationXmlHelper::writeXmlFile(resourceOveruseConfig, temporaryFile.path)
288                     .ok())
289             << "Should fail to write invalid config";
290 
291     temporaryFile.release();
292 }
293 
294 }  // namespace watchdog
295 }  // namespace automotive
296 }  // namespace android
297