blob: 968196fc0e770c93b7dcd14569475c138af32637 [file] [log] [blame]
Tao Bao1d866052017-04-10 16:55:57 -07001/*
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 agree 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>
Tao Bao00d57572017-05-02 15:48:54 -070018#include <sys/stat.h>
19#include <sys/types.h>
Tao Baof2784b62017-04-19 12:37:12 -070020#include <unistd.h>
Tao Bao1d866052017-04-10 16:55:57 -070021
Tao Baobc4b1fe2017-04-17 16:46:05 -070022#include <string>
23#include <vector>
24
Tao Baof2784b62017-04-19 12:37:12 -070025#include <android-base/file.h>
Tao Baobc4b1fe2017-04-17 16:46:05 -070026#include <android-base/properties.h>
27#include <android-base/strings.h>
Tao Bao1d866052017-04-10 16:55:57 -070028#include <android-base/test_utils.h>
29#include <gtest/gtest.h>
Tao Baof2784b62017-04-19 12:37:12 -070030#include <vintf/VintfObjectRecovery.h>
Tao Bao1d866052017-04-10 16:55:57 -070031#include <ziparchive/zip_archive.h>
32#include <ziparchive/zip_writer.h>
33
34#include "install.h"
Tao Baobc4b1fe2017-04-17 16:46:05 -070035#include "private/install.h"
Tao Bao1d866052017-04-10 16:55:57 -070036
37TEST(InstallTest, verify_package_compatibility_no_entry) {
38 TemporaryFile temp_file;
39 FILE* zip_file = fdopen(temp_file.fd, "w");
40 ZipWriter writer(zip_file);
41 // The archive must have something to be opened correctly.
42 ASSERT_EQ(0, writer.StartEntry("dummy_entry", 0));
43 ASSERT_EQ(0, writer.FinishEntry());
44 ASSERT_EQ(0, writer.Finish());
45 ASSERT_EQ(0, fclose(zip_file));
46
47 // Doesn't contain compatibility zip entry.
48 ZipArchiveHandle zip;
49 ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
50 ASSERT_TRUE(verify_package_compatibility(zip));
51 CloseArchive(zip);
52}
53
54TEST(InstallTest, verify_package_compatibility_invalid_entry) {
55 TemporaryFile temp_file;
56 FILE* zip_file = fdopen(temp_file.fd, "w");
57 ZipWriter writer(zip_file);
58 ASSERT_EQ(0, writer.StartEntry("compatibility.zip", 0));
59 ASSERT_EQ(0, writer.FinishEntry());
60 ASSERT_EQ(0, writer.Finish());
61 ASSERT_EQ(0, fclose(zip_file));
62
63 // Empty compatibility zip entry.
64 ZipArchiveHandle zip;
65 ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
66 ASSERT_FALSE(verify_package_compatibility(zip));
67 CloseArchive(zip);
68}
Tao Baobc4b1fe2017-04-17 16:46:05 -070069
Tao Bao8a7afcc2017-04-18 22:05:50 -070070TEST(InstallTest, read_metadata_from_package_smoke) {
71 TemporaryFile temp_file;
72 FILE* zip_file = fdopen(temp_file.fd, "w");
73 ZipWriter writer(zip_file);
74 ASSERT_EQ(0, writer.StartEntry("META-INF/com/android/metadata", kCompressStored));
75 const std::string content("abcdefg");
76 ASSERT_EQ(0, writer.WriteBytes(content.data(), content.size()));
77 ASSERT_EQ(0, writer.FinishEntry());
78 ASSERT_EQ(0, writer.Finish());
79 ASSERT_EQ(0, fclose(zip_file));
80
81 ZipArchiveHandle zip;
82 ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
83 std::string metadata;
84 ASSERT_TRUE(read_metadata_from_package(zip, &metadata));
85 ASSERT_EQ(content, metadata);
86 CloseArchive(zip);
87
88 TemporaryFile temp_file2;
89 FILE* zip_file2 = fdopen(temp_file2.fd, "w");
90 ZipWriter writer2(zip_file2);
91 ASSERT_EQ(0, writer2.StartEntry("META-INF/com/android/metadata", kCompressDeflated));
92 ASSERT_EQ(0, writer2.WriteBytes(content.data(), content.size()));
93 ASSERT_EQ(0, writer2.FinishEntry());
94 ASSERT_EQ(0, writer2.Finish());
95 ASSERT_EQ(0, fclose(zip_file2));
96
97 ASSERT_EQ(0, OpenArchive(temp_file2.path, &zip));
98 metadata.clear();
99 ASSERT_TRUE(read_metadata_from_package(zip, &metadata));
100 ASSERT_EQ(content, metadata);
101 CloseArchive(zip);
102}
103
104TEST(InstallTest, read_metadata_from_package_no_entry) {
105 TemporaryFile temp_file;
106 FILE* zip_file = fdopen(temp_file.fd, "w");
107 ZipWriter writer(zip_file);
108 ASSERT_EQ(0, writer.StartEntry("dummy_entry", kCompressStored));
109 ASSERT_EQ(0, writer.FinishEntry());
110 ASSERT_EQ(0, writer.Finish());
111 ASSERT_EQ(0, fclose(zip_file));
112
113 ZipArchiveHandle zip;
114 ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
115 std::string metadata;
116 ASSERT_FALSE(read_metadata_from_package(zip, &metadata));
117 CloseArchive(zip);
118}
119
Tao Baof2784b62017-04-19 12:37:12 -0700120TEST(InstallTest, verify_package_compatibility_with_libvintf_malformed_xml) {
121 TemporaryFile compatibility_zip_file;
122 FILE* compatibility_zip = fdopen(compatibility_zip_file.fd, "w");
123 ZipWriter compatibility_zip_writer(compatibility_zip);
124 ASSERT_EQ(0, compatibility_zip_writer.StartEntry("system_manifest.xml", kCompressDeflated));
125 std::string malformed_xml = "malformed";
126 ASSERT_EQ(0, compatibility_zip_writer.WriteBytes(malformed_xml.data(), malformed_xml.size()));
127 ASSERT_EQ(0, compatibility_zip_writer.FinishEntry());
128 ASSERT_EQ(0, compatibility_zip_writer.Finish());
129 ASSERT_EQ(0, fclose(compatibility_zip));
130
131 TemporaryFile temp_file;
132 FILE* zip_file = fdopen(temp_file.fd, "w");
133 ZipWriter writer(zip_file);
134 ASSERT_EQ(0, writer.StartEntry("compatibility.zip", kCompressStored));
135 std::string compatibility_zip_content;
136 ASSERT_TRUE(
137 android::base::ReadFileToString(compatibility_zip_file.path, &compatibility_zip_content));
138 ASSERT_EQ(0,
139 writer.WriteBytes(compatibility_zip_content.data(), compatibility_zip_content.size()));
140 ASSERT_EQ(0, writer.FinishEntry());
141 ASSERT_EQ(0, writer.Finish());
142 ASSERT_EQ(0, fclose(zip_file));
143
144 ZipArchiveHandle zip;
145 ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
146 std::vector<std::string> compatibility_info;
147 compatibility_info.push_back(malformed_xml);
148 // Malformed compatibility zip is expected to be rejected by libvintf. But we defer that to
149 // libvintf.
150 std::string err;
151 bool result =
152 android::vintf::VintfObjectRecovery::CheckCompatibility(compatibility_info, &err) == 0;
153 ASSERT_EQ(result, verify_package_compatibility(zip));
154 CloseArchive(zip);
155}
156
157TEST(InstallTest, verify_package_compatibility_with_libvintf_system_manifest_xml) {
158 static constexpr const char* system_manifest_xml_path = "/system/manifest.xml";
159 if (access(system_manifest_xml_path, R_OK) == -1) {
160 GTEST_LOG_(INFO) << "Test skipped on devices w/o /system/manifest.xml.";
161 return;
162 }
163 std::string system_manifest_xml_content;
164 ASSERT_TRUE(
165 android::base::ReadFileToString(system_manifest_xml_path, &system_manifest_xml_content));
166 TemporaryFile compatibility_zip_file;
167 FILE* compatibility_zip = fdopen(compatibility_zip_file.fd, "w");
168 ZipWriter compatibility_zip_writer(compatibility_zip);
169 ASSERT_EQ(0, compatibility_zip_writer.StartEntry("system_manifest.xml", kCompressDeflated));
170 ASSERT_EQ(0, compatibility_zip_writer.WriteBytes(system_manifest_xml_content.data(),
171 system_manifest_xml_content.size()));
172 ASSERT_EQ(0, compatibility_zip_writer.FinishEntry());
173 ASSERT_EQ(0, compatibility_zip_writer.Finish());
174 ASSERT_EQ(0, fclose(compatibility_zip));
175
176 TemporaryFile temp_file;
177 FILE* zip_file = fdopen(temp_file.fd, "w");
178 ZipWriter writer(zip_file);
179 ASSERT_EQ(0, writer.StartEntry("compatibility.zip", kCompressStored));
180 std::string compatibility_zip_content;
181 ASSERT_TRUE(
182 android::base::ReadFileToString(compatibility_zip_file.path, &compatibility_zip_content));
183 ASSERT_EQ(0,
184 writer.WriteBytes(compatibility_zip_content.data(), compatibility_zip_content.size()));
185 ASSERT_EQ(0, writer.FinishEntry());
186 ASSERT_EQ(0, writer.Finish());
187 ASSERT_EQ(0, fclose(zip_file));
188
189 ZipArchiveHandle zip;
190 ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
191 std::vector<std::string> compatibility_info;
192 compatibility_info.push_back(system_manifest_xml_content);
193 std::string err;
194 bool result =
195 android::vintf::VintfObjectRecovery::CheckCompatibility(compatibility_info, &err) == 0;
196 // Make sure the result is consistent with libvintf library.
197 ASSERT_EQ(result, verify_package_compatibility(zip));
198 CloseArchive(zip);
199}
200
Tao Baobc4b1fe2017-04-17 16:46:05 -0700201TEST(InstallTest, update_binary_command_smoke) {
202#ifdef AB_OTA_UPDATER
203 TemporaryFile temp_file;
204 FILE* zip_file = fdopen(temp_file.fd, "w");
205 ZipWriter writer(zip_file);
206 ASSERT_EQ(0, writer.StartEntry("payload.bin", kCompressStored));
207 ASSERT_EQ(0, writer.FinishEntry());
208 ASSERT_EQ(0, writer.StartEntry("payload_properties.txt", kCompressStored));
209 const std::string properties = "some_properties";
210 ASSERT_EQ(0, writer.WriteBytes(properties.data(), properties.size()));
211 ASSERT_EQ(0, writer.FinishEntry());
212 // A metadata entry is mandatory.
213 ASSERT_EQ(0, writer.StartEntry("META-INF/com/android/metadata", kCompressStored));
214 std::string device = android::base::GetProperty("ro.product.device", "");
215 ASSERT_NE("", device);
216 std::string timestamp = android::base::GetProperty("ro.build.date.utc", "");
217 ASSERT_NE("", timestamp);
218 std::string metadata = android::base::Join(
219 std::vector<std::string>{
220 "ota-type=AB", "pre-device=" + device, "post-timestamp=" + timestamp,
221 },
222 "\n");
223 ASSERT_EQ(0, writer.WriteBytes(metadata.data(), metadata.size()));
224 ASSERT_EQ(0, writer.FinishEntry());
225 ASSERT_EQ(0, writer.Finish());
226 ASSERT_EQ(0, fclose(zip_file));
227
228 ZipArchiveHandle zip;
229 ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
Tao Bao00d57572017-05-02 15:48:54 -0700230 ZipString payload_name("payload.bin");
231 ZipEntry payload_entry;
232 ASSERT_EQ(0, FindEntry(zip, payload_name, &payload_entry));
Tao Baobc4b1fe2017-04-17 16:46:05 -0700233 int status_fd = 10;
Tao Bao00d57572017-05-02 15:48:54 -0700234 std::string package = "/path/to/update.zip";
235 std::string binary_path = "/sbin/update_engine_sideload";
Tao Baobc4b1fe2017-04-17 16:46:05 -0700236 std::vector<std::string> cmd;
Tao Bao00d57572017-05-02 15:48:54 -0700237 ASSERT_EQ(0, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd));
238 ASSERT_EQ(5U, cmd.size());
239 ASSERT_EQ(binary_path, cmd[0]);
240 ASSERT_EQ("--payload=file://" + package, cmd[1]);
241 ASSERT_EQ("--offset=" + std::to_string(payload_entry.offset), cmd[2]);
Tao Baobc4b1fe2017-04-17 16:46:05 -0700242 ASSERT_EQ("--headers=" + properties, cmd[3]);
243 ASSERT_EQ("--status_fd=" + std::to_string(status_fd), cmd[4]);
244 CloseArchive(zip);
245#else
Tao Bao00d57572017-05-02 15:48:54 -0700246 TemporaryFile temp_file;
247 FILE* zip_file = fdopen(temp_file.fd, "w");
248 ZipWriter writer(zip_file);
249 static constexpr const char* UPDATE_BINARY_NAME = "META-INF/com/google/android/update-binary";
250 ASSERT_EQ(0, writer.StartEntry(UPDATE_BINARY_NAME, kCompressStored));
251 ASSERT_EQ(0, writer.FinishEntry());
252 ASSERT_EQ(0, writer.Finish());
253 ASSERT_EQ(0, fclose(zip_file));
254
255 ZipArchiveHandle zip;
256 ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
257 int status_fd = 10;
258 std::string package = "/path/to/update.zip";
259 TemporaryDir td;
260 std::string binary_path = std::string(td.path) + "/update_binary";
261 std::vector<std::string> cmd;
262 ASSERT_EQ(0, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd));
263 ASSERT_EQ(4U, cmd.size());
264 ASSERT_EQ(binary_path, cmd[0]);
265 ASSERT_EQ("3", cmd[1]); // RECOVERY_API_VERSION
266 ASSERT_EQ(std::to_string(status_fd), cmd[2]);
267 ASSERT_EQ(package, cmd[3]);
268 struct stat sb;
269 ASSERT_EQ(0, stat(binary_path.c_str(), &sb));
270 ASSERT_EQ(static_cast<mode_t>(0755), sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
271
272 // With non-zero retry count. update_binary will be removed automatically.
273 cmd.clear();
274 ASSERT_EQ(0, update_binary_command(package, zip, binary_path, 2, status_fd, &cmd));
275 ASSERT_EQ(5U, cmd.size());
276 ASSERT_EQ(binary_path, cmd[0]);
277 ASSERT_EQ("3", cmd[1]); // RECOVERY_API_VERSION
278 ASSERT_EQ(std::to_string(status_fd), cmd[2]);
279 ASSERT_EQ(package, cmd[3]);
280 ASSERT_EQ("retry", cmd[4]);
281 sb = {};
282 ASSERT_EQ(0, stat(binary_path.c_str(), &sb));
283 ASSERT_EQ(static_cast<mode_t>(0755), sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
284
285 CloseArchive(zip);
Tao Baobc4b1fe2017-04-17 16:46:05 -0700286#endif // AB_OTA_UPDATER
287}
288
289TEST(InstallTest, update_binary_command_invalid) {
290#ifdef AB_OTA_UPDATER
291 TemporaryFile temp_file;
292 FILE* zip_file = fdopen(temp_file.fd, "w");
293 ZipWriter writer(zip_file);
294 // Missing payload_properties.txt.
295 ASSERT_EQ(0, writer.StartEntry("payload.bin", kCompressStored));
296 ASSERT_EQ(0, writer.FinishEntry());
297 // A metadata entry is mandatory.
298 ASSERT_EQ(0, writer.StartEntry("META-INF/com/android/metadata", kCompressStored));
299 std::string device = android::base::GetProperty("ro.product.device", "");
300 ASSERT_NE("", device);
301 std::string timestamp = android::base::GetProperty("ro.build.date.utc", "");
302 ASSERT_NE("", timestamp);
303 std::string metadata = android::base::Join(
304 std::vector<std::string>{
305 "ota-type=AB", "pre-device=" + device, "post-timestamp=" + timestamp,
306 },
307 "\n");
308 ASSERT_EQ(0, writer.WriteBytes(metadata.data(), metadata.size()));
309 ASSERT_EQ(0, writer.FinishEntry());
310 ASSERT_EQ(0, writer.Finish());
311 ASSERT_EQ(0, fclose(zip_file));
312
313 ZipArchiveHandle zip;
314 ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
315 int status_fd = 10;
Tao Bao00d57572017-05-02 15:48:54 -0700316 std::string package = "/path/to/update.zip";
317 std::string binary_path = "/sbin/update_engine_sideload";
Tao Baobc4b1fe2017-04-17 16:46:05 -0700318 std::vector<std::string> cmd;
Tao Bao00d57572017-05-02 15:48:54 -0700319 ASSERT_EQ(INSTALL_CORRUPT, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd));
Tao Baobc4b1fe2017-04-17 16:46:05 -0700320 CloseArchive(zip);
321#else
Tao Bao00d57572017-05-02 15:48:54 -0700322 TemporaryFile temp_file;
323 FILE* zip_file = fdopen(temp_file.fd, "w");
324 ZipWriter writer(zip_file);
325 // The archive must have something to be opened correctly.
326 ASSERT_EQ(0, writer.StartEntry("dummy_entry", 0));
327 ASSERT_EQ(0, writer.FinishEntry());
328 ASSERT_EQ(0, writer.Finish());
329 ASSERT_EQ(0, fclose(zip_file));
330
331 // Missing update binary.
332 ZipArchiveHandle zip;
333 ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
334 int status_fd = 10;
335 std::string package = "/path/to/update.zip";
336 TemporaryDir td;
337 std::string binary_path = std::string(td.path) + "/update_binary";
338 std::vector<std::string> cmd;
339 ASSERT_EQ(INSTALL_CORRUPT, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd));
340 CloseArchive(zip);
Tao Baobc4b1fe2017-04-17 16:46:05 -0700341#endif // AB_OTA_UPDATER
342}