xref: /aosp_15_r20/system/libvintf/xsd/halManifest/vts/ValidateHalManifest.cpp (revision 70a7ec852fcefd15a4fb57f8f183a8b1c3aacb08)
1 /*
2  * Copyright (C) 2019 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 <dirent.h>
18 #include <glob.h>
19 #include <string>
20 
21 #include <android-base/properties.h>
22 #include <android-base/scopeguard.h>
23 #include <android-base/strings.h>
24 #include "utility/ValidateXml.h"
25 
26 using std::string_literals::operator""s;
27 
get_files_in_dirs(const char * dir_path,std::vector<std::string> & files)28 static void get_files_in_dirs(const char* dir_path, std::vector<std::string>& files) {
29     DIR* d;
30     struct dirent* de;
31 
32     d = opendir(dir_path);
33     if (d == nullptr) {
34         return;
35     }
36 
37     while ((de = readdir(d))) {
38         if (de->d_type != DT_REG) {
39             continue;
40         }
41         files.push_back(de->d_name);
42     }
43     closedir(d);
44 }
45 
glob(const std::string & pattern)46 static std::vector<std::string> glob(const std::string& pattern) {
47     glob_t glob_result;
48     auto ret = glob(pattern.c_str(), GLOB_MARK, nullptr, &glob_result);
49     auto guard = android::base::make_scope_guard([&glob_result] { globfree(&glob_result); });
50 
51     std::vector<std::string> files;
52     if (ret == 0) {
53         for (size_t i = 0; i < glob_result.gl_pathc; i++) {
54             files.emplace_back(glob_result.gl_pathv[i]);
55         }
56     }
57     return files;
58 }
59 
TEST(CheckConfig,halManifestValidation)60 TEST(CheckConfig, halManifestValidation) {
61     if (android::base::GetIntProperty("ro.product.first_api_level", INT64_MAX) <= 28) {
62         GTEST_SKIP();
63     }
64 
65     RecordProperty("description",
66                    "Verify that the hal manifest file "
67                    "is valid according to the schema");
68 
69     constexpr const char* xsd = "/data/local/tmp/hal_manifest.xsd";
70 
71     // There may be compatibility matrices in .../etc/vintf. Manifests are only loaded from
72     // manifest.xml and manifest_*.xml, so only check those.
73     std::vector<const char*> vintf_locations = {"/vendor/etc/vintf", "/odm/etc/vintf"};
74     for (const char* dir_path : vintf_locations) {
75         std::vector<std::string> files;
76         get_files_in_dirs(dir_path, files);
77         for (std::string file_name : files) {
78             if (android::base::StartsWith(file_name, "manifest")) {
79                 EXPECT_VALID_XML((dir_path + "/"s + file_name).c_str(), xsd);
80             }
81         }
82     }
83 
84     // .../etc/vintf/manifest should only contain manifest fragments, so all of them must match the
85     // schema.
86     std::vector<const char*> fragment_locations = {"/vendor/etc/vintf/manifest",
87                                                    "/odm/etc/vintf/manifest"};
88     for (const char* dir_path : fragment_locations) {
89         std::vector<std::string> files;
90         get_files_in_dirs(dir_path, files);
91         for (std::string file_name : files) {
92             EXPECT_VALID_XML((dir_path + "/"s + file_name).c_str(), xsd);
93         }
94     }
95 
96     // APEXes contain fragments as well.
97     auto fragments = glob("/apex/*/etc/vintf/*.xml");
98     for (const auto& fragment : fragments) {
99         // Skip /apex/name@version paths to avoid double processing
100         auto parts = android::base::Split(fragment, "/");
101         if (parts.size() < 3 || parts[2].find('@') != std::string::npos) continue;
102         EXPECT_VALID_XML(fragment.c_str(), xsd);
103     }
104 }
105