blob: 4f8349e2fbb294b3ad36d02393ca149cc0900739 [file] [log] [blame]
Tao Bao0c7839a2016-10-10 15:48:37 -07001/*
2 * Copyright (C) 2016 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
Tao Bao9aa7ab52017-01-05 17:27:19 -080017#include <stdio.h>
Tao Bao89929022016-11-08 20:51:31 -080018#include <sys/stat.h>
19#include <sys/types.h>
20#include <unistd.h>
21
Tao Bao0c7839a2016-10-10 15:48:37 -070022#include <string>
Tianjie Xu56ebe622017-03-16 00:48:21 -070023#include <vector>
Tao Bao0c7839a2016-10-10 15:48:37 -070024
Tao Bao51d516e2016-11-03 14:49:01 -070025#include <android-base/file.h>
Tao Bao0c7839a2016-10-10 15:48:37 -070026#include <android-base/properties.h>
Tao Bao9aa7ab52017-01-05 17:27:19 -080027#include <android-base/stringprintf.h>
28#include <android-base/strings.h>
Tao Bao51d516e2016-11-03 14:49:01 -070029#include <android-base/test_utils.h>
Tao Baobedf5fc2016-11-18 12:01:26 -080030#include <bootloader_message/bootloader_message.h>
Tianjie Xu56ebe622017-03-16 00:48:21 -070031#include <bsdiff.h>
Tao Bao0c7839a2016-10-10 15:48:37 -070032#include <gtest/gtest.h>
Tao Baoef0eb3b2016-11-14 21:29:52 -080033#include <ziparchive/zip_archive.h>
Tianjie Xu56ebe622017-03-16 00:48:21 -070034#include <ziparchive/zip_writer.h>
Tao Bao0c7839a2016-10-10 15:48:37 -070035
Tao Baoef0eb3b2016-11-14 21:29:52 -080036#include "common/test_constants.h"
Tao Bao0c7839a2016-10-10 15:48:37 -070037#include "edify/expr.h"
38#include "error_code.h"
Tianjie Xu56ebe622017-03-16 00:48:21 -070039#include "otautil/SysUtil.h"
40#include "print_sha1.h"
41#include "updater/blockimg.h"
Tao Bao0c7839a2016-10-10 15:48:37 -070042#include "updater/install.h"
Tao Baoef0eb3b2016-11-14 21:29:52 -080043#include "updater/updater.h"
Tao Bao0c7839a2016-10-10 15:48:37 -070044
45struct selabel_handle *sehandle = nullptr;
46
Tao Baoef0eb3b2016-11-14 21:29:52 -080047static void expect(const char* expected, const char* expr_str, CauseCode cause_code,
48 UpdaterInfo* info = nullptr) {
49 Expr* e;
50 int error_count = 0;
51 ASSERT_EQ(0, parse_string(expr_str, &e, &error_count));
52 ASSERT_EQ(0, error_count);
Tao Bao0c7839a2016-10-10 15:48:37 -070053
Tao Baoef0eb3b2016-11-14 21:29:52 -080054 State state(expr_str, info);
Tao Bao0c7839a2016-10-10 15:48:37 -070055
Tao Baoef0eb3b2016-11-14 21:29:52 -080056 std::string result;
57 bool status = Evaluate(&state, e, &result);
Tao Bao0c7839a2016-10-10 15:48:37 -070058
Tao Baoef0eb3b2016-11-14 21:29:52 -080059 if (expected == nullptr) {
60 ASSERT_FALSE(status);
61 } else {
62 ASSERT_TRUE(status);
63 ASSERT_STREQ(expected, result.c_str());
64 }
Tao Bao0c7839a2016-10-10 15:48:37 -070065
Tao Baoef0eb3b2016-11-14 21:29:52 -080066 // Error code is set in updater/updater.cpp only, by parsing State.errmsg.
67 ASSERT_EQ(kNoError, state.error_code);
Tao Bao361342c2016-02-08 11:15:50 -080068
Tao Baoef0eb3b2016-11-14 21:29:52 -080069 // Cause code should always be available.
70 ASSERT_EQ(cause_code, state.cause_code);
Tao Bao0c7839a2016-10-10 15:48:37 -070071}
72
Tianjie Xu56ebe622017-03-16 00:48:21 -070073static std::string get_sha1(const std::string& content) {
74 uint8_t digest[SHA_DIGEST_LENGTH];
75 SHA1(reinterpret_cast<const uint8_t*>(content.c_str()), content.size(), digest);
76 return print_sha1(digest);
77}
78
Tao Bao0c7839a2016-10-10 15:48:37 -070079class UpdaterTest : public ::testing::Test {
Tianjie Xu56ebe622017-03-16 00:48:21 -070080 protected:
81 virtual void SetUp() override {
82 RegisterBuiltins();
83 RegisterInstallFunctions();
84 RegisterBlockImageFunctions();
85 }
Tao Bao0c7839a2016-10-10 15:48:37 -070086};
87
88TEST_F(UpdaterTest, getprop) {
89 expect(android::base::GetProperty("ro.product.device", "").c_str(),
90 "getprop(\"ro.product.device\")",
Tao Bao361342c2016-02-08 11:15:50 -080091 kNoCause);
Tao Bao0c7839a2016-10-10 15:48:37 -070092
93 expect(android::base::GetProperty("ro.build.fingerprint", "").c_str(),
94 "getprop(\"ro.build.fingerprint\")",
Tao Bao361342c2016-02-08 11:15:50 -080095 kNoCause);
Tao Bao0c7839a2016-10-10 15:48:37 -070096
97 // getprop() accepts only one parameter.
Tao Bao361342c2016-02-08 11:15:50 -080098 expect(nullptr, "getprop()", kArgsParsingFailure);
99 expect(nullptr, "getprop(\"arg1\", \"arg2\")", kArgsParsingFailure);
100}
101
102TEST_F(UpdaterTest, sha1_check) {
103 // sha1_check(data) returns the SHA-1 of the data.
104 expect("81fe8bfe87576c3ecb22426f8e57847382917acf", "sha1_check(\"abcd\")", kNoCause);
105 expect("da39a3ee5e6b4b0d3255bfef95601890afd80709", "sha1_check(\"\")", kNoCause);
106
107 // sha1_check(data, sha1_hex, [sha1_hex, ...]) returns the matched SHA-1.
108 expect("81fe8bfe87576c3ecb22426f8e57847382917acf",
109 "sha1_check(\"abcd\", \"81fe8bfe87576c3ecb22426f8e57847382917acf\")",
110 kNoCause);
111
112 expect("81fe8bfe87576c3ecb22426f8e57847382917acf",
113 "sha1_check(\"abcd\", \"wrong_sha1\", \"81fe8bfe87576c3ecb22426f8e57847382917acf\")",
114 kNoCause);
115
116 // Or "" if there's no match.
117 expect("",
118 "sha1_check(\"abcd\", \"wrong_sha1\")",
119 kNoCause);
120
121 expect("",
122 "sha1_check(\"abcd\", \"wrong_sha1\", \"wrong_sha2\")",
123 kNoCause);
124
125 // sha1_check() expects at least one argument.
126 expect(nullptr, "sha1_check()", kArgsParsingFailure);
Tao Bao0c7839a2016-10-10 15:48:37 -0700127}
Tao Bao51d516e2016-11-03 14:49:01 -0700128
129TEST_F(UpdaterTest, file_getprop) {
130 // file_getprop() expects two arguments.
131 expect(nullptr, "file_getprop()", kArgsParsingFailure);
132 expect(nullptr, "file_getprop(\"arg1\")", kArgsParsingFailure);
133 expect(nullptr, "file_getprop(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
134
135 // File doesn't exist.
136 expect(nullptr, "file_getprop(\"/doesntexist\", \"key1\")", kFileGetPropFailure);
137
138 // Reject too large files (current limit = 65536).
139 TemporaryFile temp_file1;
140 std::string buffer(65540, '\0');
141 ASSERT_TRUE(android::base::WriteStringToFile(buffer, temp_file1.path));
142
143 // Read some keys.
144 TemporaryFile temp_file2;
145 std::string content("ro.product.name=tardis\n"
146 "# comment\n\n\n"
147 "ro.product.model\n"
148 "ro.product.board = magic \n");
149 ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file2.path));
150
151 std::string script1("file_getprop(\"" + std::string(temp_file2.path) +
152 "\", \"ro.product.name\")");
153 expect("tardis", script1.c_str(), kNoCause);
154
155 std::string script2("file_getprop(\"" + std::string(temp_file2.path) +
156 "\", \"ro.product.board\")");
157 expect("magic", script2.c_str(), kNoCause);
158
159 // No match.
160 std::string script3("file_getprop(\"" + std::string(temp_file2.path) +
161 "\", \"ro.product.wrong\")");
162 expect("", script3.c_str(), kNoCause);
163
164 std::string script4("file_getprop(\"" + std::string(temp_file2.path) +
165 "\", \"ro.product.name=\")");
166 expect("", script4.c_str(), kNoCause);
167
168 std::string script5("file_getprop(\"" + std::string(temp_file2.path) +
169 "\", \"ro.product.nam\")");
170 expect("", script5.c_str(), kNoCause);
171
172 std::string script6("file_getprop(\"" + std::string(temp_file2.path) +
173 "\", \"ro.product.model\")");
174 expect("", script6.c_str(), kNoCause);
175}
Tao Bao0831d0b2016-11-03 23:25:04 -0700176
Tao Bao1036d362016-11-17 22:49:56 -0800177TEST_F(UpdaterTest, package_extract_dir) {
178 // package_extract_dir expects 2 arguments.
179 expect(nullptr, "package_extract_dir()", kArgsParsingFailure);
180 expect(nullptr, "package_extract_dir(\"arg1\")", kArgsParsingFailure);
181 expect(nullptr, "package_extract_dir(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
182
183 std::string zip_path = from_testdata_base("ziptest_valid.zip");
184 ZipArchiveHandle handle;
185 ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
186
187 // Need to set up the ziphandle.
188 UpdaterInfo updater_info;
189 updater_info.package_zip = handle;
190
191 // Extract "b/c.txt" and "b/d.txt" with package_extract_dir("b", "<dir>").
192 TemporaryDir td;
193 std::string temp_dir(td.path);
194 std::string script("package_extract_dir(\"b\", \"" + temp_dir + "\")");
195 expect("t", script.c_str(), kNoCause, &updater_info);
196
197 // Verify.
198 std::string data;
199 std::string file_c = temp_dir + "/c.txt";
200 ASSERT_TRUE(android::base::ReadFileToString(file_c, &data));
201 ASSERT_EQ(kCTxtContents, data);
202
203 std::string file_d = temp_dir + "/d.txt";
204 ASSERT_TRUE(android::base::ReadFileToString(file_d, &data));
205 ASSERT_EQ(kDTxtContents, data);
206
207 // Modify the contents in order to retry. It's expected to be overwritten.
208 ASSERT_TRUE(android::base::WriteStringToFile("random", file_c));
209 ASSERT_TRUE(android::base::WriteStringToFile("random", file_d));
210
211 // Extract again and verify.
212 expect("t", script.c_str(), kNoCause, &updater_info);
213
214 ASSERT_TRUE(android::base::ReadFileToString(file_c, &data));
215 ASSERT_EQ(kCTxtContents, data);
216 ASSERT_TRUE(android::base::ReadFileToString(file_d, &data));
217 ASSERT_EQ(kDTxtContents, data);
218
219 // Clean up the temp files under td.
220 ASSERT_EQ(0, unlink(file_c.c_str()));
221 ASSERT_EQ(0, unlink(file_d.c_str()));
222
223 // Extracting "b/" (with slash) should give the same result.
224 script = "package_extract_dir(\"b/\", \"" + temp_dir + "\")";
225 expect("t", script.c_str(), kNoCause, &updater_info);
226
227 ASSERT_TRUE(android::base::ReadFileToString(file_c, &data));
228 ASSERT_EQ(kCTxtContents, data);
229 ASSERT_TRUE(android::base::ReadFileToString(file_d, &data));
230 ASSERT_EQ(kDTxtContents, data);
231
232 ASSERT_EQ(0, unlink(file_c.c_str()));
233 ASSERT_EQ(0, unlink(file_d.c_str()));
234
235 // Extracting "" is allowed. The entries will carry the path name.
236 script = "package_extract_dir(\"\", \"" + temp_dir + "\")";
237 expect("t", script.c_str(), kNoCause, &updater_info);
238
239 std::string file_a = temp_dir + "/a.txt";
240 ASSERT_TRUE(android::base::ReadFileToString(file_a, &data));
241 ASSERT_EQ(kATxtContents, data);
242 std::string file_b = temp_dir + "/b.txt";
243 ASSERT_TRUE(android::base::ReadFileToString(file_b, &data));
244 ASSERT_EQ(kBTxtContents, data);
245 std::string file_b_c = temp_dir + "/b/c.txt";
246 ASSERT_TRUE(android::base::ReadFileToString(file_b_c, &data));
247 ASSERT_EQ(kCTxtContents, data);
248 std::string file_b_d = temp_dir + "/b/d.txt";
249 ASSERT_TRUE(android::base::ReadFileToString(file_b_d, &data));
250 ASSERT_EQ(kDTxtContents, data);
251
252 ASSERT_EQ(0, unlink(file_a.c_str()));
253 ASSERT_EQ(0, unlink(file_b.c_str()));
254 ASSERT_EQ(0, unlink(file_b_c.c_str()));
255 ASSERT_EQ(0, unlink(file_b_d.c_str()));
256 ASSERT_EQ(0, rmdir((temp_dir + "/b").c_str()));
257
258 // Extracting non-existent entry should still give "t".
259 script = "package_extract_dir(\"doesntexist\", \"" + temp_dir + "\")";
260 expect("t", script.c_str(), kNoCause, &updater_info);
261
262 // Only relative zip_path is allowed.
263 script = "package_extract_dir(\"/b\", \"" + temp_dir + "\")";
264 expect("", script.c_str(), kNoCause, &updater_info);
265
266 // Only absolute dest_path is allowed.
267 script = "package_extract_dir(\"b\", \"path\")";
268 expect("", script.c_str(), kNoCause, &updater_info);
269
270 CloseArchive(handle);
271}
272
Tao Baoef0eb3b2016-11-14 21:29:52 -0800273// TODO: Test extracting to block device.
274TEST_F(UpdaterTest, package_extract_file) {
275 // package_extract_file expects 1 or 2 arguments.
276 expect(nullptr, "package_extract_file()", kArgsParsingFailure);
277 expect(nullptr, "package_extract_file(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
278
279 std::string zip_path = from_testdata_base("ziptest_valid.zip");
280 ZipArchiveHandle handle;
281 ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
282
283 // Need to set up the ziphandle.
284 UpdaterInfo updater_info;
285 updater_info.package_zip = handle;
286
287 // Two-argument version.
288 TemporaryFile temp_file1;
289 std::string script("package_extract_file(\"a.txt\", \"" + std::string(temp_file1.path) + "\")");
290 expect("t", script.c_str(), kNoCause, &updater_info);
291
292 // Verify the extracted entry.
293 std::string data;
294 ASSERT_TRUE(android::base::ReadFileToString(temp_file1.path, &data));
295 ASSERT_EQ(kATxtContents, data);
296
297 // Now extract another entry to the same location, which should overwrite.
298 script = "package_extract_file(\"b.txt\", \"" + std::string(temp_file1.path) + "\")";
299 expect("t", script.c_str(), kNoCause, &updater_info);
300
301 ASSERT_TRUE(android::base::ReadFileToString(temp_file1.path, &data));
302 ASSERT_EQ(kBTxtContents, data);
303
304 // Missing zip entry. The two-argument version doesn't abort.
305 script = "package_extract_file(\"doesntexist\", \"" + std::string(temp_file1.path) + "\")";
306 expect("", script.c_str(), kNoCause, &updater_info);
307
308 // Extract to /dev/full should fail.
309 script = "package_extract_file(\"a.txt\", \"/dev/full\")";
310 expect("", script.c_str(), kNoCause, &updater_info);
311
312 // One-argument version.
313 script = "sha1_check(package_extract_file(\"a.txt\"))";
314 expect(kATxtSha1Sum.c_str(), script.c_str(), kNoCause, &updater_info);
315
316 script = "sha1_check(package_extract_file(\"b.txt\"))";
317 expect(kBTxtSha1Sum.c_str(), script.c_str(), kNoCause, &updater_info);
318
319 // Missing entry. The one-argument version aborts the evaluation.
320 script = "package_extract_file(\"doesntexist\")";
321 expect(nullptr, script.c_str(), kPackageExtractFileFailure, &updater_info);
322
323 CloseArchive(handle);
324}
Tao Baod0f30882016-11-03 23:52:01 -0700325
326TEST_F(UpdaterTest, write_value) {
327 // write_value() expects two arguments.
328 expect(nullptr, "write_value()", kArgsParsingFailure);
329 expect(nullptr, "write_value(\"arg1\")", kArgsParsingFailure);
330 expect(nullptr, "write_value(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
331
332 // filename cannot be empty.
333 expect(nullptr, "write_value(\"value\", \"\")", kArgsParsingFailure);
334
335 // Write some value to file.
336 TemporaryFile temp_file;
337 std::string value = "magicvalue";
338 std::string script("write_value(\"" + value + "\", \"" + std::string(temp_file.path) + "\")");
339 expect("t", script.c_str(), kNoCause);
340
341 // Verify the content.
342 std::string content;
343 ASSERT_TRUE(android::base::ReadFileToString(temp_file.path, &content));
344 ASSERT_EQ(value, content);
345
346 // Allow writing empty string.
347 script = "write_value(\"\", \"" + std::string(temp_file.path) + "\")";
348 expect("t", script.c_str(), kNoCause);
349
350 // Verify the content.
351 ASSERT_TRUE(android::base::ReadFileToString(temp_file.path, &content));
352 ASSERT_EQ("", content);
353
354 // It should fail gracefully when write fails.
355 script = "write_value(\"value\", \"/proc/0/file1\")";
356 expect("", script.c_str(), kNoCause);
357}
Tao Baobedf5fc2016-11-18 12:01:26 -0800358
359TEST_F(UpdaterTest, get_stage) {
360 // get_stage() expects one argument.
361 expect(nullptr, "get_stage()", kArgsParsingFailure);
362 expect(nullptr, "get_stage(\"arg1\", \"arg2\")", kArgsParsingFailure);
363 expect(nullptr, "get_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
364
365 // Set up a local file as BCB.
366 TemporaryFile tf;
367 std::string temp_file(tf.path);
368 bootloader_message boot;
369 strlcpy(boot.stage, "2/3", sizeof(boot.stage));
370 std::string err;
371 ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err));
372
373 // Can read the stage value.
374 std::string script("get_stage(\"" + temp_file + "\")");
375 expect("2/3", script.c_str(), kNoCause);
376
377 // Bad BCB path.
378 script = "get_stage(\"doesntexist\")";
379 expect("", script.c_str(), kNoCause);
380}
381
382TEST_F(UpdaterTest, set_stage) {
383 // set_stage() expects two arguments.
384 expect(nullptr, "set_stage()", kArgsParsingFailure);
385 expect(nullptr, "set_stage(\"arg1\")", kArgsParsingFailure);
386 expect(nullptr, "set_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
387
388 // Set up a local file as BCB.
389 TemporaryFile tf;
390 std::string temp_file(tf.path);
391 bootloader_message boot;
392 strlcpy(boot.command, "command", sizeof(boot.command));
393 strlcpy(boot.stage, "2/3", sizeof(boot.stage));
394 std::string err;
395 ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err));
396
397 // Write with set_stage().
398 std::string script("set_stage(\"" + temp_file + "\", \"1/3\")");
399 expect(tf.path, script.c_str(), kNoCause);
400
401 // Verify.
402 bootloader_message boot_verify;
403 ASSERT_TRUE(read_bootloader_message_from(&boot_verify, temp_file, &err));
404
405 // Stage should be updated, with command part untouched.
406 ASSERT_STREQ("1/3", boot_verify.stage);
407 ASSERT_STREQ(boot.command, boot_verify.command);
408
409 // Bad BCB path.
410 script = "set_stage(\"doesntexist\", \"1/3\")";
411 expect("", script.c_str(), kNoCause);
412
413 script = "set_stage(\"/dev/full\", \"1/3\")";
414 expect("", script.c_str(), kNoCause);
415}
Tao Bao9aa7ab52017-01-05 17:27:19 -0800416
417TEST_F(UpdaterTest, set_progress) {
418 // set_progress() expects one argument.
419 expect(nullptr, "set_progress()", kArgsParsingFailure);
420 expect(nullptr, "set_progress(\"arg1\", \"arg2\")", kArgsParsingFailure);
421
422 // Invalid progress argument.
423 expect(nullptr, "set_progress(\"arg1\")", kArgsParsingFailure);
424 expect(nullptr, "set_progress(\"3x+5\")", kArgsParsingFailure);
425 expect(nullptr, "set_progress(\".3.5\")", kArgsParsingFailure);
426
427 TemporaryFile tf;
428 UpdaterInfo updater_info;
429 updater_info.cmd_pipe = fdopen(tf.fd, "w");
430 expect(".52", "set_progress(\".52\")", kNoCause, &updater_info);
431 fflush(updater_info.cmd_pipe);
432
433 std::string cmd;
434 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &cmd));
435 ASSERT_EQ(android::base::StringPrintf("set_progress %f\n", .52), cmd);
436 // recovery-updater protocol expects 2 tokens ("set_progress <frac>").
437 ASSERT_EQ(2U, android::base::Split(cmd, " ").size());
438}
439
440TEST_F(UpdaterTest, show_progress) {
441 // show_progress() expects two arguments.
442 expect(nullptr, "show_progress()", kArgsParsingFailure);
443 expect(nullptr, "show_progress(\"arg1\")", kArgsParsingFailure);
444 expect(nullptr, "show_progress(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
445
446 // Invalid progress arguments.
447 expect(nullptr, "show_progress(\"arg1\", \"arg2\")", kArgsParsingFailure);
448 expect(nullptr, "show_progress(\"3x+5\", \"10\")", kArgsParsingFailure);
449 expect(nullptr, "show_progress(\".3\", \"5a\")", kArgsParsingFailure);
450
451 TemporaryFile tf;
452 UpdaterInfo updater_info;
453 updater_info.cmd_pipe = fdopen(tf.fd, "w");
454 expect(".52", "show_progress(\".52\", \"10\")", kNoCause, &updater_info);
455 fflush(updater_info.cmd_pipe);
456
457 std::string cmd;
458 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &cmd));
459 ASSERT_EQ(android::base::StringPrintf("progress %f %d\n", .52, 10), cmd);
460 // recovery-updater protocol expects 3 tokens ("progress <frac> <secs>").
461 ASSERT_EQ(3U, android::base::Split(cmd, " ").size());
462}
Tianjie Xu56ebe622017-03-16 00:48:21 -0700463
464TEST_F(UpdaterTest, block_image_update) {
465 // Create a zip file with new_data and patch_data.
466 TemporaryFile zip_file;
467 FILE* zip_file_ptr = fdopen(zip_file.fd, "wb");
468 ZipWriter zip_writer(zip_file_ptr);
469
470 // Add a dummy new data.
471 ASSERT_EQ(0, zip_writer.StartEntry("new_data", 0));
472 ASSERT_EQ(0, zip_writer.FinishEntry());
473
474 // Generate and add the patch data.
475 std::string src_content = std::string(4096, 'a') + std::string(4096, 'c');
476 std::string tgt_content = std::string(4096, 'b') + std::string(4096, 'd');
477 TemporaryFile patch_file;
478 ASSERT_EQ(0, bsdiff::bsdiff(reinterpret_cast<const uint8_t*>(src_content.data()),
479 src_content.size(), reinterpret_cast<const uint8_t*>(tgt_content.data()),
480 tgt_content.size(), patch_file.path, nullptr));
481 std::string patch_content;
482 ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch_content));
483 ASSERT_EQ(0, zip_writer.StartEntry("patch_data", 0));
484 ASSERT_EQ(0, zip_writer.WriteBytes(patch_content.data(), patch_content.size()));
485 ASSERT_EQ(0, zip_writer.FinishEntry());
486
487 // Add two transfer lists. The first one contains a bsdiff; and we expect the update to succeed.
488 std::string src_hash = get_sha1(src_content);
489 std::string tgt_hash = get_sha1(tgt_content);
490 std::vector<std::string> transfer_list = {
491 "4",
492 "2",
493 "0",
494 "2",
495 "stash " + src_hash + " 2,0,2",
496 android::base::StringPrintf("bsdiff 0 %zu %s %s 2,0,2 2 - %s:2,0,2", patch_content.size(),
497 src_hash.c_str(), tgt_hash.c_str(), src_hash.c_str()),
498 "free " + src_hash,
499 };
500 ASSERT_EQ(0, zip_writer.StartEntry("transfer_list", 0));
501 std::string commands = android::base::Join(transfer_list, '\n');
502 ASSERT_EQ(0, zip_writer.WriteBytes(commands.data(), commands.size()));
503 ASSERT_EQ(0, zip_writer.FinishEntry());
504
505 // Stash and free some blocks, then fail the 2nd update intentionally.
506 std::vector<std::string> fail_transfer_list = {
507 "4",
508 "2",
509 "0",
510 "2",
511 "stash " + tgt_hash + " 2,0,2",
512 "free " + tgt_hash,
513 "fail",
514 };
515 ASSERT_EQ(0, zip_writer.StartEntry("fail_transfer_list", 0));
516 std::string fail_commands = android::base::Join(fail_transfer_list, '\n');
517 ASSERT_EQ(0, zip_writer.WriteBytes(fail_commands.data(), fail_commands.size()));
518 ASSERT_EQ(0, zip_writer.FinishEntry());
519 ASSERT_EQ(0, zip_writer.Finish());
520 ASSERT_EQ(0, fclose(zip_file_ptr));
521
522 MemMapping map;
523 ASSERT_EQ(0, sysMapFile(zip_file.path, &map));
524 ZipArchiveHandle handle;
525 ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));
526
527 // Set up the handler, command_pipe, patch offset & length.
528 UpdaterInfo updater_info;
529 updater_info.package_zip = handle;
530 TemporaryFile temp_pipe;
531 updater_info.cmd_pipe = fopen(temp_pipe.path, "wb");
532 updater_info.package_zip_addr = map.addr;
533 updater_info.package_zip_len = map.length;
534
535 // Execute the commands in the 1st transfer list.
536 TemporaryFile update_file;
537 ASSERT_TRUE(android::base::WriteStringToFile(src_content, update_file.path));
538 std::string script = "block_image_update(\"" + std::string(update_file.path) +
539 R"(", package_extract_file("transfer_list"), "new_data", "patch_data"))";
540 expect("t", script.c_str(), kNoCause, &updater_info);
541 // The update_file should be patched correctly.
542 std::string updated_content;
543 ASSERT_TRUE(android::base::ReadFileToString(update_file.path, &updated_content));
544 ASSERT_EQ(tgt_hash, get_sha1(updated_content));
545
546 // Expect the 2nd update to fail, but expect the stashed blocks to be freed.
547 script = "block_image_update(\"" + std::string(update_file.path) +
548 R"(", package_extract_file("fail_transfer_list"), "new_data", "patch_data"))";
549 expect("", script.c_str(), kNoCause, &updater_info);
550 // Updater generates the stash name based on the input file name.
551 std::string name_digest = get_sha1(update_file.path);
552 std::string stash_base = "/cache/recovery/" + name_digest;
553 ASSERT_EQ(0, access(stash_base.c_str(), F_OK));
554 ASSERT_EQ(-1, access((stash_base + tgt_hash).c_str(), F_OK));
555 ASSERT_EQ(0, rmdir(stash_base.c_str()));
556
557 ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
558 CloseArchive(handle);
559}