Home | History | Annotate | Download | only in component
      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 <vector>
     27 
     28 #include <android-base/file.h>
     29 #include <android-base/properties.h>
     30 #include <android-base/stringprintf.h>
     31 #include <android-base/strings.h>
     32 #include <android-base/test_utils.h>
     33 #include <bootloader_message/bootloader_message.h>
     34 #include <brotli/encode.h>
     35 #include <bsdiff.h>
     36 #include <gtest/gtest.h>
     37 #include <ziparchive/zip_archive.h>
     38 #include <ziparchive/zip_writer.h>
     39 
     40 #include "common/test_constants.h"
     41 #include "edify/expr.h"
     42 #include "error_code.h"
     43 #include "otautil/SysUtil.h"
     44 #include "print_sha1.h"
     45 #include "updater/blockimg.h"
     46 #include "updater/install.h"
     47 #include "updater/updater.h"
     48 
     49 struct selabel_handle *sehandle = nullptr;
     50 
     51 static void expect(const char* expected, const char* expr_str, CauseCode cause_code,
     52                    UpdaterInfo* info = nullptr) {
     53   std::unique_ptr<Expr> e;
     54   int error_count = 0;
     55   ASSERT_EQ(0, parse_string(expr_str, &e, &error_count));
     56   ASSERT_EQ(0, error_count);
     57 
     58   State state(expr_str, info);
     59 
     60   std::string result;
     61   bool status = Evaluate(&state, e, &result);
     62 
     63   if (expected == nullptr) {
     64     ASSERT_FALSE(status);
     65   } else {
     66     ASSERT_TRUE(status);
     67     ASSERT_STREQ(expected, result.c_str());
     68   }
     69 
     70   // Error code is set in updater/updater.cpp only, by parsing State.errmsg.
     71   ASSERT_EQ(kNoError, state.error_code);
     72 
     73   // Cause code should always be available.
     74   ASSERT_EQ(cause_code, state.cause_code);
     75 }
     76 
     77 static std::string get_sha1(const std::string& content) {
     78   uint8_t digest[SHA_DIGEST_LENGTH];
     79   SHA1(reinterpret_cast<const uint8_t*>(content.c_str()), content.size(), digest);
     80   return print_sha1(digest);
     81 }
     82 
     83 class UpdaterTest : public ::testing::Test {
     84  protected:
     85   virtual void SetUp() override {
     86     RegisterBuiltins();
     87     RegisterInstallFunctions();
     88     RegisterBlockImageFunctions();
     89   }
     90 };
     91 
     92 TEST_F(UpdaterTest, getprop) {
     93     expect(android::base::GetProperty("ro.product.device", "").c_str(),
     94            "getprop(\"ro.product.device\")",
     95            kNoCause);
     96 
     97     expect(android::base::GetProperty("ro.build.fingerprint", "").c_str(),
     98            "getprop(\"ro.build.fingerprint\")",
     99            kNoCause);
    100 
    101     // getprop() accepts only one parameter.
    102     expect(nullptr, "getprop()", kArgsParsingFailure);
    103     expect(nullptr, "getprop(\"arg1\", \"arg2\")", kArgsParsingFailure);
    104 }
    105 
    106 TEST_F(UpdaterTest, sha1_check) {
    107     // sha1_check(data) returns the SHA-1 of the data.
    108     expect("81fe8bfe87576c3ecb22426f8e57847382917acf", "sha1_check(\"abcd\")", kNoCause);
    109     expect("da39a3ee5e6b4b0d3255bfef95601890afd80709", "sha1_check(\"\")", kNoCause);
    110 
    111     // sha1_check(data, sha1_hex, [sha1_hex, ...]) returns the matched SHA-1.
    112     expect("81fe8bfe87576c3ecb22426f8e57847382917acf",
    113            "sha1_check(\"abcd\", \"81fe8bfe87576c3ecb22426f8e57847382917acf\")",
    114            kNoCause);
    115 
    116     expect("81fe8bfe87576c3ecb22426f8e57847382917acf",
    117            "sha1_check(\"abcd\", \"wrong_sha1\", \"81fe8bfe87576c3ecb22426f8e57847382917acf\")",
    118            kNoCause);
    119 
    120     // Or "" if there's no match.
    121     expect("",
    122            "sha1_check(\"abcd\", \"wrong_sha1\")",
    123            kNoCause);
    124 
    125     expect("",
    126            "sha1_check(\"abcd\", \"wrong_sha1\", \"wrong_sha2\")",
    127            kNoCause);
    128 
    129     // sha1_check() expects at least one argument.
    130     expect(nullptr, "sha1_check()", kArgsParsingFailure);
    131 }
    132 
    133 TEST_F(UpdaterTest, apply_patch_check) {
    134   // Zero-argument is not valid.
    135   expect(nullptr, "apply_patch_check()", kArgsParsingFailure);
    136 
    137   // File not found.
    138   expect("", "apply_patch_check(\"/doesntexist\")", kNoCause);
    139 
    140   std::string src_file = from_testdata_base("old.file");
    141   std::string src_content;
    142   ASSERT_TRUE(android::base::ReadFileToString(src_file, &src_content));
    143   size_t src_size = src_content.size();
    144   std::string src_hash = get_sha1(src_content);
    145 
    146   // One-argument with EMMC:file:size:sha1 should pass the check.
    147   std::string filename = android::base::Join(
    148       std::vector<std::string>{ "EMMC", src_file, std::to_string(src_size), src_hash }, ":");
    149   std::string cmd = "apply_patch_check(\"" + filename + "\")";
    150   expect("t", cmd.c_str(), kNoCause);
    151 
    152   // EMMC:file:(size-1):sha1:(size+1):sha1 should fail the check.
    153   std::string filename_bad = android::base::Join(
    154       std::vector<std::string>{ "EMMC", src_file, std::to_string(src_size - 1), src_hash,
    155                                 std::to_string(src_size + 1), src_hash },
    156       ":");
    157   cmd = "apply_patch_check(\"" + filename_bad + "\")";
    158   expect("", cmd.c_str(), kNoCause);
    159 
    160   // EMMC:file:(size-1):sha1:size:sha1:(size+1):sha1 should pass the check.
    161   filename_bad =
    162       android::base::Join(std::vector<std::string>{ "EMMC", src_file, std::to_string(src_size - 1),
    163                                                     src_hash, std::to_string(src_size), src_hash,
    164                                                     std::to_string(src_size + 1), src_hash },
    165                           ":");
    166   cmd = "apply_patch_check(\"" + filename_bad + "\")";
    167   expect("t", cmd.c_str(), kNoCause);
    168 
    169   // Multiple arguments.
    170   cmd = "apply_patch_check(\"" + filename + "\", \"wrong_sha1\", \"wrong_sha2\")";
    171   expect("", cmd.c_str(), kNoCause);
    172 
    173   cmd = "apply_patch_check(\"" + filename + "\", \"wrong_sha1\", \"" + src_hash +
    174         "\", \"wrong_sha2\")";
    175   expect("t", cmd.c_str(), kNoCause);
    176 
    177   cmd = "apply_patch_check(\"" + filename_bad + "\", \"wrong_sha1\", \"" + src_hash +
    178         "\", \"wrong_sha2\")";
    179   expect("t", cmd.c_str(), kNoCause);
    180 }
    181 
    182 TEST_F(UpdaterTest, file_getprop) {
    183     // file_getprop() expects two arguments.
    184     expect(nullptr, "file_getprop()", kArgsParsingFailure);
    185     expect(nullptr, "file_getprop(\"arg1\")", kArgsParsingFailure);
    186     expect(nullptr, "file_getprop(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
    187 
    188     // File doesn't exist.
    189     expect(nullptr, "file_getprop(\"/doesntexist\", \"key1\")", kFileGetPropFailure);
    190 
    191     // Reject too large files (current limit = 65536).
    192     TemporaryFile temp_file1;
    193     std::string buffer(65540, '\0');
    194     ASSERT_TRUE(android::base::WriteStringToFile(buffer, temp_file1.path));
    195 
    196     // Read some keys.
    197     TemporaryFile temp_file2;
    198     std::string content("ro.product.name=tardis\n"
    199                         "# comment\n\n\n"
    200                         "ro.product.model\n"
    201                         "ro.product.board =  magic \n");
    202     ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file2.path));
    203 
    204     std::string script1("file_getprop(\"" + std::string(temp_file2.path) +
    205                        "\", \"ro.product.name\")");
    206     expect("tardis", script1.c_str(), kNoCause);
    207 
    208     std::string script2("file_getprop(\"" + std::string(temp_file2.path) +
    209                        "\", \"ro.product.board\")");
    210     expect("magic", script2.c_str(), kNoCause);
    211 
    212     // No match.
    213     std::string script3("file_getprop(\"" + std::string(temp_file2.path) +
    214                        "\", \"ro.product.wrong\")");
    215     expect("", script3.c_str(), kNoCause);
    216 
    217     std::string script4("file_getprop(\"" + std::string(temp_file2.path) +
    218                        "\", \"ro.product.name=\")");
    219     expect("", script4.c_str(), kNoCause);
    220 
    221     std::string script5("file_getprop(\"" + std::string(temp_file2.path) +
    222                        "\", \"ro.product.nam\")");
    223     expect("", script5.c_str(), kNoCause);
    224 
    225     std::string script6("file_getprop(\"" + std::string(temp_file2.path) +
    226                        "\", \"ro.product.model\")");
    227     expect("", script6.c_str(), kNoCause);
    228 }
    229 
    230 // TODO: Test extracting to block device.
    231 TEST_F(UpdaterTest, package_extract_file) {
    232   // package_extract_file expects 1 or 2 arguments.
    233   expect(nullptr, "package_extract_file()", kArgsParsingFailure);
    234   expect(nullptr, "package_extract_file(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
    235 
    236   std::string zip_path = from_testdata_base("ziptest_valid.zip");
    237   ZipArchiveHandle handle;
    238   ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
    239 
    240   // Need to set up the ziphandle.
    241   UpdaterInfo updater_info;
    242   updater_info.package_zip = handle;
    243 
    244   // Two-argument version.
    245   TemporaryFile temp_file1;
    246   std::string script("package_extract_file(\"a.txt\", \"" + std::string(temp_file1.path) + "\")");
    247   expect("t", script.c_str(), kNoCause, &updater_info);
    248 
    249   // Verify the extracted entry.
    250   std::string data;
    251   ASSERT_TRUE(android::base::ReadFileToString(temp_file1.path, &data));
    252   ASSERT_EQ(kATxtContents, data);
    253 
    254   // Now extract another entry to the same location, which should overwrite.
    255   script = "package_extract_file(\"b.txt\", \"" + std::string(temp_file1.path) + "\")";
    256   expect("t", script.c_str(), kNoCause, &updater_info);
    257 
    258   ASSERT_TRUE(android::base::ReadFileToString(temp_file1.path, &data));
    259   ASSERT_EQ(kBTxtContents, data);
    260 
    261   // Missing zip entry. The two-argument version doesn't abort.
    262   script = "package_extract_file(\"doesntexist\", \"" + std::string(temp_file1.path) + "\")";
    263   expect("", script.c_str(), kNoCause, &updater_info);
    264 
    265   // Extract to /dev/full should fail.
    266   script = "package_extract_file(\"a.txt\", \"/dev/full\")";
    267   expect("", script.c_str(), kNoCause, &updater_info);
    268 
    269   // One-argument version.
    270   script = "sha1_check(package_extract_file(\"a.txt\"))";
    271   expect(kATxtSha1Sum.c_str(), script.c_str(), kNoCause, &updater_info);
    272 
    273   script = "sha1_check(package_extract_file(\"b.txt\"))";
    274   expect(kBTxtSha1Sum.c_str(), script.c_str(), kNoCause, &updater_info);
    275 
    276   // Missing entry. The one-argument version aborts the evaluation.
    277   script = "package_extract_file(\"doesntexist\")";
    278   expect(nullptr, script.c_str(), kPackageExtractFileFailure, &updater_info);
    279 
    280   CloseArchive(handle);
    281 }
    282 
    283 TEST_F(UpdaterTest, write_value) {
    284   // write_value() expects two arguments.
    285   expect(nullptr, "write_value()", kArgsParsingFailure);
    286   expect(nullptr, "write_value(\"arg1\")", kArgsParsingFailure);
    287   expect(nullptr, "write_value(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
    288 
    289   // filename cannot be empty.
    290   expect(nullptr, "write_value(\"value\", \"\")", kArgsParsingFailure);
    291 
    292   // Write some value to file.
    293   TemporaryFile temp_file;
    294   std::string value = "magicvalue";
    295   std::string script("write_value(\"" + value + "\", \"" + std::string(temp_file.path) + "\")");
    296   expect("t", script.c_str(), kNoCause);
    297 
    298   // Verify the content.
    299   std::string content;
    300   ASSERT_TRUE(android::base::ReadFileToString(temp_file.path, &content));
    301   ASSERT_EQ(value, content);
    302 
    303   // Allow writing empty string.
    304   script = "write_value(\"\", \"" + std::string(temp_file.path) + "\")";
    305   expect("t", script.c_str(), kNoCause);
    306 
    307   // Verify the content.
    308   ASSERT_TRUE(android::base::ReadFileToString(temp_file.path, &content));
    309   ASSERT_EQ("", content);
    310 
    311   // It should fail gracefully when write fails.
    312   script = "write_value(\"value\", \"/proc/0/file1\")";
    313   expect("", script.c_str(), kNoCause);
    314 }
    315 
    316 TEST_F(UpdaterTest, get_stage) {
    317   // get_stage() expects one argument.
    318   expect(nullptr, "get_stage()", kArgsParsingFailure);
    319   expect(nullptr, "get_stage(\"arg1\", \"arg2\")", kArgsParsingFailure);
    320   expect(nullptr, "get_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
    321 
    322   // Set up a local file as BCB.
    323   TemporaryFile tf;
    324   std::string temp_file(tf.path);
    325   bootloader_message boot;
    326   strlcpy(boot.stage, "2/3", sizeof(boot.stage));
    327   std::string err;
    328   ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err));
    329 
    330   // Can read the stage value.
    331   std::string script("get_stage(\"" + temp_file + "\")");
    332   expect("2/3", script.c_str(), kNoCause);
    333 
    334   // Bad BCB path.
    335   script = "get_stage(\"doesntexist\")";
    336   expect("", script.c_str(), kNoCause);
    337 }
    338 
    339 TEST_F(UpdaterTest, set_stage) {
    340   // set_stage() expects two arguments.
    341   expect(nullptr, "set_stage()", kArgsParsingFailure);
    342   expect(nullptr, "set_stage(\"arg1\")", kArgsParsingFailure);
    343   expect(nullptr, "set_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
    344 
    345   // Set up a local file as BCB.
    346   TemporaryFile tf;
    347   std::string temp_file(tf.path);
    348   bootloader_message boot;
    349   strlcpy(boot.command, "command", sizeof(boot.command));
    350   strlcpy(boot.stage, "2/3", sizeof(boot.stage));
    351   std::string err;
    352   ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err));
    353 
    354   // Write with set_stage().
    355   std::string script("set_stage(\"" + temp_file + "\", \"1/3\")");
    356   expect(tf.path, script.c_str(), kNoCause);
    357 
    358   // Verify.
    359   bootloader_message boot_verify;
    360   ASSERT_TRUE(read_bootloader_message_from(&boot_verify, temp_file, &err));
    361 
    362   // Stage should be updated, with command part untouched.
    363   ASSERT_STREQ("1/3", boot_verify.stage);
    364   ASSERT_STREQ(boot.command, boot_verify.command);
    365 
    366   // Bad BCB path.
    367   script = "set_stage(\"doesntexist\", \"1/3\")";
    368   expect("", script.c_str(), kNoCause);
    369 
    370   script = "set_stage(\"/dev/full\", \"1/3\")";
    371   expect("", script.c_str(), kNoCause);
    372 }
    373 
    374 TEST_F(UpdaterTest, set_progress) {
    375   // set_progress() expects one argument.
    376   expect(nullptr, "set_progress()", kArgsParsingFailure);
    377   expect(nullptr, "set_progress(\"arg1\", \"arg2\")", kArgsParsingFailure);
    378 
    379   // Invalid progress argument.
    380   expect(nullptr, "set_progress(\"arg1\")", kArgsParsingFailure);
    381   expect(nullptr, "set_progress(\"3x+5\")", kArgsParsingFailure);
    382   expect(nullptr, "set_progress(\".3.5\")", kArgsParsingFailure);
    383 
    384   TemporaryFile tf;
    385   UpdaterInfo updater_info;
    386   updater_info.cmd_pipe = fdopen(tf.fd, "w");
    387   expect(".52", "set_progress(\".52\")", kNoCause, &updater_info);
    388   fflush(updater_info.cmd_pipe);
    389 
    390   std::string cmd;
    391   ASSERT_TRUE(android::base::ReadFileToString(tf.path, &cmd));
    392   ASSERT_EQ(android::base::StringPrintf("set_progress %f\n", .52), cmd);
    393   // recovery-updater protocol expects 2 tokens ("set_progress <frac>").
    394   ASSERT_EQ(2U, android::base::Split(cmd, " ").size());
    395 }
    396 
    397 TEST_F(UpdaterTest, show_progress) {
    398   // show_progress() expects two arguments.
    399   expect(nullptr, "show_progress()", kArgsParsingFailure);
    400   expect(nullptr, "show_progress(\"arg1\")", kArgsParsingFailure);
    401   expect(nullptr, "show_progress(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
    402 
    403   // Invalid progress arguments.
    404   expect(nullptr, "show_progress(\"arg1\", \"arg2\")", kArgsParsingFailure);
    405   expect(nullptr, "show_progress(\"3x+5\", \"10\")", kArgsParsingFailure);
    406   expect(nullptr, "show_progress(\".3\", \"5a\")", kArgsParsingFailure);
    407 
    408   TemporaryFile tf;
    409   UpdaterInfo updater_info;
    410   updater_info.cmd_pipe = fdopen(tf.fd, "w");
    411   expect(".52", "show_progress(\".52\", \"10\")", kNoCause, &updater_info);
    412   fflush(updater_info.cmd_pipe);
    413 
    414   std::string cmd;
    415   ASSERT_TRUE(android::base::ReadFileToString(tf.path, &cmd));
    416   ASSERT_EQ(android::base::StringPrintf("progress %f %d\n", .52, 10), cmd);
    417   // recovery-updater protocol expects 3 tokens ("progress <frac> <secs>").
    418   ASSERT_EQ(3U, android::base::Split(cmd, " ").size());
    419 }
    420 
    421 TEST_F(UpdaterTest, block_image_update) {
    422   // Create a zip file with new_data and patch_data.
    423   TemporaryFile zip_file;
    424   FILE* zip_file_ptr = fdopen(zip_file.fd, "wb");
    425   ZipWriter zip_writer(zip_file_ptr);
    426 
    427   // Add a dummy new data.
    428   ASSERT_EQ(0, zip_writer.StartEntry("new_data", 0));
    429   ASSERT_EQ(0, zip_writer.FinishEntry());
    430 
    431   // Generate and add the patch data.
    432   std::string src_content = std::string(4096, 'a') + std::string(4096, 'c');
    433   std::string tgt_content = std::string(4096, 'b') + std::string(4096, 'd');
    434   TemporaryFile patch_file;
    435   ASSERT_EQ(0, bsdiff::bsdiff(reinterpret_cast<const uint8_t*>(src_content.data()),
    436       src_content.size(), reinterpret_cast<const uint8_t*>(tgt_content.data()),
    437       tgt_content.size(), patch_file.path, nullptr));
    438   std::string patch_content;
    439   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch_content));
    440   ASSERT_EQ(0, zip_writer.StartEntry("patch_data", 0));
    441   ASSERT_EQ(0, zip_writer.WriteBytes(patch_content.data(), patch_content.size()));
    442   ASSERT_EQ(0, zip_writer.FinishEntry());
    443 
    444   // Add two transfer lists. The first one contains a bsdiff; and we expect the update to succeed.
    445   std::string src_hash = get_sha1(src_content);
    446   std::string tgt_hash = get_sha1(tgt_content);
    447   std::vector<std::string> transfer_list = {
    448     "4",
    449     "2",
    450     "0",
    451     "2",
    452     "stash " + src_hash + " 2,0,2",
    453     android::base::StringPrintf("bsdiff 0 %zu %s %s 2,0,2 2 - %s:2,0,2", patch_content.size(),
    454                                 src_hash.c_str(), tgt_hash.c_str(), src_hash.c_str()),
    455     "free " + src_hash,
    456   };
    457   ASSERT_EQ(0, zip_writer.StartEntry("transfer_list", 0));
    458   std::string commands = android::base::Join(transfer_list, '\n');
    459   ASSERT_EQ(0, zip_writer.WriteBytes(commands.data(), commands.size()));
    460   ASSERT_EQ(0, zip_writer.FinishEntry());
    461 
    462   // Stash and free some blocks, then fail the 2nd update intentionally.
    463   std::vector<std::string> fail_transfer_list = {
    464     "4",
    465     "2",
    466     "0",
    467     "2",
    468     "stash " + tgt_hash + " 2,0,2",
    469     "free " + tgt_hash,
    470     "fail",
    471   };
    472   ASSERT_EQ(0, zip_writer.StartEntry("fail_transfer_list", 0));
    473   std::string fail_commands = android::base::Join(fail_transfer_list, '\n');
    474   ASSERT_EQ(0, zip_writer.WriteBytes(fail_commands.data(), fail_commands.size()));
    475   ASSERT_EQ(0, zip_writer.FinishEntry());
    476   ASSERT_EQ(0, zip_writer.Finish());
    477   ASSERT_EQ(0, fclose(zip_file_ptr));
    478 
    479   MemMapping map;
    480   ASSERT_TRUE(map.MapFile(zip_file.path));
    481   ZipArchiveHandle handle;
    482   ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));
    483 
    484   // Set up the handler, command_pipe, patch offset & length.
    485   UpdaterInfo updater_info;
    486   updater_info.package_zip = handle;
    487   TemporaryFile temp_pipe;
    488   updater_info.cmd_pipe = fopen(temp_pipe.path, "wbe");
    489   updater_info.package_zip_addr = map.addr;
    490   updater_info.package_zip_len = map.length;
    491 
    492   // Execute the commands in the 1st transfer list.
    493   TemporaryFile update_file;
    494   ASSERT_TRUE(android::base::WriteStringToFile(src_content, update_file.path));
    495   std::string script = "block_image_update(\"" + std::string(update_file.path) +
    496       R"(", package_extract_file("transfer_list"), "new_data", "patch_data"))";
    497   expect("t", script.c_str(), kNoCause, &updater_info);
    498   // The update_file should be patched correctly.
    499   std::string updated_content;
    500   ASSERT_TRUE(android::base::ReadFileToString(update_file.path, &updated_content));
    501   ASSERT_EQ(tgt_hash, get_sha1(updated_content));
    502 
    503   // Expect the 2nd update to fail, but expect the stashed blocks to be freed.
    504   script = "block_image_update(\"" + std::string(update_file.path) +
    505       R"(", package_extract_file("fail_transfer_list"), "new_data", "patch_data"))";
    506   expect("", script.c_str(), kNoCause, &updater_info);
    507   // Updater generates the stash name based on the input file name.
    508   std::string name_digest = get_sha1(update_file.path);
    509   std::string stash_base = "/cache/recovery/" + name_digest;
    510   ASSERT_EQ(0, access(stash_base.c_str(), F_OK));
    511   ASSERT_EQ(-1, access((stash_base + tgt_hash).c_str(), F_OK));
    512   ASSERT_EQ(0, rmdir(stash_base.c_str()));
    513 
    514   ASSERT_EQ(0, fclose(updater_info.cmd_pipe));
    515   CloseArchive(handle);
    516 }
    517 
    518 TEST_F(UpdaterTest, new_data_short_write) {
    519   // Create a zip file with new_data.
    520   TemporaryFile zip_file;
    521   FILE* zip_file_ptr = fdopen(zip_file.fd, "wb");
    522   ZipWriter zip_writer(zip_file_ptr);
    523 
    524   // Add the empty new data.
    525   ASSERT_EQ(0, zip_writer.StartEntry("empty_new_data", 0));
    526   ASSERT_EQ(0, zip_writer.FinishEntry());
    527   // Add the short written new data.
    528   ASSERT_EQ(0, zip_writer.StartEntry("short_new_data", 0));
    529   std::string new_data_short = std::string(10, 'a');
    530   ASSERT_EQ(0, zip_writer.WriteBytes(new_data_short.data(), new_data_short.size()));
    531   ASSERT_EQ(0, zip_writer.FinishEntry());
    532   // Add the data of exactly one block.
    533   ASSERT_EQ(0, zip_writer.StartEntry("exact_new_data", 0));
    534   std::string new_data_exact = std::string(4096, 'a');
    535   ASSERT_EQ(0, zip_writer.WriteBytes(new_data_exact.data(), new_data_exact.size()));
    536   ASSERT_EQ(0, zip_writer.FinishEntry());
    537   // Add a dummy patch data.
    538   ASSERT_EQ(0, zip_writer.StartEntry("patch_data", 0));
    539   ASSERT_EQ(0, zip_writer.FinishEntry());
    540 
    541   std::vector<std::string> transfer_list = {
    542     "4",
    543     "1",
    544     "0",
    545     "0",
    546     "new 2,0,1",
    547   };
    548   ASSERT_EQ(0, zip_writer.StartEntry("transfer_list", 0));
    549   std::string commands = android::base::Join(transfer_list, '\n');
    550   ASSERT_EQ(0, zip_writer.WriteBytes(commands.data(), commands.size()));
    551   ASSERT_EQ(0, zip_writer.FinishEntry());
    552   ASSERT_EQ(0, zip_writer.Finish());
    553   ASSERT_EQ(0, fclose(zip_file_ptr));
    554 
    555   MemMapping map;
    556   ASSERT_TRUE(map.MapFile(zip_file.path));
    557   ZipArchiveHandle handle;
    558   ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));
    559 
    560   // Set up the handler, command_pipe, patch offset & length.
    561   UpdaterInfo updater_info;
    562   updater_info.package_zip = handle;
    563   TemporaryFile temp_pipe;
    564   updater_info.cmd_pipe = fopen(temp_pipe.path, "wbe");
    565   updater_info.package_zip_addr = map.addr;
    566   updater_info.package_zip_len = map.length;
    567 
    568   // Updater should report the failure gracefully rather than stuck in deadlock.
    569   TemporaryFile update_file;
    570   std::string script_empty_data = "block_image_update(\"" + std::string(update_file.path) +
    571       R"(", package_extract_file("transfer_list"), "empty_new_data", "patch_data"))";
    572   expect("", script_empty_data.c_str(), kNoCause, &updater_info);
    573 
    574   std::string script_short_data = "block_image_update(\"" + std::string(update_file.path) +
    575       R"(", package_extract_file("transfer_list"), "short_new_data", "patch_data"))";
    576   expect("", script_short_data.c_str(), kNoCause, &updater_info);
    577 
    578   // Expect to write 1 block of new data successfully.
    579   std::string script_exact_data = "block_image_update(\"" + std::string(update_file.path) +
    580       R"(", package_extract_file("transfer_list"), "exact_new_data", "patch_data"))";
    581   expect("t", script_exact_data.c_str(), kNoCause, &updater_info);
    582   CloseArchive(handle);
    583 }
    584 
    585 TEST_F(UpdaterTest, brotli_new_data) {
    586   // Create a zip file with new_data.
    587   TemporaryFile zip_file;
    588   FILE* zip_file_ptr = fdopen(zip_file.fd, "wb");
    589   ZipWriter zip_writer(zip_file_ptr);
    590 
    591   // Add a brotli compressed new data entry.
    592   ASSERT_EQ(0, zip_writer.StartEntry("new.dat.br", 0));
    593 
    594   auto generator = []() { return rand() % 128; };
    595   // Generate 100 blocks of random data.
    596   std::string brotli_new_data;
    597   brotli_new_data.reserve(4096 * 100);
    598   generate_n(back_inserter(brotli_new_data), 4096 * 100, generator);
    599 
    600   size_t encoded_size = BrotliEncoderMaxCompressedSize(brotli_new_data.size());
    601   std::vector<uint8_t> encoded_data(encoded_size);
    602   ASSERT_TRUE(BrotliEncoderCompress(
    603       BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW, BROTLI_DEFAULT_MODE, brotli_new_data.size(),
    604       reinterpret_cast<const uint8_t*>(brotli_new_data.data()), &encoded_size, encoded_data.data()));
    605 
    606   ASSERT_EQ(0, zip_writer.WriteBytes(encoded_data.data(), encoded_size));
    607   ASSERT_EQ(0, zip_writer.FinishEntry());
    608   // Add a dummy patch data.
    609   ASSERT_EQ(0, zip_writer.StartEntry("patch_data", 0));
    610   ASSERT_EQ(0, zip_writer.FinishEntry());
    611 
    612   // Write a few small chunks of new data, then a large chunk, and finally a few small chunks.
    613   // This helps us to catch potential short writes.
    614   std::vector<std::string> transfer_list = {
    615     "4",
    616     "100",
    617     "0",
    618     "0",
    619     "new 2,0,1",
    620     "new 2,1,2",
    621     "new 4,2,50,50,97",
    622     "new 2,97,98",
    623     "new 2,98,99",
    624     "new 2,99,100",
    625   };
    626   ASSERT_EQ(0, zip_writer.StartEntry("transfer_list", 0));
    627   std::string commands = android::base::Join(transfer_list, '\n');
    628   ASSERT_EQ(0, zip_writer.WriteBytes(commands.data(), commands.size()));
    629   ASSERT_EQ(0, zip_writer.FinishEntry());
    630   ASSERT_EQ(0, zip_writer.Finish());
    631   ASSERT_EQ(0, fclose(zip_file_ptr));
    632 
    633   MemMapping map;
    634   ASSERT_TRUE(map.MapFile(zip_file.path));
    635   ZipArchiveHandle handle;
    636   ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_file.path, &handle));
    637 
    638   // Set up the handler, command_pipe, patch offset & length.
    639   UpdaterInfo updater_info;
    640   updater_info.package_zip = handle;
    641   TemporaryFile temp_pipe;
    642   updater_info.cmd_pipe = fopen(temp_pipe.path, "wb");
    643   updater_info.package_zip_addr = map.addr;
    644   updater_info.package_zip_len = map.length;
    645 
    646   // Check if we can decompress the new data correctly.
    647   TemporaryFile update_file;
    648   std::string script_new_data =
    649       "block_image_update(\"" + std::string(update_file.path) +
    650       R"(", package_extract_file("transfer_list"), "new.dat.br", "patch_data"))";
    651   expect("t", script_new_data.c_str(), kNoCause, &updater_info);
    652 
    653   std::string updated_content;
    654   ASSERT_TRUE(android::base::ReadFileToString(update_file.path, &updated_content));
    655   ASSERT_EQ(brotli_new_data, updated_content);
    656   CloseArchive(handle);
    657 }
    658