1 /*
2  * Copyright (C) 2017 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 <stdio.h>
18 #include <sys/cdefs.h>
19 
20 #include <string>
21 #include <vector>
22 
23 #include <android-base/file.h>
24 #include <android-base/macros.h>
25 #include <android-base/strings.h>
26 #include <android-base/stringprintf.h>
27 #include <gtest/gtest.h>
28 #include <private/android_filesystem_config.h>
29 #include <private/fs_config.h>
30 
31 #include "android_filesystem_config_test_data.h"
32 
33 // must run test in the test directory
34 const static char fs_config_generate_command[] = "./fs_config_generate_test";
35 
36 static std::string popenToString(std::string command) {
37   std::string ret;
38 
39   FILE* fp = popen(command.c_str(), "r");
40   if (fp) {
41     if (!android::base::ReadFdToString(fileno(fp), &ret)) ret = "";
42     pclose(fp);
43   }
44   return ret;
45 }
46 
47 static void confirm(std::string&& data, const fs_path_config* config,
48                     ssize_t num_config) {
49   const struct fs_path_config_from_file* pc =
50       reinterpret_cast<const fs_path_config_from_file*>(data.c_str());
51   size_t len = data.size();
52 
53   ASSERT_TRUE(config != NULL);
54   ASSERT_LT(0, num_config);
55 
56   while (len > 0) {
57     uint16_t host_len = pc->len;
58     if (host_len > len) break;
59 
60     EXPECT_EQ(config->mode, pc->mode);
61     EXPECT_EQ(config->uid, pc->uid);
62     EXPECT_EQ(config->gid, pc->gid);
63     EXPECT_EQ(config->capabilities, pc->capabilities);
64     EXPECT_STREQ(config->prefix, pc->prefix);
65 
66     EXPECT_LT(0, num_config);
67     --num_config;
68     if (num_config >= 0) ++config;
69     pc = reinterpret_cast<const fs_path_config_from_file*>(
70         reinterpret_cast<const char*>(pc) + host_len);
71     len -= host_len;
72   }
73   EXPECT_EQ(0, num_config);
74 }
75 
76 /* See local android_filesystem_config.h for test data */
77 
78 TEST(fs_conf_test, dirs) {
79   confirm(popenToString(
80               android::base::StringPrintf("%s -D", fs_config_generate_command)),
81           android_device_dirs, arraysize(android_device_dirs));
82 }
83 
84 TEST(fs_conf_test, files) {
85   confirm(popenToString(
86               android::base::StringPrintf("%s -F", fs_config_generate_command)),
87           android_device_files, arraysize(android_device_files));
88 }
89 
90 static const char vendor_str[] = "vendor/";
91 static const char vendor_alt_str[] = "system/vendor/";
92 static const char oem_str[] = "oem/";
93 static const char oem_alt_str[] = "system/oem/";
94 static const char odm_str[] = "odm/";
95 static const char odm_alt_str[] = "system/odm/";
96 
97 TEST(fs_conf_test, system_dirs) {
98   std::vector<fs_path_config> dirs;
99   const fs_path_config* config = android_device_dirs;
100   for (size_t num = arraysize(android_device_dirs); num; --num) {
101     if (!android::base::StartsWith(config->prefix, vendor_str) &&
102         !android::base::StartsWith(config->prefix, vendor_alt_str) &&
103         !android::base::StartsWith(config->prefix, oem_str) &&
104         !android::base::StartsWith(config->prefix, oem_alt_str) &&
105         !android::base::StartsWith(config->prefix, odm_str) &&
106         !android::base::StartsWith(config->prefix, odm_alt_str)) {
107       dirs.emplace_back(*config);
108     }
109     ++config;
110   }
111   confirm(popenToString(android::base::StringPrintf(
112               "%s -D -P -vendor,-oem,-odm", fs_config_generate_command)),
113           &dirs[0], dirs.size());
114 }
115 
116 TEST(fs_conf_test, vendor_dirs) {
117   std::vector<fs_path_config> dirs;
118   const fs_path_config* config = android_device_dirs;
119   for (size_t num = arraysize(android_device_dirs); num; --num) {
120     if (android::base::StartsWith(config->prefix, vendor_str) ||
121         android::base::StartsWith(config->prefix, vendor_alt_str)) {
122       dirs.emplace_back(*config);
123     }
124     ++config;
125   }
126   confirm(popenToString(android::base::StringPrintf(
127               "%s -D -P vendor", fs_config_generate_command)),
128           &dirs[0], dirs.size());
129 }
130 
131 TEST(fs_conf_test, oem_dirs) {
132   std::vector<fs_path_config> dirs;
133   const fs_path_config* config = android_device_dirs;
134   for (size_t num = arraysize(android_device_dirs); num; --num) {
135     if (android::base::StartsWith(config->prefix, oem_str) ||
136         android::base::StartsWith(config->prefix, oem_alt_str)) {
137       dirs.emplace_back(*config);
138     }
139     ++config;
140   }
141   confirm(popenToString(android::base::StringPrintf(
142               "%s -D -P oem", fs_config_generate_command)),
143           &dirs[0], dirs.size());
144 }
145 
146 TEST(fs_conf_test, odm_dirs) {
147   std::vector<fs_path_config> dirs;
148   const fs_path_config* config = android_device_dirs;
149   for (size_t num = arraysize(android_device_dirs); num; --num) {
150     if (android::base::StartsWith(config->prefix, odm_str) ||
151         android::base::StartsWith(config->prefix, odm_alt_str)) {
152       dirs.emplace_back(*config);
153     }
154     ++config;
155   }
156   confirm(popenToString(android::base::StringPrintf(
157               "%s -D -P odm", fs_config_generate_command)),
158           &dirs[0], dirs.size());
159 }
160 
161 TEST(fs_conf_test, system_files) {
162   std::vector<fs_path_config> files;
163   const fs_path_config* config = android_device_files;
164   for (size_t num = arraysize(android_device_files); num; --num) {
165     if (!android::base::StartsWith(config->prefix, vendor_str) &&
166         !android::base::StartsWith(config->prefix, vendor_alt_str) &&
167         !android::base::StartsWith(config->prefix, oem_str) &&
168         !android::base::StartsWith(config->prefix, oem_alt_str) &&
169         !android::base::StartsWith(config->prefix, odm_str) &&
170         !android::base::StartsWith(config->prefix, odm_alt_str)) {
171       files.emplace_back(*config);
172     }
173     ++config;
174   }
175   confirm(popenToString(android::base::StringPrintf(
176               "%s -F -P -vendor,-oem,-odm", fs_config_generate_command)),
177           &files[0], files.size());
178 }
179 
180 TEST(fs_conf_test, vendor_files) {
181   std::vector<fs_path_config> files;
182   const fs_path_config* config = android_device_files;
183   for (size_t num = arraysize(android_device_files); num; --num) {
184     if (android::base::StartsWith(config->prefix, vendor_str) ||
185         android::base::StartsWith(config->prefix, vendor_alt_str)) {
186       files.emplace_back(*config);
187     }
188     ++config;
189   }
190   confirm(popenToString(android::base::StringPrintf(
191               "%s -F -P vendor", fs_config_generate_command)),
192           &files[0], files.size());
193 }
194 
195 TEST(fs_conf_test, oem_files) {
196   std::vector<fs_path_config> files;
197   const fs_path_config* config = android_device_files;
198   for (size_t num = arraysize(android_device_files); num; --num) {
199     if (android::base::StartsWith(config->prefix, oem_str) ||
200         android::base::StartsWith(config->prefix, oem_alt_str)) {
201       files.emplace_back(*config);
202     }
203     ++config;
204   }
205   confirm(popenToString(android::base::StringPrintf(
206               "%s -F -P oem", fs_config_generate_command)),
207           &files[0], files.size());
208 }
209 
210 TEST(fs_conf_test, odm_files) {
211   std::vector<fs_path_config> files;
212   const fs_path_config* config = android_device_files;
213   for (size_t num = arraysize(android_device_files); num; --num) {
214     if (android::base::StartsWith(config->prefix, odm_str) ||
215         android::base::StartsWith(config->prefix, odm_alt_str)) {
216       files.emplace_back(*config);
217     }
218     ++config;
219   }
220   confirm(popenToString(android::base::StringPrintf(
221               "%s -F -P odm", fs_config_generate_command)),
222           &files[0], files.size());
223 }
224