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