blob: cfe5361c6737c6496893f038dd41c9d1582a6a9c [file] [log] [blame]
Mårten Kongstad02751232018-04-27 13:16:32 +02001/*
2 * Copyright (C) 2018 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/*
18 * The tests in this file operate on a higher level than the tests in the other
19 * files. Here, all tests execute the idmap2 binary and only depend on
20 * libidmap2 to verify the output of idmap2.
21 */
22#include <fcntl.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25#include <sys/wait.h>
26#include <unistd.h>
27
28#include <cerrno>
29#include <cstdlib>
30#include <cstring> // strerror
31#include <fstream>
32#include <memory>
33#include <sstream>
34#include <string>
35#include <vector>
36
37#include "gmock/gmock.h"
38#include "gtest/gtest.h"
39
40#include "androidfw/PosixUtils.h"
41#include "idmap2/FileUtils.h"
42#include "idmap2/Idmap.h"
43
44#include "TestHelpers.h"
45
46using ::android::util::ExecuteBinary;
47using ::testing::NotNull;
48
49namespace android {
50namespace idmap2 {
51
52class Idmap2BinaryTests : public Idmap2Tests {};
53
Mårten Kongstad744ccfe2018-12-20 14:56:14 +010054namespace {
55
56void AssertIdmap(const Idmap& idmap, const std::string& target_apk_path,
57 const std::string& overlay_apk_path) {
Mårten Kongstad02751232018-04-27 13:16:32 +020058 // check that the idmap file looks reasonable (IdmapTests is responsible for
59 // more in-depth verification)
60 ASSERT_EQ(idmap.GetHeader()->GetMagic(), kIdmapMagic);
61 ASSERT_EQ(idmap.GetHeader()->GetVersion(), kIdmapCurrentVersion);
62 ASSERT_EQ(idmap.GetHeader()->GetTargetPath(), target_apk_path);
63 ASSERT_EQ(idmap.GetHeader()->GetOverlayPath(), overlay_apk_path);
64 ASSERT_EQ(idmap.GetData().size(), 1u);
65}
66
67#define ASSERT_IDMAP(idmap_ref, target_apk_path, overlay_apk_path) \
68 do { \
69 ASSERT_NO_FATAL_FAILURE(AssertIdmap(idmap_ref, target_apk_path, overlay_apk_path)); \
70 } while (0)
71
Mårten Kongstad744ccfe2018-12-20 14:56:14 +010072} // namespace
73
Mårten Kongstad02751232018-04-27 13:16:32 +020074TEST_F(Idmap2BinaryTests, Create) {
75 // clang-format off
76 auto result = ExecuteBinary({"idmap2",
77 "create",
78 "--target-apk-path", GetTargetApkPath(),
79 "--overlay-apk-path", GetOverlayApkPath(),
80 "--idmap-path", GetIdmapPath()});
81 // clang-format on
82 ASSERT_THAT(result, NotNull());
83 ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
84
85 struct stat st;
86 ASSERT_EQ(stat(GetIdmapPath().c_str(), &st), 0);
87
88 std::stringstream error;
89 std::ifstream fin(GetIdmapPath());
90 std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(fin, error);
91 fin.close();
92
93 ASSERT_THAT(idmap, NotNull());
94 ASSERT_IDMAP(*idmap, GetTargetApkPath(), GetOverlayApkPath());
95
96 unlink(GetIdmapPath().c_str());
97}
98
99TEST_F(Idmap2BinaryTests, Dump) {
100 // clang-format off
101 auto result = ExecuteBinary({"idmap2",
102 "create",
103 "--target-apk-path", GetTargetApkPath(),
104 "--overlay-apk-path", GetOverlayApkPath(),
105 "--idmap-path", GetIdmapPath()});
106 // clang-format on
107 ASSERT_THAT(result, NotNull());
108 ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
109
110 // clang-format off
111 result = ExecuteBinary({"idmap2",
112 "dump",
113 "--idmap-path", GetIdmapPath()});
114 // clang-format on
115 ASSERT_THAT(result, NotNull());
116 ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
117 ASSERT_NE(result->stdout.find("0x7f010000 -> 0x7f010000 integer/int1"), std::string::npos);
118 ASSERT_NE(result->stdout.find("0x7f020003 -> 0x7f020000 string/str1"), std::string::npos);
119 ASSERT_NE(result->stdout.find("0x7f020005 -> 0x7f020001 string/str3"), std::string::npos);
120 ASSERT_EQ(result->stdout.find("00000210: 007f target package id"), std::string::npos);
121
122 // clang-format off
123 result = ExecuteBinary({"idmap2",
124 "dump",
125 "--verbose",
126 "--idmap-path", GetIdmapPath()});
127 // clang-format on
128 ASSERT_THAT(result, NotNull());
129 ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
130 ASSERT_NE(result->stdout.find("00000000: 504d4449 magic"), std::string::npos);
131 ASSERT_NE(result->stdout.find("00000210: 007f target package id"), std::string::npos);
132
133 // clang-format off
134 result = ExecuteBinary({"idmap2",
135 "dump",
136 "--verbose",
137 "--idmap-path", GetTestDataPath() + "/DOES-NOT-EXIST"});
138 // clang-format on
139 ASSERT_THAT(result, NotNull());
140 ASSERT_NE(result->status, EXIT_SUCCESS);
141
142 unlink(GetIdmapPath().c_str());
143}
144
145TEST_F(Idmap2BinaryTests, Scan) {
146 const std::string overlay_static_1_apk_path = GetTestDataPath() + "/overlay/overlay-static-1.apk";
147 const std::string overlay_static_2_apk_path = GetTestDataPath() + "/overlay/overlay-static-2.apk";
148 const std::string idmap_static_1_path =
149 Idmap::CanonicalIdmapPathFor(GetTempDirPath(), overlay_static_1_apk_path);
150 const std::string idmap_static_2_path =
151 Idmap::CanonicalIdmapPathFor(GetTempDirPath(), overlay_static_2_apk_path);
152
153 // single input directory, recursive
154 // clang-format off
155 auto result = ExecuteBinary({"idmap2",
156 "scan",
157 "--input-directory", GetTestDataPath(),
158 "--recursive",
159 "--target-package-name", "test.target",
160 "--target-apk-path", GetTargetApkPath(),
161 "--output-directory", GetTempDirPath()});
162 // clang-format on
163 ASSERT_THAT(result, NotNull());
164 ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
165 std::stringstream expected;
166 expected << idmap_static_1_path << std::endl;
167 expected << idmap_static_2_path << std::endl;
168 ASSERT_EQ(result->stdout, expected.str());
169
170 std::stringstream error;
171 auto idmap_static_1_raw_string = utils::ReadFile(idmap_static_1_path);
172 auto idmap_static_1_raw_stream = std::istringstream(*idmap_static_1_raw_string);
173 auto idmap_static_1 = Idmap::FromBinaryStream(idmap_static_1_raw_stream, error);
174 ASSERT_THAT(idmap_static_1, NotNull());
175 ASSERT_IDMAP(*idmap_static_1, GetTargetApkPath(), overlay_static_1_apk_path);
176
177 auto idmap_static_2_raw_string = utils::ReadFile(idmap_static_2_path);
178 auto idmap_static_2_raw_stream = std::istringstream(*idmap_static_2_raw_string);
179 auto idmap_static_2 = Idmap::FromBinaryStream(idmap_static_2_raw_stream, error);
180 ASSERT_THAT(idmap_static_2, NotNull());
181 ASSERT_IDMAP(*idmap_static_2, GetTargetApkPath(), overlay_static_2_apk_path);
182
183 unlink(idmap_static_2_path.c_str());
184 unlink(idmap_static_1_path.c_str());
185
186 // multiple input directories, non-recursive
187 // clang-format off
188 result = ExecuteBinary({"idmap2",
189 "scan",
190 "--input-directory", GetTestDataPath() + "/target",
191 "--input-directory", GetTestDataPath() + "/overlay",
192 "--target-package-name", "test.target",
193 "--target-apk-path", GetTargetApkPath(),
194 "--output-directory", GetTempDirPath()});
195 // clang-format on
196 ASSERT_THAT(result, NotNull());
197 ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
198 ASSERT_EQ(result->stdout, expected.str());
199 unlink(idmap_static_2_path.c_str());
200 unlink(idmap_static_1_path.c_str());
201
202 // the same input directory given twice, but no duplicate entries
203 // clang-format off
204 result = ExecuteBinary({"idmap2",
205 "scan",
206 "--input-directory", GetTestDataPath(),
207 "--input-directory", GetTestDataPath(),
208 "--recursive",
209 "--target-package-name", "test.target",
210 "--target-apk-path", GetTargetApkPath(),
211 "--output-directory", GetTempDirPath()});
212 // clang-format on
213 ASSERT_THAT(result, NotNull());
214 ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
215 ASSERT_EQ(result->stdout, expected.str());
216 unlink(idmap_static_2_path.c_str());
217 unlink(idmap_static_1_path.c_str());
218
219 // no APKs in input-directory: ok, but no output
220 // clang-format off
221 result = ExecuteBinary({"idmap2",
222 "scan",
223 "--input-directory", GetTempDirPath(),
224 "--target-package-name", "test.target",
225 "--target-apk-path", GetTargetApkPath(),
226 "--output-directory", GetTempDirPath()});
227 // clang-format on
228 ASSERT_THAT(result, NotNull());
229 ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
230 ASSERT_EQ(result->stdout, "");
231}
232
233TEST_F(Idmap2BinaryTests, Lookup) {
234 // clang-format off
235 auto result = ExecuteBinary({"idmap2",
236 "create",
237 "--target-apk-path", GetTargetApkPath(),
238 "--overlay-apk-path", GetOverlayApkPath(),
239 "--idmap-path", GetIdmapPath()});
240 // clang-format on
241 ASSERT_THAT(result, NotNull());
242 ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
243
244 // clang-format off
245 result = ExecuteBinary({"idmap2",
246 "lookup",
247 "--idmap-path", GetIdmapPath(),
248 "--config", "",
249 "--resid", "0x7f020003"}); // string/str1
250 // clang-format on
251 ASSERT_THAT(result, NotNull());
252 ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
253 ASSERT_NE(result->stdout.find("overlay-1"), std::string::npos);
254 ASSERT_EQ(result->stdout.find("overlay-1-sv"), std::string::npos);
255
256 // clang-format off
257 result = ExecuteBinary({"idmap2",
258 "lookup",
259 "--idmap-path", GetIdmapPath(),
260 "--config", "",
261 "--resid", "test.target:string/str1"});
262 // clang-format on
263 ASSERT_THAT(result, NotNull());
264 ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
265 ASSERT_NE(result->stdout.find("overlay-1"), std::string::npos);
266 ASSERT_EQ(result->stdout.find("overlay-1-sv"), std::string::npos);
267
268 // clang-format off
269 result = ExecuteBinary({"idmap2",
270 "lookup",
271 "--idmap-path", GetIdmapPath(),
272 "--config", "sv",
273 "--resid", "test.target:string/str1"});
274 // clang-format on
275 ASSERT_THAT(result, NotNull());
276 ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
277 ASSERT_NE(result->stdout.find("overlay-1-sv"), std::string::npos);
278
279 unlink(GetIdmapPath().c_str());
280}
281
282TEST_F(Idmap2BinaryTests, InvalidCommandLineOptions) {
283 const std::string invalid_target_apk_path = GetTestDataPath() + "/DOES-NOT-EXIST";
284
285 // missing mandatory options
286 // clang-format off
287 auto result = ExecuteBinary({"idmap2",
288 "create"});
289 // clang-format on
290 ASSERT_THAT(result, NotNull());
291 ASSERT_NE(result->status, EXIT_SUCCESS);
292
293 // missing argument to option
294 // clang-format off
295 result = ExecuteBinary({"idmap2",
296 "create",
297 "--target-apk-path", GetTargetApkPath(),
298 "--overlay-apk-path", GetOverlayApkPath(),
299 "--idmap-path"});
300 // clang-format on
301 ASSERT_THAT(result, NotNull());
302 ASSERT_NE(result->status, EXIT_SUCCESS);
303
304 // invalid target apk path
305 // clang-format off
306 result = ExecuteBinary({"idmap2",
307 "create",
308 "--target-apk-path", invalid_target_apk_path,
309 "--overlay-apk-path", GetOverlayApkPath(),
310 "--idmap-path", GetIdmapPath()});
311 // clang-format on
312 ASSERT_THAT(result, NotNull());
313 ASSERT_NE(result->status, EXIT_SUCCESS);
314}
315
316} // namespace idmap2
317} // namespace android