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 <android-base/file.h>
21 #include <android-base/result.h>
22 #include <android/automotive/watchdog/internal/ApplicationCategoryType.h>
23 #include <android/automotive/watchdog/internal/ComponentType.h>
24 #include <gmock/gmock.h>
25 
26 namespace android {
27 namespace automotive {
28 namespace watchdog {
29 
30 using ::android::automotive::watchdog::internal::ApplicationCategoryType;
31 using ::android::automotive::watchdog::internal::ComponentType;
32 using ::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     ALOGW("Wrote to file: %s", temporaryFile.path);
196 
197     auto actual = OveruseConfigurationXmlHelper::parseXmlFile(temporaryFile.path);
198 
199     ASSERT_RESULT_OK(actual);
200 
201     EXPECT_THAT(*actual, ResourceOveruseConfigurationMatcher(expected))
202             << "Expected: " << expected.toString() << "\nActual: " << actual->toString();
203 
204     temporaryFile.release();
205 }
206 
TEST(OveruseConfigurationXmlHelperTest,TestWriteXmlFileWithVendorConfiguration)207 TEST(OveruseConfigurationXmlHelperTest, TestWriteXmlFileWithVendorConfiguration) {
208     auto ioConfig = constructIoOveruseConfig(
209             /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::VENDOR,
210                                                             1024 * kOneMegaByte, 512 * kOneMegaByte,
211                                                             3072 * kOneMegaByte),
212             /*packageSpecific=*/
213             {toPerStateIoOveruseThreshold("com.vendor.package.C", 400 * kOneMegaByte,
214                                           100 * kOneMegaByte, 200 * kOneMegaByte),
215              toPerStateIoOveruseThreshold("com.vendor.package.D", 1024 * kOneMegaByte,
216                                           500 * kOneMegaByte, 2048 * kOneMegaByte)},
217             /*categorySpecific=*/
218             {toPerStateIoOveruseThreshold("MAPS", 800 * kOneMegaByte, 900 * kOneMegaByte,
219                                           2048 * kOneMegaByte),
220              toPerStateIoOveruseThreshold("MEDIA", 600 * kOneMegaByte, 700 * kOneMegaByte,
221                                           1024 * kOneMegaByte)},
222             /*systemWide=*/{});
223     ResourceOveruseConfiguration expected =
224             constructResourceOveruseConfig(ComponentType::VENDOR,
225                                            /*safeToKill=*/
226                                            {"com.vendor.package.A", "com.vendor.package.B"},
227                                            /*vendorPrefixes=*/{"com.vendor.package"},
228                                            /*packageMetadata=*/
229                                            {toPackageMetadata("com.vendor.package.A",
230                                                               ApplicationCategoryType::MEDIA),
231                                             toPackageMetadata("com.vendor.package.B",
232                                                               ApplicationCategoryType::MAPS),
233                                             toPackageMetadata("com.third.party.package.C",
234                                                               ApplicationCategoryType::MEDIA),
235                                             toPackageMetadata("system.package.D",
236                                                               ApplicationCategoryType::MAPS)},
237                                            ioConfig);
238     TemporaryFile temporaryFile;
239     ASSERT_NE(temporaryFile.fd, -1);
240 
241     ASSERT_RESULT_OK(OveruseConfigurationXmlHelper::writeXmlFile(expected, temporaryFile.path));
242 
243     ALOGW("Wrote to file: %s", temporaryFile.path);
244 
245     auto actual = OveruseConfigurationXmlHelper::parseXmlFile(temporaryFile.path);
246 
247     ASSERT_RESULT_OK(actual);
248 
249     EXPECT_THAT(*actual, ResourceOveruseConfigurationMatcher(expected))
250             << "Expected: " << expected.toString() << "\nActual: " << actual->toString();
251 
252     temporaryFile.release();
253 }
254 
TEST(OveruseConfigurationXmlHelperTest,TestWriteXmlFileWithThirdPartyConfiguration)255 TEST(OveruseConfigurationXmlHelperTest, TestWriteXmlFileWithThirdPartyConfiguration) {
256     auto ioConfig = constructIoOveruseConfig(
257             /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::THIRD_PARTY,
258                                                             300 * kOneMegaByte, 150 * kOneMegaByte,
259                                                             500 * kOneMegaByte),
260             /*packageSpecific=*/{},
261             /*categorySpecific=*/{},
262             /*systemWide=*/{});
263     ResourceOveruseConfiguration expected =
264             constructResourceOveruseConfig(ComponentType::THIRD_PARTY,
265                                            /*safeToKill=*/{},
266                                            /*vendorPrefixes=*/{},
267                                            /*packageMetadata=*/{}, ioConfig);
268     TemporaryFile temporaryFile;
269     ASSERT_NE(temporaryFile.fd, -1);
270 
271     ASSERT_RESULT_OK(OveruseConfigurationXmlHelper::writeXmlFile(expected, temporaryFile.path));
272 
273     ALOGW("Wrote to file: %s", temporaryFile.path);
274 
275     auto actual = OveruseConfigurationXmlHelper::parseXmlFile(temporaryFile.path);
276 
277     ASSERT_RESULT_OK(actual);
278 
279     EXPECT_THAT(*actual, ResourceOveruseConfigurationMatcher(expected))
280             << "Expected: " << expected.toString() << "\nActual: " << actual->toString();
281 
282     temporaryFile.release();
283 }
284 
TEST(OveruseConfigurationXmlHelperTest,TestFailsWriteXmlFileWithInvalidConfig)285 TEST(OveruseConfigurationXmlHelperTest, TestFailsWriteXmlFileWithInvalidConfig) {
286     ResourceOveruseConfiguration resourceOveruseConfig;
287     resourceOveruseConfig.componentType = ComponentType::THIRD_PARTY;
288 
289     TemporaryFile temporaryFile;
290     ASSERT_NE(temporaryFile.fd, -1);
291 
292     ASSERT_FALSE(
293             OveruseConfigurationXmlHelper::writeXmlFile(resourceOveruseConfig, temporaryFile.path)
294                     .ok())
295             << "Should fail to write invalid config";
296 
297     temporaryFile.release();
298 }
299 
300 }  // namespace watchdog
301 }  // namespace automotive
302 }  // namespace android
303