• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 
23 #include <algorithm>
24 #include <memory>
25 #include <string>
26 #include <unordered_map>
27 #include <vector>
28 
29 #include <android-base/file.h>
30 #include <android-base/properties.h>
31 #include <android-base/stringprintf.h>
32 #include <android-base/strings.h>
33 #include <android-base/test_utils.h>
34 #include <bootloader_message/bootloader_message.h>
35 #include <brotli/encode.h>
36 #include <bsdiff/bsdiff.h>
37 #include <gtest/gtest.h>
38 #include <ziparchive/zip_archive.h>
39 #include <ziparchive/zip_writer.h>
40 
41 #include "common/test_constants.h"
42 #include "edify/expr.h"
43 #include "otautil/SysUtil.h"
44 #include "otautil/cache_location.h"
45 #include "otautil/error_code.h"
46 #include "otautil/print_sha1.h"
47 #include "updater/blockimg.h"
48 #include "updater/install.h"
49 #include "updater/updater.h"
50 
51 struct selabel_handle *sehandle = nullptr;
52 
expect(const char * expected,const char * expr_str,CauseCode cause_code,UpdaterInfo * info=nullptr)53 static void expect(const char* expected, const char* expr_str, CauseCode cause_code,
54                    UpdaterInfo* info = nullptr) {
55   std::unique_ptr<Expr> e;
56   int error_count = 0;
57   ASSERT_EQ(0, parse_string(expr_str, &e, &error_count));
58   ASSERT_EQ(0, error_count);
59 
60   State state(expr_str, info);
61 
62   std::string result;
63   bool status = Evaluate(&state, e, &result);
64 
65   if (expected == nullptr) {
66     ASSERT_FALSE(status);
67   } else {
68     ASSERT_TRUE(status);
69     ASSERT_STREQ(expected, result.c_str());
70   }
71 
72   // Error code is set in updater/updater.cpp only, by parsing State.errmsg.
73   ASSERT_EQ(kNoError, state.error_code);
74 
75   // Cause code should always be available.
76   ASSERT_EQ(cause_code, state.cause_code);
77 }
78 
BuildUpdatePackage(const std::unordered_map<std::string,std::string> & entries,int fd)79 static void BuildUpdatePackage(const std::unordered_map<std::string, std::string>& entries,
80                                int fd) {
81   FILE* zip_file_ptr = fdopen(fd, "wb");
82   ZipWriter zip_writer(zip_file_ptr);
83 
84   for (const auto& entry : entries) {
85     ASSERT_EQ(0, zip_writer.StartEntry(entry.first.c_str(), 0));
86     if (!entry.second.empty()) {
87       ASSERT_EQ(0, zip_writer.WriteBytes(entry.second.data(), entry.second.size()));
88     }
89     ASSERT_EQ(0, zip_writer.FinishEntry());
90   }
91 
92   ASSERT_EQ(0, zip_writer.Finish());
93   ASSERT_EQ(0, fclose(zip_file_ptr));
94 }
95 
get_sha1(const std::string & content)96 static std::string get_sha1(const std::string& content) {
97   uint8_t digest[SHA_DIGEST_LENGTH];
98   SHA1(reinterpret_cast<const uint8_t*>(content.c_str()), content.size(), digest);
99   return print_sha1(digest);
100 }
101 
102 class UpdaterTest : public ::testing::Test {
103  protected:
SetUp()104   virtual void SetUp() override {
105     RegisterBuiltins();
106     RegisterInstallFunctions();
107     RegisterBlockImageFunctions();
108 
109     // Mock the location of last_command_file.
110     CacheLocation::location().set_cache_temp_source(temp_saved_source_.path);
111     CacheLocation::location().set_last_command_file(temp_last_command_.path);
112     CacheLocation::location().set_stash_directory_base(temp_stash_base_.path);
113   }
114 
115   TemporaryFile temp_saved_source_;
116   TemporaryFile temp_last_command_;
117   TemporaryDir temp_stash_base_;
118 };
119 
TEST_F(UpdaterTest,getprop)120 TEST_F(UpdaterTest, getprop) {
121     expect(android::base::GetProperty("ro.product.device", "").c_str(),
122            "getprop(\"ro.product.device\")",
123            kNoCause);
124 
125     expect(android::base::GetProperty("ro.build.fingerprint", "").c_str(),
126            "getprop(\"ro.build.fingerprint\")",
127            kNoCause);
128 
129     // getprop() accepts only one parameter.
130     expect(nullptr, "getprop()", kArgsParsingFailure);
131     expect(nullptr, "getprop(\"arg1\", \"arg2\")", kArgsParsingFailure);
132 }
133 
TEST_F(UpdaterTest,sha1_check)134 TEST_F(UpdaterTest, sha1_check) {
135     // sha1_check(data) returns the SHA-1 of the data.
136     expect("81fe8bfe87576c3ecb22426f8e57847382917acf", "sha1_check(\"abcd\")", kNoCause);
137     expect("da39a3ee5e6b4b0d3255bfef95601890afd80709", "sha1_check(\"\")", kNoCause);
138 
139     // sha1_check(data, sha1_hex, [sha1_hex, ...]) returns the matched SHA-1.
140     expect("81fe8bfe87576c3ecb22426f8e57847382917acf",
141            "sha1_check(\"abcd\", \"81fe8bfe87576c3ecb22426f8e57847382917acf\")",
142            kNoCause);
143 
144     expect("81fe8bfe87576c3ecb22426f8e57847382917acf",
145            "sha1_check(\"abcd\", \"wrong_sha1\", \"81fe8bfe87576c3ecb22426f8e57847382917acf\")",
146            kNoCause);
147 
148     // Or "" if there's no match.
149     expect("",
150            "sha1_check(\"abcd\", \"wrong_sha1\")",
151            kNoCause);
152 
153     expect("",
154            "sha1_check(\"abcd\", \"wrong_sha1\", \"wrong_sha2\")",
155            kNoCause);
156 
157     // sha1_check() expects at least one argument.
158     expect(nullptr, "sha1_check()", kArgsParsingFailure);
159 }
160 
TEST_F(UpdaterTest,apply_patch_check)161 TEST_F(UpdaterTest, apply_patch_check) {
162   // Zero-argument is not valid.
163   expect(nullptr, "apply_patch_check()", kArgsParsingFailure);
164 
165   // File not found.
166   expect("", "apply_patch_check(\"/doesntexist\")", kNoCause);
167 
168   std::string src_file = from_testdata_base("old.file");
169   std::string src_content;
170   ASSERT_TRUE(android::base::ReadFileToString(src_file, &src_content));
171   size_t src_size = src_content.size();
172   std::string src_hash = get_sha1(src_content);
173 
174   // One-argument with EMMC:file:size:sha1 should pass the check.
175   std::string filename = android::base::Join(
176       std::vector<std::string>{ "EMMC", src_file, std::to_string(src_size), src_hash }, ":");
177   std::string cmd = "apply_patch_check(\"" + filename + "\")";
178   expect("t", cmd.c_str(), kNoCause);
179 
180   // EMMC:file:(size-1):sha1:(size+1):sha1 should fail the check.
181   std::string filename_bad = android::base::Join(
182       std::vector<std::string>{ "EMMC", src_file, std::to_string(src_size - 1), src_hash,
183                                 std::to_string(src_size + 1), src_hash },
184       ":");
185   cmd = "apply_patch_check(\"" + filename_bad + "\")";
186   expect("", cmd.c_str(), kNoCause);
187 
188   // EMMC:file:(size-1):sha1:size:sha1:(size+1):sha1 should pass the check.
189   filename_bad =
190       android::base::Join(std::vector<std::string>{ "EMMC", src_file, std::to_string(src_size - 1),
191                                                     src_hash, std::to_string(src_size), src_hash,
192                                                     std::to_string(src_size + 1), src_hash },
193                           ":");
194   cmd = "apply_patch_check(\"" + filename_bad + "\")";
195   expect("t", cmd.c_str(), kNoCause);
196 
197   // Multiple arguments.
198   cmd = "apply_patch_check(\"" + filename + "\", \"wrong_sha1\", \"wrong_sha2\")";
199   expect("", cmd.c_str(), kNoCause);
200 
201   cmd = "apply_patch_check(\"" + filename + "\", \"wrong_sha1\", \"" + src_hash +
202         "\", \"wrong_sha2\")";
203   expect("t", cmd.c_str(), kNoCause);
204 
205   cmd = "apply_patch_check(\"" + filename_bad + "\", \"wrong_sha1\", \"" + src_hash +
206         "\", \"wrong_sha2\")";
207   expect("t", cmd.c_str(), kNoCause);
208 }
209 
TEST_F(UpdaterTest,file_getprop)210 TEST_F(UpdaterTest, file_getprop) {
211     // file_getprop() expects two arguments.
212     expect(nullptr, "file_getprop()", kArgsParsingFailure);
213     expect(nullptr, "file_getprop(\"arg1\")", kArgsParsingFailure);
214     expect(nullptr, "file_getprop(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
215 
216     // File doesn't exist.
217     expect(nullptr, "file_getprop(\"/doesntexist\", \"key1\")", kFileGetPropFailure);
218 
219     // Reject too large files (current limit = 65536).
220     TemporaryFile temp_file1;
221     std::string buffer(65540, '\0');
222     ASSERT_TRUE(android::base::WriteStringToFile(buffer, temp_file1.path));
223 
224     // Read some keys.
225     TemporaryFile temp_file2;
226     std::string content("ro.product.name=tardis\n"
227                         "# comment\n\n\n"
228                         "ro.product.model\n"
229                         "ro.product.board =  magic \n");
230     ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file2.path));
231 
232     std::string script1("file_getprop(\"" + std::string(temp_file2.path) +
233                        "\", \"ro.product.name\")");
234     expect("tardis", script1.c_str(), kNoCause);
235 
236     std::string script2("file_getprop(\"" + std::string(temp_file2.path) +
237                        "\", \"ro.product.board\")");
238     expect("magic", script2.c_str(), kNoCause);
239 
240     // No match.
241     std::string script3("file_getprop(\"" + std::string(temp_file2.path) +
242                        "\", \"ro.product.wrong\")");
243     expect("", script3.c_str(), kNoCause);
244 
245     std::string script4("file_getprop(\"" + std::string(temp_file2.path) +
246                        "\", \"ro.product.name=\")");
247     expect("", script4.c_str(), kNoCause);
248 
249     std::string script5("file_getprop(\"" + std::string(temp_file2.path) +
250                        "\", \"ro.product.nam\")");
251     expect("", script5.c_str(), kNoCause);
252 
253     std::string script6("file_getprop(\"" + std::string(temp_file2.path) +
254                        "\", \"ro.product.model\")");
255     expect("", script6.c_str(), kNoCause);
256 }
257 
258 // TODO: Test extracting to block device.
TEST_F(UpdaterTest,package_extract_file)259 TEST_F(UpdaterTest, package_extract_file) {
260   // package_extract_file expects 1 or 2 arguments.
261   expect(nullptr, "package_extract_file()", kArgsParsingFailure);
262   expect(nullptr, "package_extract_file(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
263 
264   std::string zip_path = from_testdata_base("ziptest_valid.zip");
265   ZipArchiveHandle handle;
266   ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
267 
268   // Need to set up the ziphandle.
269   UpdaterInfo updater_info;
270   updater_info.package_zip = handle;
271 
272   // Two-argument version.
273   TemporaryFile temp_file1;
274   std::string script("package_extract_file(\"a.txt\", \"" + std::string(temp_file1.path) + "\")");
275   expect("t", script.c_str(), kNoCause, &updater_info);
276 
277   // Verify the extracted entry.
278   std::string data;
279   ASSERT_TRUE(android::base::ReadFileToString(temp_file1.path, &data));
280   ASSERT_EQ(kATxtContents, data);
281 
282   // Now extract another entry to the same location, which should overwrite.
283   script = "package_extract_file(\"b.txt\", \"" + std::string(temp_file1.path) + "\")";
284   expect("t", script.c_str(), kNoCause, &updater_info);
285 
286   ASSERT_TRUE(android::base::ReadFileToString(temp_file1.path, &data));
287   ASSERT_EQ(kBTxtContents, data);
288 
289   // Missing zip entry. The two-argument version doesn't abort.
290   script = "package_extract_file(\"doesntexist\", \"" + std::string(temp_file1.path) + "\")";
291   expect("", script.c_str(), kNoCause, &updater_info);
292 
293   // Extract to /dev/full should fail.
294   script = "package_extract_file(\"a.txt\", \"/dev/full\")";
295   expect("", script.c_str(), kNoCause, &updater_info);
296 
297   // One-argument version.
298   script = "sha1_check(package_extract_file(\"a.txt\"))";
299   expect(kATxtSha1Sum.c_str(), script.c_str(), kNoCause, &updater_info);
300 
301   script = "sha1_check(package_extract_file(\"b.txt\"))";
302   expect(kBTxtSha1Sum.c_str(), script.c_str(), kNoCause, &updater_info);
303 
304   // Missing entry. The one-argument version aborts the evaluation.
305   script = "package_extract_file(\"doesntexist\")";
306   expect(nullptr, script.c_str(), kPackageExtractFileFailure, &updater_info);
307 
308   CloseArchive(handle);
309 }
310 
TEST_F(UpdaterTest,write_value)311 TEST_F(UpdaterTest, write_value) {
312   // write_value() expects two arguments.
313   expect(nullptr, "write_value()", kArgsParsingFailure);
314   expect(nullptr, "write_value(\"arg1\")", kArgsParsingFailure);
315   expect(nullptr, "write_value(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
316 
317   // filename cannot be empty.
318   expect(nullptr, "write_value(\"value\", \"\")", kArgsParsingFailure);
319 
320   // Write some value to file.
321   TemporaryFile temp_file;
322   std::string value = "magicvalue";
323   std::string script("write_value(\"" + value + "\", \"" + std::string(temp_file.path) + "\")");
324   expect("t", script.c_str(), kNoCause);
325 
326   // Verify the content.
327   std::string content;
328   ASSERT_TRUE(android::base::ReadFileToString(temp_file.path, &content));
329   ASSERT_EQ(value, content);
330 
331   // Allow writing empty string.
332   script = "write_value(\"\", \"" + std::string(temp_file.path) + "\")";
333   expect("t", script.c_str(), kNoCause);
334 
335   // Verify the content.
336   ASSERT_TRUE(android::base::ReadFileToString(temp_file.path, &content));
337   ASSERT_EQ("", content);
338 
339   // It should fail gracefully when write fails.
340   script = "write_value(\"value\", \"/proc/0/file1\")";
341   expect("", script.c_str(), kNoCause);
342 }
343 
TEST_F(UpdaterTest,get_stage)344 TEST_F(UpdaterTest, get_stage) {
345   // get_stage() expects one argument.
346   expect(nullptr, "get_stage()", kArgsParsingFailure);
347   expect(nullptr, "get_stage(\"arg1\", \"arg2\")", kArgsParsingFailure);
348   expect(nullptr, "get_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
349 
350   // Set up a local file as BCB.
351   TemporaryFile tf;
352   std::string temp_file(tf.path);
353   bootloader_message boot;
354   strlcpy(boot.stage, "2/3", sizeof(boot.stage));
355   std::string err;
356   ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err));
357 
358   // Can read the stage value.
359   std::string script("get_stage(\"" + temp_file + "\")");
360   expect("2/3", script.c_str(), kNoCause);
361 
362   // Bad BCB path.
363   script = "get_stage(\"doesntexist\")";
364   expect("", script.c_str(), kNoCause);
365 }
366 
TEST_F(UpdaterTest,set_stage)367 TEST_F(UpdaterTest, set_stage) {
368   // set_stage() expects two arguments.
369   expect(nullptr, "set_stage()", kArgsParsingFailure);
370   expect(nullptr, "set_stage(\"arg1\")", kArgsParsingFailure);
371   expect(nullptr, "set_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
372 
373   // Set up a local file as BCB.
374   TemporaryFile tf;
375   std::string temp_file(tf.path);
376   bootloader_message boot;
377   strlcpy(boot.command, "command", sizeof(boot.command));
378   strlcpy(boot.stage, "2/3", sizeof(boot.stage));
379   std::string err;
380   ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err));
381 
382   // Write with set_stage().
383   std::string script("set_stage(\"" + temp_file + "\", \"1/3\")");
384   expect(tf.path, script.c_str(), kNoCause);
385 
386   // Verify.
387   bootloader_message boot_verify;
388   ASSERT_TRUE(read_bootloader_message_from(&boot_verify, temp_file, &err));
389 
390   // Stage should be updated, with command part untouched.
391   ASSERT_STREQ("1/3", boot_verify.stage);
392   ASSERT_STREQ(boot.command, boot_verify.command);
393 
394   // Bad BCB path.
395   script = "set_stage(\"doesntexist\", \"1/3\")";
396   expect("", script.c_str(), kNoCause);
397 
398   script = "set_stage(\"/dev/full\", \"1/3\")";
399   expect("", script.c_str(), kNoCause);
400 }
401 
TEST_F(UpdaterTest,set_progress)402 TEST_F(UpdaterTest, set_progress) {
403   // set_progress() expects one argument.
404   expect(nullptr, "set_progress()", kArgsParsingFailure);
405   expect(nullptr, "set_progress(\"arg1\", \"arg2\")", kArgsParsingFailure);
406 
407   // Invalid progress argument.
408   expect(nullptr, "set_progress(\"arg1\")", kArgsParsingFailure);
409   expect(nullptr, "set_progress(\"3x+5\")", kArgsParsingFailure);
410   expect(nullptr, "set_progress(\".3.5\")", kArgsParsingFailure);
411 
412   TemporaryFile tf;
413   UpdaterInfo updater_info;
414   updater_info.cmd_pipe = fdopen(tf.release(), "w");
415   expect(".52", "set_progress(\".52\")", kNoCause, &updater_info);
416   fflush(updater_info.cmd_pipe);
417 
418   std::string cmd;
419   ASSERT_TRUE(android::base::ReadFileToString(tf.path, &cmd));
420   ASSERT_EQ(android::base::StringPrintf("set_progress %f\n", .52), cmd);
421   // recovery-updater protocol expects 2 tokens ("set_progress <frac>").
422   ASSERT_EQ(2U, android::base::Split(cmd, " ").size());
423   ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
424 }
425 
TEST_F(UpdaterTest,show_progress)426 TEST_F(UpdaterTest, show_progress) {
427   // show_progress() expects two arguments.
428   expect(nullptr, "show_progress()", kArgsParsingFailure);
429   expect(nullptr, "show_progress(\"arg1\")", kArgsParsingFailure);
430   expect(nullptr, "show_progress(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
431 
432   // Invalid progress arguments.
433   expect(nullptr, "show_progress(\"arg1\", \"arg2\")", kArgsParsingFailure);
434   expect(nullptr, "show_progress(\"3x+5\", \"10\")", kArgsParsingFailure);
435   expect(nullptr, "show_progress(\".3\", \"5a\")", kArgsParsingFailure);
436 
437   TemporaryFile tf;
438   UpdaterInfo updater_info;
439   updater_info.cmd_pipe = fdopen(tf.release(), "w");
440   expect(".52", "show_progress(\".52\", \"10\")", kNoCause, &updater_info);
441   fflush(updater_info.cmd_pipe);
442 
443   std::string cmd;
444   ASSERT_TRUE(android::base::ReadFileToString(tf.path, &cmd));
445   ASSERT_EQ(android::base::StringPrintf("progress %f %d\n", .52, 10), cmd);
446   // recovery-updater protocol expects 3 tokens ("progress <frac> <secs>").
447   ASSERT_EQ(3U, android::base::Split(cmd, " ").size());
448   ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
449 }
450 
TEST_F(UpdaterTest,block_image_update_patch_data)451 TEST_F(UpdaterTest, block_image_update_patch_data) {
452   std::string src_content = std::string(4096, 'a') + std::string(4096, 'c');
453   std::string tgt_content = std::string(4096, 'b') + std::string(4096, 'd');
454 
455   // Generate the patch data.
456   TemporaryFile patch_file;
457   ASSERT_EQ(0, bsdiff::bsdiff(reinterpret_cast<const uint8_t*>(src_content.data()),
458       src_content.size(), reinterpret_cast<const uint8_t*>(tgt_content.data()),
459       tgt_content.size(), patch_file.path, nullptr));
460   std::string patch_content;
461   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch_content));
462 
463   // Create the transfer list that contains a bsdiff.
464   std::string src_hash = get_sha1(src_content);
465   std::string tgt_hash = get_sha1(tgt_content);
466   std::vector<std::string> transfer_list = {
467     "4",
468     "2",
469     "0",
470     "2",
471     "stash " + src_hash + " 2,0,2",
472     android::base::StringPrintf("bsdiff 0 %zu %s %s 2,0,2 2 - %s:2,0,2", patch_content.size(),
473                                 src_hash.c_str(), tgt_hash.c_str(), src_hash.c_str()),
474     "free " + src_hash,
475   };
476 
477   std::unordered_map<std::string, std::string> entries = {
478     { "new_data", "" },
479     { "patch_data", patch_content },
480     { "transfer_list", android::base::Join(transfer_list, '\n') },
481   };
482 
483   // Build the update package.
484   TemporaryFile zip_file;
485   BuildUpdatePackage(entries, zip_file.release());
486 
487   MemMapping map;
488   ASSERT_TRUE(map.MapFile(zip_file.path));
489   ZipArchiveHandle handle;
490   ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));
491 
492   // Set up the handler, command_pipe, patch offset & length.
493   UpdaterInfo updater_info;
494   updater_info.package_zip = handle;
495   TemporaryFile temp_pipe;
496   updater_info.cmd_pipe = fdopen(temp_pipe.release(), "wbe");
497   updater_info.package_zip_addr = map.addr;
498   updater_info.package_zip_len = map.length;
499 
500   // Execute the commands in the transfer list.
501   TemporaryFile update_file;
502   ASSERT_TRUE(android::base::WriteStringToFile(src_content, update_file.path));
503   std::string script = "block_image_update(\"" + std::string(update_file.path) +
504       R"(", package_extract_file("transfer_list"), "new_data", "patch_data"))";
505   expect("t", script.c_str(), kNoCause, &updater_info);
506   // The update_file should be patched correctly.
507   std::string updated_content;
508   ASSERT_TRUE(android::base::ReadFileToString(update_file.path, &updated_content));
509   ASSERT_EQ(tgt_hash, get_sha1(updated_content));
510 
511   ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
512   CloseArchive(handle);
513 }
514 
515 TEST_F(UpdaterTest, block_image_update_fail) {
516   std::string src_content(4096 * 2, 'e');
517   std::string src_hash = get_sha1(src_content);
518   // Stash and free some blocks, then fail the update intentionally.
519   std::vector<std::string> transfer_list = {
520     "4", "2", "0", "2", "stash " + src_hash + " 2,0,2", "free " + src_hash, "fail",
521   };
522 
523   // Add a new data of 10 bytes to test the deadlock.
524   std::unordered_map<std::string, std::string> entries = {
525     { "new_data", std::string(10, 0) },
526     { "patch_data", "" },
527     { "transfer_list", android::base::Join(transfer_list, '\n') },
528   };
529 
530   // Build the update package.
531   TemporaryFile zip_file;
532   BuildUpdatePackage(entries, zip_file.release());
533 
534   MemMapping map;
535   ASSERT_TRUE(map.MapFile(zip_file.path));
536   ZipArchiveHandle handle;
537   ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));
538 
539   // Set up the handler, command_pipe, patch offset & length.
540   UpdaterInfo updater_info;
541   updater_info.package_zip = handle;
542   TemporaryFile temp_pipe;
543   updater_info.cmd_pipe = fdopen(temp_pipe.release(), "wbe");
544   updater_info.package_zip_addr = map.addr;
545   updater_info.package_zip_len = map.length;
546 
547   TemporaryFile update_file;
548   ASSERT_TRUE(android::base::WriteStringToFile(src_content, update_file.path));
549   // Expect the stashed blocks to be freed.
550   std::string script = "block_image_update(\"" + std::string(update_file.path) +
551                        R"(", package_extract_file("transfer_list"), "new_data", "patch_data"))";
552   expect("", script.c_str(), kNoCause, &updater_info);
553   // Updater generates the stash name based on the input file name.
554   std::string name_digest = get_sha1(update_file.path);
555   std::string stash_base = std::string(temp_stash_base_.path) + "/" + name_digest;
556   ASSERT_EQ(0, access(stash_base.c_str(), F_OK));
557   ASSERT_EQ(-1, access((stash_base + src_hash).c_str(), F_OK));
558   ASSERT_EQ(0, rmdir(stash_base.c_str()));
559 
560   ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
561   CloseArchive(handle);
562 }
563 
564 TEST_F(UpdaterTest, new_data_over_write) {
565   std::vector<std::string> transfer_list = {
566     "4", "1", "0", "0", "new 2,0,1",
567   };
568 
569   // Write 4096 + 100 bytes of new data.
570   std::unordered_map<std::string, std::string> entries = {
571     { "new_data", std::string(4196, 0) },
572     { "patch_data", "" },
573     { "transfer_list", android::base::Join(transfer_list, '\n') },
574   };
575 
576   // Build the update package.
577   TemporaryFile zip_file;
578   BuildUpdatePackage(entries, zip_file.release());
579 
580   MemMapping map;
581   ASSERT_TRUE(map.MapFile(zip_file.path));
582   ZipArchiveHandle handle;
583   ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));
584 
585   // Set up the handler, command_pipe, patch offset & length.
586   UpdaterInfo updater_info;
587   updater_info.package_zip = handle;
588   TemporaryFile temp_pipe;
589   updater_info.cmd_pipe = fdopen(temp_pipe.release(), "wbe");
590   updater_info.package_zip_addr = map.addr;
591   updater_info.package_zip_len = map.length;
592 
593   TemporaryFile update_file;
594   std::string script = "block_image_update(\"" + std::string(update_file.path) +
595                        R"(", package_extract_file("transfer_list"), "new_data", "patch_data"))";
596   expect("t", script.c_str(), kNoCause, &updater_info);
597 
598   ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
599   CloseArchive(handle);
600 }
601 
602 TEST_F(UpdaterTest, new_data_short_write) {
603   std::vector<std::string> transfer_list = {
604     "4",
605     "1",
606     "0",
607     "0",
608     "new 2,0,1",
609   };
610 
611   std::unordered_map<std::string, std::string> entries = {
612     { "empty_new_data", "" },
613     { "short_new_data", std::string(10, 'a') },
614     { "exact_new_data", std::string(4096, 'a') },
615     { "patch_data", "" },
616     { "transfer_list", android::base::Join(transfer_list, '\n') },
617   };
618 
619   TemporaryFile zip_file;
620   BuildUpdatePackage(entries, zip_file.release());
621 
622   MemMapping map;
623   ASSERT_TRUE(map.MapFile(zip_file.path));
624   ZipArchiveHandle handle;
625   ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));
626 
627   // Set up the handler, command_pipe, patch offset & length.
628   UpdaterInfo updater_info;
629   updater_info.package_zip = handle;
630   TemporaryFile temp_pipe;
631   updater_info.cmd_pipe = fdopen(temp_pipe.release(), "wbe");
632   updater_info.package_zip_addr = map.addr;
633   updater_info.package_zip_len = map.length;
634 
635   // Updater should report the failure gracefully rather than stuck in deadlock.
636   TemporaryFile update_file;
637   std::string script_empty_data = "block_image_update(\"" + std::string(update_file.path) +
638       R"(", package_extract_file("transfer_list"), "empty_new_data", "patch_data"))";
639   expect("", script_empty_data.c_str(), kNoCause, &updater_info);
640 
641   std::string script_short_data = "block_image_update(\"" + std::string(update_file.path) +
642       R"(", package_extract_file("transfer_list"), "short_new_data", "patch_data"))";
643   expect("", script_short_data.c_str(), kNoCause, &updater_info);
644 
645   // Expect to write 1 block of new data successfully.
646   std::string script_exact_data = "block_image_update(\"" + std::string(update_file.path) +
647       R"(", package_extract_file("transfer_list"), "exact_new_data", "patch_data"))";
648   expect("t", script_exact_data.c_str(), kNoCause, &updater_info);
649 
650   ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
651   CloseArchive(handle);
652 }
653 
654 TEST_F(UpdaterTest, brotli_new_data) {
655   auto generator = []() { return rand() % 128; };
656   // Generate 100 blocks of random data.
657   std::string brotli_new_data;
658   brotli_new_data.reserve(4096 * 100);
659   generate_n(back_inserter(brotli_new_data), 4096 * 100, generator);
660 
661   size_t encoded_size = BrotliEncoderMaxCompressedSize(brotli_new_data.size());
662   std::string encoded_data(encoded_size, 0);
663   ASSERT_TRUE(BrotliEncoderCompress(
664       BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW, BROTLI_DEFAULT_MODE, brotli_new_data.size(),
665       reinterpret_cast<const uint8_t*>(brotli_new_data.data()), &encoded_size,
666       reinterpret_cast<uint8_t*>(const_cast<char*>(encoded_data.data()))));
667   encoded_data.resize(encoded_size);
668 
669   // Write a few small chunks of new data, then a large chunk, and finally a few small chunks.
670   // This helps us to catch potential short writes.
671   std::vector<std::string> transfer_list = {
672     "4",
673     "100",
674     "0",
675     "0",
676     "new 2,0,1",
677     "new 2,1,2",
678     "new 4,2,50,50,97",
679     "new 2,97,98",
680     "new 2,98,99",
681     "new 2,99,100",
682   };
683 
684   std::unordered_map<std::string, std::string> entries = {
685     { "new.dat.br", std::move(encoded_data) },
686     { "patch_data", "" },
687     { "transfer_list", android::base::Join(transfer_list, '\n') },
688   };
689 
690   TemporaryFile zip_file;
691   BuildUpdatePackage(entries, zip_file.release());
692 
693   MemMapping map;
694   ASSERT_TRUE(map.MapFile(zip_file.path));
695   ZipArchiveHandle handle;
696   ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));
697 
698   // Set up the handler, command_pipe, patch offset & length.
699   UpdaterInfo updater_info;
700   updater_info.package_zip = handle;
701   TemporaryFile temp_pipe;
702   updater_info.cmd_pipe = fdopen(temp_pipe.release(), "wb");
703   updater_info.package_zip_addr = map.addr;
704   updater_info.package_zip_len = map.length;
705 
706   // Check if we can decompress the new data correctly.
707   TemporaryFile update_file;
708   std::string script_new_data =
709       "block_image_update(\"" + std::string(update_file.path) +
710       R"(", package_extract_file("transfer_list"), "new.dat.br", "patch_data"))";
711   expect("t", script_new_data.c_str(), kNoCause, &updater_info);
712 
713   std::string updated_content;
714   ASSERT_TRUE(android::base::ReadFileToString(update_file.path, &updated_content));
715   ASSERT_EQ(brotli_new_data, updated_content);
716 
717   ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
718   CloseArchive(handle);
719 }
720 
721 TEST_F(UpdaterTest, last_command_update) {
722   std::string last_command_file = CacheLocation::location().last_command_file();
723 
724   std::string block1 = std::string(4096, '1');
725   std::string block2 = std::string(4096, '2');
726   std::string block3 = std::string(4096, '3');
727   std::string block1_hash = get_sha1(block1);
728   std::string block2_hash = get_sha1(block2);
729   std::string block3_hash = get_sha1(block3);
730 
731   // Compose the transfer list to fail the first update.
732   std::vector<std::string> transfer_list_fail = {
733     "4",
734     "2",
735     "0",
736     "2",
737     "stash " + block1_hash + " 2,0,1",
738     "move " + block1_hash + " 2,1,2 1 2,0,1",
739     "stash " + block3_hash + " 2,2,3",
740     "fail",
741   };
742 
743   // Mimic a resumed update with the same transfer commands.
744   std::vector<std::string> transfer_list_continue = {
745     "4",
746     "2",
747     "0",
748     "2",
749     "stash " + block1_hash + " 2,0,1",
750     "move " + block1_hash + " 2,1,2 1 2,0,1",
751     "stash " + block3_hash + " 2,2,3",
752     "move " + block1_hash + " 2,2,3 1 2,0,1",
753   };
754 
755   std::unordered_map<std::string, std::string> entries = {
756     { "new_data", "" },
757     { "patch_data", "" },
758     { "transfer_list_fail", android::base::Join(transfer_list_fail, '\n') },
759     { "transfer_list_continue", android::base::Join(transfer_list_continue, '\n') },
760   };
761 
762   // Build the update package.
763   TemporaryFile zip_file;
764   BuildUpdatePackage(entries, zip_file.release());
765 
766   MemMapping map;
767   ASSERT_TRUE(map.MapFile(zip_file.path));
768   ZipArchiveHandle handle;
769   ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));
770 
771   // Set up the handler, command_pipe, patch offset & length.
772   UpdaterInfo updater_info;
773   updater_info.package_zip = handle;
774   TemporaryFile temp_pipe;
775   updater_info.cmd_pipe = fdopen(temp_pipe.release(), "wbe");
776   updater_info.package_zip_addr = map.addr;
777   updater_info.package_zip_len = map.length;
778 
779   std::string src_content = block1 + block2 + block3;
780   TemporaryFile update_file;
781   ASSERT_TRUE(android::base::WriteStringToFile(src_content, update_file.path));
782   std::string script =
783       "block_image_update(\"" + std::string(update_file.path) +
784       R"(", package_extract_file("transfer_list_fail"), "new_data", "patch_data"))";
785   expect("", script.c_str(), kNoCause, &updater_info);
786 
787   // Expect last_command to contain the last stash command.
788   std::string last_command_content;
789   ASSERT_TRUE(android::base::ReadFileToString(last_command_file.c_str(), &last_command_content));
790   EXPECT_EQ("2\nstash " + block3_hash + " 2,2,3", last_command_content);
791   std::string updated_contents;
792   ASSERT_TRUE(android::base::ReadFileToString(update_file.path, &updated_contents));
793   ASSERT_EQ(block1 + block1 + block3, updated_contents);
794 
795   // Resume the update, expect the first 'move' to be skipped but the second 'move' to be executed.
796   ASSERT_TRUE(android::base::WriteStringToFile(src_content, update_file.path));
797   std::string script_second_update =
798       "block_image_update(\"" + std::string(update_file.path) +
799       R"(", package_extract_file("transfer_list_continue"), "new_data", "patch_data"))";
800   expect("t", script_second_update.c_str(), kNoCause, &updater_info);
801   ASSERT_TRUE(android::base::ReadFileToString(update_file.path, &updated_contents));
802   ASSERT_EQ(block1 + block2 + block1, updated_contents);
803 
804   ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
805   CloseArchive(handle);
806 }
807 
808 TEST_F(UpdaterTest, last_command_update_unresumable) {
809   std::string last_command_file = CacheLocation::location().last_command_file();
810 
811   std::string block1 = std::string(4096, '1');
812   std::string block2 = std::string(4096, '2');
813   std::string block1_hash = get_sha1(block1);
814   std::string block2_hash = get_sha1(block2);
815 
816   // Construct an unresumable update with source blocks mismatch.
817   std::vector<std::string> transfer_list_unresumable = {
818     "4", "2", "0", "2", "stash " + block1_hash + " 2,0,1", "move " + block2_hash + " 2,1,2 1 2,0,1",
819   };
820 
821   std::unordered_map<std::string, std::string> entries = {
822     { "new_data", "" },
823     { "patch_data", "" },
824     { "transfer_list_unresumable", android::base::Join(transfer_list_unresumable, '\n') },
825   };
826 
827   // Build the update package.
828   TemporaryFile zip_file;
829   BuildUpdatePackage(entries, zip_file.release());
830 
831   MemMapping map;
832   ASSERT_TRUE(map.MapFile(zip_file.path));
833   ZipArchiveHandle handle;
834   ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));
835 
836   // Set up the handler, command_pipe, patch offset & length.
837   UpdaterInfo updater_info;
838   updater_info.package_zip = handle;
839   TemporaryFile temp_pipe;
840   updater_info.cmd_pipe = fdopen(temp_pipe.release(), "wbe");
841   updater_info.package_zip_addr = map.addr;
842   updater_info.package_zip_len = map.length;
843 
844   // Set up the last_command_file
845   ASSERT_TRUE(
846       android::base::WriteStringToFile("0\nstash " + block1_hash + " 2,0,1", last_command_file));
847 
848   // The last_command_file will be deleted if the update encounters an unresumable failure
849   // later.
850   std::string src_content = block1 + block1;
851   TemporaryFile update_file;
852   ASSERT_TRUE(android::base::WriteStringToFile(src_content, update_file.path));
853   std::string script =
854       "block_image_update(\"" + std::string(update_file.path) +
855       R"(", package_extract_file("transfer_list_unresumable"), "new_data", "patch_data"))";
856   expect("", script.c_str(), kNoCause, &updater_info);
857   ASSERT_EQ(-1, access(last_command_file.c_str(), R_OK));
858 
859   ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
860   CloseArchive(handle);
861 }
862 
863 TEST_F(UpdaterTest, last_command_verify) {
864   std::string last_command_file = CacheLocation::location().last_command_file();
865 
866   std::string block1 = std::string(4096, '1');
867   std::string block2 = std::string(4096, '2');
868   std::string block3 = std::string(4096, '3');
869   std::string block1_hash = get_sha1(block1);
870   std::string block2_hash = get_sha1(block2);
871   std::string block3_hash = get_sha1(block3);
872 
873   std::vector<std::string> transfer_list_verify = {
874     "4",
875     "2",
876     "0",
877     "2",
878     "stash " + block1_hash + " 2,0,1",
879     "move " + block1_hash + " 2,0,1 1 2,0,1",
880     "move " + block1_hash + " 2,1,2 1 2,0,1",
881     "stash " + block3_hash + " 2,2,3",
882   };
883 
884   std::unordered_map<std::string, std::string> entries = {
885     { "new_data", "" },
886     { "patch_data", "" },
887     { "transfer_list_verify", android::base::Join(transfer_list_verify, '\n') },
888   };
889 
890   // Build the update package.
891   TemporaryFile zip_file;
892   BuildUpdatePackage(entries, zip_file.release());
893 
894   MemMapping map;
895   ASSERT_TRUE(map.MapFile(zip_file.path));
896   ZipArchiveHandle handle;
897   ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));
898 
899   // Set up the handler, command_pipe, patch offset & length.
900   UpdaterInfo updater_info;
901   updater_info.package_zip = handle;
902   TemporaryFile temp_pipe;
903   updater_info.cmd_pipe = fdopen(temp_pipe.release(), "wbe");
904   updater_info.package_zip_addr = map.addr;
905   updater_info.package_zip_len = map.length;
906 
907   std::string src_content = block1 + block1 + block3;
908   TemporaryFile update_file;
909   ASSERT_TRUE(android::base::WriteStringToFile(src_content, update_file.path));
910 
911   ASSERT_TRUE(
912       android::base::WriteStringToFile("2\nstash " + block3_hash + " 2,2,3", last_command_file));
913 
914   // Expect the verification to succeed and the last_command_file is intact.
915   std::string script_verify =
916       "block_image_verify(\"" + std::string(update_file.path) +
917       R"(", package_extract_file("transfer_list_verify"), "new_data","patch_data"))";
918   expect("t", script_verify.c_str(), kNoCause, &updater_info);
919 
920   std::string last_command_content;
921   ASSERT_TRUE(android::base::ReadFileToString(last_command_file.c_str(), &last_command_content));
922   EXPECT_EQ("2\nstash " + block3_hash + " 2,2,3", last_command_content);
923 
924   // Expect the verification to succeed but last_command_file to be deleted; because the target
925   // blocks don't have the expected contents for the second move command.
926   src_content = block1 + block2 + block3;
927   ASSERT_TRUE(android::base::WriteStringToFile(src_content, update_file.path));
928   expect("t", script_verify.c_str(), kNoCause, &updater_info);
929   ASSERT_EQ(-1, access(last_command_file.c_str(), R_OK));
930 
931   ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
932   CloseArchive(handle);
933 }
934