xref: /aosp_15_r20/bootable/deprecated-ota/tests/unit/updater_test.cpp (revision acea8879c968027b49a027136800575dd9783ddf)
1*acea8879SAndroid Build Coastguard Worker /*
2*acea8879SAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*acea8879SAndroid Build Coastguard Worker  *
4*acea8879SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*acea8879SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*acea8879SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*acea8879SAndroid Build Coastguard Worker  *
8*acea8879SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*acea8879SAndroid Build Coastguard Worker  *
10*acea8879SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*acea8879SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*acea8879SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*acea8879SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*acea8879SAndroid Build Coastguard Worker  * limitations under the License.
15*acea8879SAndroid Build Coastguard Worker  */
16*acea8879SAndroid Build Coastguard Worker 
17*acea8879SAndroid Build Coastguard Worker #include <stdio.h>
18*acea8879SAndroid Build Coastguard Worker #include <stdlib.h>
19*acea8879SAndroid Build Coastguard Worker #include <sys/stat.h>
20*acea8879SAndroid Build Coastguard Worker #include <sys/types.h>
21*acea8879SAndroid Build Coastguard Worker #include <unistd.h>
22*acea8879SAndroid Build Coastguard Worker 
23*acea8879SAndroid Build Coastguard Worker #include <algorithm>
24*acea8879SAndroid Build Coastguard Worker #include <memory>
25*acea8879SAndroid Build Coastguard Worker #include <string>
26*acea8879SAndroid Build Coastguard Worker #include <string_view>
27*acea8879SAndroid Build Coastguard Worker #include <unordered_map>
28*acea8879SAndroid Build Coastguard Worker #include <vector>
29*acea8879SAndroid Build Coastguard Worker 
30*acea8879SAndroid Build Coastguard Worker #include <android-base/file.h>
31*acea8879SAndroid Build Coastguard Worker #include <android-base/logging.h>
32*acea8879SAndroid Build Coastguard Worker #include <android-base/parseint.h>
33*acea8879SAndroid Build Coastguard Worker #include <android-base/properties.h>
34*acea8879SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
35*acea8879SAndroid Build Coastguard Worker #include <android-base/strings.h>
36*acea8879SAndroid Build Coastguard Worker #include <bootloader_message/bootloader_message.h>
37*acea8879SAndroid Build Coastguard Worker #include <brotli/encode.h>
38*acea8879SAndroid Build Coastguard Worker #include <bsdiff/bsdiff.h>
39*acea8879SAndroid Build Coastguard Worker #include <gtest/gtest.h>
40*acea8879SAndroid Build Coastguard Worker #include <verity/hash_tree_builder.h>
41*acea8879SAndroid Build Coastguard Worker #include <ziparchive/zip_archive.h>
42*acea8879SAndroid Build Coastguard Worker #include <ziparchive/zip_writer.h>
43*acea8879SAndroid Build Coastguard Worker 
44*acea8879SAndroid Build Coastguard Worker #include "applypatch/applypatch.h"
45*acea8879SAndroid Build Coastguard Worker #include "common/test_constants.h"
46*acea8879SAndroid Build Coastguard Worker #include "edify/expr.h"
47*acea8879SAndroid Build Coastguard Worker #include "otautil/error_code.h"
48*acea8879SAndroid Build Coastguard Worker #include "otautil/paths.h"
49*acea8879SAndroid Build Coastguard Worker #include "otautil/print_sha1.h"
50*acea8879SAndroid Build Coastguard Worker #include "otautil/sysutil.h"
51*acea8879SAndroid Build Coastguard Worker #include "private/commands.h"
52*acea8879SAndroid Build Coastguard Worker #include "updater/blockimg.h"
53*acea8879SAndroid Build Coastguard Worker #include "updater/install.h"
54*acea8879SAndroid Build Coastguard Worker #include "updater/updater.h"
55*acea8879SAndroid Build Coastguard Worker #include "updater/updater_runtime.h"
56*acea8879SAndroid Build Coastguard Worker 
57*acea8879SAndroid Build Coastguard Worker using namespace std::string_literals;
58*acea8879SAndroid Build Coastguard Worker 
59*acea8879SAndroid Build Coastguard Worker using PackageEntries = std::unordered_map<std::string, std::string>;
60*acea8879SAndroid Build Coastguard Worker 
expect(const char * expected,const std::string & expr_str,CauseCode cause_code,Updater * updater)61*acea8879SAndroid Build Coastguard Worker static void expect(const char* expected, const std::string& expr_str, CauseCode cause_code,
62*acea8879SAndroid Build Coastguard Worker                    Updater* updater) {
63*acea8879SAndroid Build Coastguard Worker   std::unique_ptr<Expr> e;
64*acea8879SAndroid Build Coastguard Worker   int error_count = 0;
65*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, ParseString(expr_str, &e, &error_count));
66*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, error_count);
67*acea8879SAndroid Build Coastguard Worker 
68*acea8879SAndroid Build Coastguard Worker   State state(expr_str, updater);
69*acea8879SAndroid Build Coastguard Worker 
70*acea8879SAndroid Build Coastguard Worker   std::string result;
71*acea8879SAndroid Build Coastguard Worker   bool status = Evaluate(&state, e, &result);
72*acea8879SAndroid Build Coastguard Worker 
73*acea8879SAndroid Build Coastguard Worker   if (expected == nullptr) {
74*acea8879SAndroid Build Coastguard Worker     ASSERT_FALSE(status);
75*acea8879SAndroid Build Coastguard Worker   } else {
76*acea8879SAndroid Build Coastguard Worker     ASSERT_TRUE(status) << "Evaluate() finished with error message: " << state.errmsg;
77*acea8879SAndroid Build Coastguard Worker     ASSERT_STREQ(expected, result.c_str());
78*acea8879SAndroid Build Coastguard Worker   }
79*acea8879SAndroid Build Coastguard Worker 
80*acea8879SAndroid Build Coastguard Worker   // Error code is set in updater/updater.cpp only, by parsing State.errmsg.
81*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(kNoError, state.error_code);
82*acea8879SAndroid Build Coastguard Worker 
83*acea8879SAndroid Build Coastguard Worker   // Cause code should always be available.
84*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(cause_code, state.cause_code);
85*acea8879SAndroid Build Coastguard Worker }
86*acea8879SAndroid Build Coastguard Worker 
expect(const char * expected,const std::string & expr_str,CauseCode cause_code)87*acea8879SAndroid Build Coastguard Worker static void expect(const char* expected, const std::string& expr_str, CauseCode cause_code) {
88*acea8879SAndroid Build Coastguard Worker   Updater updater(std::make_unique<UpdaterRuntime>(nullptr));
89*acea8879SAndroid Build Coastguard Worker   expect(expected, expr_str, cause_code, &updater);
90*acea8879SAndroid Build Coastguard Worker }
91*acea8879SAndroid Build Coastguard Worker 
BuildUpdatePackage(const PackageEntries & entries,int fd)92*acea8879SAndroid Build Coastguard Worker static void BuildUpdatePackage(const PackageEntries& entries, int fd) {
93*acea8879SAndroid Build Coastguard Worker   FILE* zip_file_ptr = fdopen(fd, "wb");
94*acea8879SAndroid Build Coastguard Worker   ZipWriter zip_writer(zip_file_ptr);
95*acea8879SAndroid Build Coastguard Worker 
96*acea8879SAndroid Build Coastguard Worker   for (const auto& entry : entries) {
97*acea8879SAndroid Build Coastguard Worker     // All the entries are written as STORED.
98*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(0, zip_writer.StartEntry(entry.first.c_str(), 0));
99*acea8879SAndroid Build Coastguard Worker     if (!entry.second.empty()) {
100*acea8879SAndroid Build Coastguard Worker       ASSERT_EQ(0, zip_writer.WriteBytes(entry.second.data(), entry.second.size()));
101*acea8879SAndroid Build Coastguard Worker     }
102*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(0, zip_writer.FinishEntry());
103*acea8879SAndroid Build Coastguard Worker   }
104*acea8879SAndroid Build Coastguard Worker 
105*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, zip_writer.Finish());
106*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, fclose(zip_file_ptr));
107*acea8879SAndroid Build Coastguard Worker }
108*acea8879SAndroid Build Coastguard Worker 
GetSha1(std::string_view content)109*acea8879SAndroid Build Coastguard Worker static std::string GetSha1(std::string_view content) {
110*acea8879SAndroid Build Coastguard Worker   uint8_t digest[SHA_DIGEST_LENGTH];
111*acea8879SAndroid Build Coastguard Worker   SHA1(reinterpret_cast<const uint8_t*>(content.data()), content.size(), digest);
112*acea8879SAndroid Build Coastguard Worker   return print_sha1(digest);
113*acea8879SAndroid Build Coastguard Worker }
114*acea8879SAndroid Build Coastguard Worker 
BlobToString(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)115*acea8879SAndroid Build Coastguard Worker static Value* BlobToString(const char* name, State* state,
116*acea8879SAndroid Build Coastguard Worker                            const std::vector<std::unique_ptr<Expr>>& argv) {
117*acea8879SAndroid Build Coastguard Worker   if (argv.size() != 1) {
118*acea8879SAndroid Build Coastguard Worker     return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
119*acea8879SAndroid Build Coastguard Worker   }
120*acea8879SAndroid Build Coastguard Worker 
121*acea8879SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<Value>> args;
122*acea8879SAndroid Build Coastguard Worker   if (!ReadValueArgs(state, argv, &args)) {
123*acea8879SAndroid Build Coastguard Worker     return nullptr;
124*acea8879SAndroid Build Coastguard Worker   }
125*acea8879SAndroid Build Coastguard Worker 
126*acea8879SAndroid Build Coastguard Worker   if (args[0]->type != Value::Type::BLOB) {
127*acea8879SAndroid Build Coastguard Worker     return ErrorAbort(state, kArgsParsingFailure, "%s() expects a BLOB argument", name);
128*acea8879SAndroid Build Coastguard Worker   }
129*acea8879SAndroid Build Coastguard Worker 
130*acea8879SAndroid Build Coastguard Worker   args[0]->type = Value::Type::STRING;
131*acea8879SAndroid Build Coastguard Worker   return args[0].release();
132*acea8879SAndroid Build Coastguard Worker }
133*acea8879SAndroid Build Coastguard Worker 
134*acea8879SAndroid Build Coastguard Worker class UpdaterTestBase {
135*acea8879SAndroid Build Coastguard Worker  protected:
UpdaterTestBase()136*acea8879SAndroid Build Coastguard Worker   UpdaterTestBase() : updater_(std::make_unique<UpdaterRuntime>(nullptr)) {}
137*acea8879SAndroid Build Coastguard Worker 
SetUp()138*acea8879SAndroid Build Coastguard Worker   void SetUp() {
139*acea8879SAndroid Build Coastguard Worker     RegisterBuiltins();
140*acea8879SAndroid Build Coastguard Worker     RegisterInstallFunctions();
141*acea8879SAndroid Build Coastguard Worker     RegisterBlockImageFunctions();
142*acea8879SAndroid Build Coastguard Worker 
143*acea8879SAndroid Build Coastguard Worker     // Each test is run in a separate process (isolated mode). Shared temporary files won't cause
144*acea8879SAndroid Build Coastguard Worker     // conflicts.
145*acea8879SAndroid Build Coastguard Worker     Paths::Get().set_cache_temp_source(temp_saved_source_.path);
146*acea8879SAndroid Build Coastguard Worker     Paths::Get().set_last_command_file(temp_last_command_.path);
147*acea8879SAndroid Build Coastguard Worker     Paths::Get().set_stash_directory_base(temp_stash_base_.path);
148*acea8879SAndroid Build Coastguard Worker 
149*acea8879SAndroid Build Coastguard Worker     last_command_file_ = temp_last_command_.path;
150*acea8879SAndroid Build Coastguard Worker     image_file_ = image_temp_file_.path;
151*acea8879SAndroid Build Coastguard Worker   }
152*acea8879SAndroid Build Coastguard Worker 
TearDown()153*acea8879SAndroid Build Coastguard Worker   void TearDown() {
154*acea8879SAndroid Build Coastguard Worker     // Clean up the last_command_file if any.
155*acea8879SAndroid Build Coastguard Worker     ASSERT_TRUE(android::base::RemoveFileIfExists(last_command_file_));
156*acea8879SAndroid Build Coastguard Worker 
157*acea8879SAndroid Build Coastguard Worker     // Clear partition updated marker if any.
158*acea8879SAndroid Build Coastguard Worker     std::string updated_marker{ temp_stash_base_.path };
159*acea8879SAndroid Build Coastguard Worker     updated_marker += "/" + GetSha1(image_temp_file_.path) + ".UPDATED";
160*acea8879SAndroid Build Coastguard Worker     ASSERT_TRUE(android::base::RemoveFileIfExists(updated_marker));
161*acea8879SAndroid Build Coastguard Worker   }
162*acea8879SAndroid Build Coastguard Worker 
RunBlockImageUpdate(bool is_verify,PackageEntries entries,const std::string & image_file,const std::string & result,CauseCode cause_code=kNoCause)163*acea8879SAndroid Build Coastguard Worker   void RunBlockImageUpdate(bool is_verify, PackageEntries entries, const std::string& image_file,
164*acea8879SAndroid Build Coastguard Worker                            const std::string& result, CauseCode cause_code = kNoCause) {
165*acea8879SAndroid Build Coastguard Worker     CHECK(entries.find("transfer_list") != entries.end());
166*acea8879SAndroid Build Coastguard Worker     std::string new_data =
167*acea8879SAndroid Build Coastguard Worker         entries.find("new_data.br") != entries.end() ? "new_data.br" : "new_data";
168*acea8879SAndroid Build Coastguard Worker     std::string script = is_verify ? "block_image_verify" : "block_image_update";
169*acea8879SAndroid Build Coastguard Worker     script += R"((")" + image_file + R"(", package_extract_file("transfer_list"), ")" + new_data +
170*acea8879SAndroid Build Coastguard Worker               R"(", "patch_data"))";
171*acea8879SAndroid Build Coastguard Worker     entries.emplace(Updater::SCRIPT_NAME, script);
172*acea8879SAndroid Build Coastguard Worker 
173*acea8879SAndroid Build Coastguard Worker     // Build the update package.
174*acea8879SAndroid Build Coastguard Worker     TemporaryFile zip_file;
175*acea8879SAndroid Build Coastguard Worker     BuildUpdatePackage(entries, zip_file.release());
176*acea8879SAndroid Build Coastguard Worker 
177*acea8879SAndroid Build Coastguard Worker     // Set up the handler, command_pipe, patch offset & length.
178*acea8879SAndroid Build Coastguard Worker     TemporaryFile temp_pipe;
179*acea8879SAndroid Build Coastguard Worker     ASSERT_TRUE(updater_.Init(temp_pipe.release(), zip_file.path, false));
180*acea8879SAndroid Build Coastguard Worker     ASSERT_TRUE(updater_.RunUpdate());
181*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(result, updater_.GetResult());
182*acea8879SAndroid Build Coastguard Worker 
183*acea8879SAndroid Build Coastguard Worker     // Parse the cause code written to the command pipe.
184*acea8879SAndroid Build Coastguard Worker     int received_cause_code = kNoCause;
185*acea8879SAndroid Build Coastguard Worker     std::string pipe_content;
186*acea8879SAndroid Build Coastguard Worker     ASSERT_TRUE(android::base::ReadFileToString(temp_pipe.path, &pipe_content));
187*acea8879SAndroid Build Coastguard Worker     auto lines = android::base::Split(pipe_content, "\n");
188*acea8879SAndroid Build Coastguard Worker     for (std::string_view line : lines) {
189*acea8879SAndroid Build Coastguard Worker       if (android::base::ConsumePrefix(&line, "log cause: ")) {
190*acea8879SAndroid Build Coastguard Worker         ASSERT_TRUE(android::base::ParseInt(line.data(), &received_cause_code));
191*acea8879SAndroid Build Coastguard Worker       }
192*acea8879SAndroid Build Coastguard Worker     }
193*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(cause_code, received_cause_code);
194*acea8879SAndroid Build Coastguard Worker   }
195*acea8879SAndroid Build Coastguard Worker 
196*acea8879SAndroid Build Coastguard Worker   TemporaryFile temp_saved_source_;
197*acea8879SAndroid Build Coastguard Worker   TemporaryDir temp_stash_base_;
198*acea8879SAndroid Build Coastguard Worker   std::string last_command_file_;
199*acea8879SAndroid Build Coastguard Worker   std::string image_file_;
200*acea8879SAndroid Build Coastguard Worker 
201*acea8879SAndroid Build Coastguard Worker   Updater updater_;
202*acea8879SAndroid Build Coastguard Worker 
203*acea8879SAndroid Build Coastguard Worker  private:
204*acea8879SAndroid Build Coastguard Worker   TemporaryFile temp_last_command_;
205*acea8879SAndroid Build Coastguard Worker   TemporaryFile image_temp_file_;
206*acea8879SAndroid Build Coastguard Worker };
207*acea8879SAndroid Build Coastguard Worker 
208*acea8879SAndroid Build Coastguard Worker class UpdaterTest : public UpdaterTestBase, public ::testing::Test {
209*acea8879SAndroid Build Coastguard Worker  protected:
SetUp()210*acea8879SAndroid Build Coastguard Worker   void SetUp() override {
211*acea8879SAndroid Build Coastguard Worker     UpdaterTestBase::SetUp();
212*acea8879SAndroid Build Coastguard Worker 
213*acea8879SAndroid Build Coastguard Worker     RegisterFunction("blob_to_string", BlobToString);
214*acea8879SAndroid Build Coastguard Worker     // Enable a special command "abort" to simulate interruption.
215*acea8879SAndroid Build Coastguard Worker     Command::abort_allowed_ = true;
216*acea8879SAndroid Build Coastguard Worker   }
217*acea8879SAndroid Build Coastguard Worker 
TearDown()218*acea8879SAndroid Build Coastguard Worker   void TearDown() override {
219*acea8879SAndroid Build Coastguard Worker     UpdaterTestBase::TearDown();
220*acea8879SAndroid Build Coastguard Worker   }
221*acea8879SAndroid Build Coastguard Worker 
SetUpdaterCmdPipe(int fd)222*acea8879SAndroid Build Coastguard Worker   void SetUpdaterCmdPipe(int fd) {
223*acea8879SAndroid Build Coastguard Worker     FILE* cmd_pipe = fdopen(fd, "w");
224*acea8879SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, cmd_pipe);
225*acea8879SAndroid Build Coastguard Worker     updater_.cmd_pipe_.reset(cmd_pipe);
226*acea8879SAndroid Build Coastguard Worker   }
227*acea8879SAndroid Build Coastguard Worker 
SetUpdaterOtaPackageHandle(ZipArchiveHandle handle)228*acea8879SAndroid Build Coastguard Worker   void SetUpdaterOtaPackageHandle(ZipArchiveHandle handle) {
229*acea8879SAndroid Build Coastguard Worker     updater_.package_handle_ = handle;
230*acea8879SAndroid Build Coastguard Worker   }
231*acea8879SAndroid Build Coastguard Worker 
FlushUpdaterCommandPipe() const232*acea8879SAndroid Build Coastguard Worker   void FlushUpdaterCommandPipe() const {
233*acea8879SAndroid Build Coastguard Worker     fflush(updater_.cmd_pipe_.get());
234*acea8879SAndroid Build Coastguard Worker   }
235*acea8879SAndroid Build Coastguard Worker };
236*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,getprop)237*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, getprop) {
238*acea8879SAndroid Build Coastguard Worker     expect(android::base::GetProperty("ro.product.device", "").c_str(),
239*acea8879SAndroid Build Coastguard Worker            "getprop(\"ro.product.device\")",
240*acea8879SAndroid Build Coastguard Worker            kNoCause);
241*acea8879SAndroid Build Coastguard Worker 
242*acea8879SAndroid Build Coastguard Worker     expect(android::base::GetProperty("ro.build.fingerprint", "").c_str(),
243*acea8879SAndroid Build Coastguard Worker            "getprop(\"ro.build.fingerprint\")",
244*acea8879SAndroid Build Coastguard Worker            kNoCause);
245*acea8879SAndroid Build Coastguard Worker 
246*acea8879SAndroid Build Coastguard Worker     // getprop() accepts only one parameter.
247*acea8879SAndroid Build Coastguard Worker     expect(nullptr, "getprop()", kArgsParsingFailure);
248*acea8879SAndroid Build Coastguard Worker     expect(nullptr, "getprop(\"arg1\", \"arg2\")", kArgsParsingFailure);
249*acea8879SAndroid Build Coastguard Worker }
250*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,patch_partition_check)251*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, patch_partition_check) {
252*acea8879SAndroid Build Coastguard Worker   // Zero argument is not valid.
253*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "patch_partition_check()", kArgsParsingFailure);
254*acea8879SAndroid Build Coastguard Worker 
255*acea8879SAndroid Build Coastguard Worker   std::string source_file = from_testdata_base("boot.img");
256*acea8879SAndroid Build Coastguard Worker   std::string source_content;
257*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(source_file, &source_content));
258*acea8879SAndroid Build Coastguard Worker   size_t source_size = source_content.size();
259*acea8879SAndroid Build Coastguard Worker   std::string source_hash = GetSha1(source_content);
260*acea8879SAndroid Build Coastguard Worker   Partition source(source_file, source_size, source_hash);
261*acea8879SAndroid Build Coastguard Worker 
262*acea8879SAndroid Build Coastguard Worker   std::string target_file = from_testdata_base("recovery.img");
263*acea8879SAndroid Build Coastguard Worker   std::string target_content;
264*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(target_file, &target_content));
265*acea8879SAndroid Build Coastguard Worker   size_t target_size = target_content.size();
266*acea8879SAndroid Build Coastguard Worker   std::string target_hash = GetSha1(target_content);
267*acea8879SAndroid Build Coastguard Worker   Partition target(target_file, target_size, target_hash);
268*acea8879SAndroid Build Coastguard Worker 
269*acea8879SAndroid Build Coastguard Worker   // One argument is not valid.
270*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "patch_partition_check(\"" + source.ToString() + "\")", kArgsParsingFailure);
271*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "patch_partition_check(\"" + target.ToString() + "\")", kArgsParsingFailure);
272*acea8879SAndroid Build Coastguard Worker 
273*acea8879SAndroid Build Coastguard Worker   // Both of the source and target have the desired checksum.
274*acea8879SAndroid Build Coastguard Worker   std::string cmd =
275*acea8879SAndroid Build Coastguard Worker       "patch_partition_check(\"" + source.ToString() + "\", \"" + target.ToString() + "\")";
276*acea8879SAndroid Build Coastguard Worker   expect("t", cmd, kNoCause);
277*acea8879SAndroid Build Coastguard Worker 
278*acea8879SAndroid Build Coastguard Worker   // Only source partition has the desired checksum.
279*acea8879SAndroid Build Coastguard Worker   Partition bad_target(target_file, target_size - 1, target_hash);
280*acea8879SAndroid Build Coastguard Worker   cmd = "patch_partition_check(\"" + source.ToString() + "\", \"" + bad_target.ToString() + "\")";
281*acea8879SAndroid Build Coastguard Worker   expect("t", cmd, kNoCause);
282*acea8879SAndroid Build Coastguard Worker 
283*acea8879SAndroid Build Coastguard Worker   // Only target partition has the desired checksum.
284*acea8879SAndroid Build Coastguard Worker   Partition bad_source(source_file, source_size + 1, source_hash);
285*acea8879SAndroid Build Coastguard Worker   cmd = "patch_partition_check(\"" + bad_source.ToString() + "\", \"" + target.ToString() + "\")";
286*acea8879SAndroid Build Coastguard Worker   expect("t", cmd, kNoCause);
287*acea8879SAndroid Build Coastguard Worker 
288*acea8879SAndroid Build Coastguard Worker   // Neither of the source or target has the desired checksum.
289*acea8879SAndroid Build Coastguard Worker   cmd =
290*acea8879SAndroid Build Coastguard Worker       "patch_partition_check(\"" + bad_source.ToString() + "\", \"" + bad_target.ToString() + "\")";
291*acea8879SAndroid Build Coastguard Worker   expect("", cmd, kNoCause);
292*acea8879SAndroid Build Coastguard Worker }
293*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,file_getprop)294*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, file_getprop) {
295*acea8879SAndroid Build Coastguard Worker     // file_getprop() expects two arguments.
296*acea8879SAndroid Build Coastguard Worker     expect(nullptr, "file_getprop()", kArgsParsingFailure);
297*acea8879SAndroid Build Coastguard Worker     expect(nullptr, "file_getprop(\"arg1\")", kArgsParsingFailure);
298*acea8879SAndroid Build Coastguard Worker     expect(nullptr, "file_getprop(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
299*acea8879SAndroid Build Coastguard Worker 
300*acea8879SAndroid Build Coastguard Worker     // File doesn't exist.
301*acea8879SAndroid Build Coastguard Worker     expect(nullptr, "file_getprop(\"/doesntexist\", \"key1\")", kFreadFailure);
302*acea8879SAndroid Build Coastguard Worker 
303*acea8879SAndroid Build Coastguard Worker     // Reject too large files (current limit = 65536).
304*acea8879SAndroid Build Coastguard Worker     TemporaryFile temp_file1;
305*acea8879SAndroid Build Coastguard Worker     std::string buffer(65540, '\0');
306*acea8879SAndroid Build Coastguard Worker     ASSERT_TRUE(android::base::WriteStringToFile(buffer, temp_file1.path));
307*acea8879SAndroid Build Coastguard Worker 
308*acea8879SAndroid Build Coastguard Worker     // Read some keys.
309*acea8879SAndroid Build Coastguard Worker     TemporaryFile temp_file2;
310*acea8879SAndroid Build Coastguard Worker     std::string content("ro.product.name=tardis\n"
311*acea8879SAndroid Build Coastguard Worker                         "# comment\n\n\n"
312*acea8879SAndroid Build Coastguard Worker                         "ro.product.model\n"
313*acea8879SAndroid Build Coastguard Worker                         "ro.product.board =  magic \n");
314*acea8879SAndroid Build Coastguard Worker     ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file2.path));
315*acea8879SAndroid Build Coastguard Worker 
316*acea8879SAndroid Build Coastguard Worker     std::string script1("file_getprop(\"" + std::string(temp_file2.path) +
317*acea8879SAndroid Build Coastguard Worker                        "\", \"ro.product.name\")");
318*acea8879SAndroid Build Coastguard Worker     expect("tardis", script1, kNoCause);
319*acea8879SAndroid Build Coastguard Worker 
320*acea8879SAndroid Build Coastguard Worker     std::string script2("file_getprop(\"" + std::string(temp_file2.path) +
321*acea8879SAndroid Build Coastguard Worker                        "\", \"ro.product.board\")");
322*acea8879SAndroid Build Coastguard Worker     expect("magic", script2, kNoCause);
323*acea8879SAndroid Build Coastguard Worker 
324*acea8879SAndroid Build Coastguard Worker     // No match.
325*acea8879SAndroid Build Coastguard Worker     std::string script3("file_getprop(\"" + std::string(temp_file2.path) +
326*acea8879SAndroid Build Coastguard Worker                        "\", \"ro.product.wrong\")");
327*acea8879SAndroid Build Coastguard Worker     expect("", script3, kNoCause);
328*acea8879SAndroid Build Coastguard Worker 
329*acea8879SAndroid Build Coastguard Worker     std::string script4("file_getprop(\"" + std::string(temp_file2.path) +
330*acea8879SAndroid Build Coastguard Worker                        "\", \"ro.product.name=\")");
331*acea8879SAndroid Build Coastguard Worker     expect("", script4, kNoCause);
332*acea8879SAndroid Build Coastguard Worker 
333*acea8879SAndroid Build Coastguard Worker     std::string script5("file_getprop(\"" + std::string(temp_file2.path) +
334*acea8879SAndroid Build Coastguard Worker                        "\", \"ro.product.nam\")");
335*acea8879SAndroid Build Coastguard Worker     expect("", script5, kNoCause);
336*acea8879SAndroid Build Coastguard Worker 
337*acea8879SAndroid Build Coastguard Worker     std::string script6("file_getprop(\"" + std::string(temp_file2.path) +
338*acea8879SAndroid Build Coastguard Worker                        "\", \"ro.product.model\")");
339*acea8879SAndroid Build Coastguard Worker     expect("", script6, kNoCause);
340*acea8879SAndroid Build Coastguard Worker }
341*acea8879SAndroid Build Coastguard Worker 
342*acea8879SAndroid Build Coastguard Worker // TODO: Test extracting to block device.
TEST_F(UpdaterTest,package_extract_file)343*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, package_extract_file) {
344*acea8879SAndroid Build Coastguard Worker   // package_extract_file expects 1 or 2 arguments.
345*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "package_extract_file()", kArgsParsingFailure);
346*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "package_extract_file(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
347*acea8879SAndroid Build Coastguard Worker 
348*acea8879SAndroid Build Coastguard Worker   std::string zip_path = from_testdata_base("ziptest_valid.zip");
349*acea8879SAndroid Build Coastguard Worker   ZipArchiveHandle handle;
350*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, OpenArchive(zip_path.c_str(), &handle));
351*acea8879SAndroid Build Coastguard Worker 
352*acea8879SAndroid Build Coastguard Worker   // Need to set up the ziphandle.
353*acea8879SAndroid Build Coastguard Worker   SetUpdaterOtaPackageHandle(handle);
354*acea8879SAndroid Build Coastguard Worker 
355*acea8879SAndroid Build Coastguard Worker   // Two-argument version.
356*acea8879SAndroid Build Coastguard Worker   TemporaryFile temp_file1;
357*acea8879SAndroid Build Coastguard Worker   std::string script("package_extract_file(\"a.txt\", \"" + std::string(temp_file1.path) + "\")");
358*acea8879SAndroid Build Coastguard Worker   expect("t", script, kNoCause, &updater_);
359*acea8879SAndroid Build Coastguard Worker 
360*acea8879SAndroid Build Coastguard Worker   // Verify the extracted entry.
361*acea8879SAndroid Build Coastguard Worker   std::string data;
362*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(temp_file1.path, &data));
363*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(kATxtContents, data);
364*acea8879SAndroid Build Coastguard Worker 
365*acea8879SAndroid Build Coastguard Worker   // Now extract another entry to the same location, which should overwrite.
366*acea8879SAndroid Build Coastguard Worker   script = "package_extract_file(\"b.txt\", \"" + std::string(temp_file1.path) + "\")";
367*acea8879SAndroid Build Coastguard Worker   expect("t", script, kNoCause, &updater_);
368*acea8879SAndroid Build Coastguard Worker 
369*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(temp_file1.path, &data));
370*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(kBTxtContents, data);
371*acea8879SAndroid Build Coastguard Worker 
372*acea8879SAndroid Build Coastguard Worker   // Missing zip entry. The two-argument version doesn't abort.
373*acea8879SAndroid Build Coastguard Worker   script = "package_extract_file(\"doesntexist\", \"" + std::string(temp_file1.path) + "\")";
374*acea8879SAndroid Build Coastguard Worker   expect("", script, kNoCause, &updater_);
375*acea8879SAndroid Build Coastguard Worker 
376*acea8879SAndroid Build Coastguard Worker   // Extract to /dev/full should fail.
377*acea8879SAndroid Build Coastguard Worker   script = "package_extract_file(\"a.txt\", \"/dev/full\")";
378*acea8879SAndroid Build Coastguard Worker   expect("", script, kNoCause, &updater_);
379*acea8879SAndroid Build Coastguard Worker 
380*acea8879SAndroid Build Coastguard Worker   // One-argument version. package_extract_file() gives a VAL_BLOB, which needs to be converted to
381*acea8879SAndroid Build Coastguard Worker   // VAL_STRING for equality test.
382*acea8879SAndroid Build Coastguard Worker   script = "blob_to_string(package_extract_file(\"a.txt\")) == \"" + kATxtContents + "\"";
383*acea8879SAndroid Build Coastguard Worker   expect("t", script, kNoCause, &updater_);
384*acea8879SAndroid Build Coastguard Worker 
385*acea8879SAndroid Build Coastguard Worker   script = "blob_to_string(package_extract_file(\"b.txt\")) == \"" + kBTxtContents + "\"";
386*acea8879SAndroid Build Coastguard Worker   expect("t", script, kNoCause, &updater_);
387*acea8879SAndroid Build Coastguard Worker 
388*acea8879SAndroid Build Coastguard Worker   // Missing entry. The one-argument version aborts the evaluation.
389*acea8879SAndroid Build Coastguard Worker   script = "package_extract_file(\"doesntexist\")";
390*acea8879SAndroid Build Coastguard Worker   expect(nullptr, script, kPackageExtractFileFailure, &updater_);
391*acea8879SAndroid Build Coastguard Worker }
392*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,read_file)393*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, read_file) {
394*acea8879SAndroid Build Coastguard Worker   // read_file() expects one argument.
395*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "read_file()", kArgsParsingFailure);
396*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "read_file(\"arg1\", \"arg2\")", kArgsParsingFailure);
397*acea8879SAndroid Build Coastguard Worker 
398*acea8879SAndroid Build Coastguard Worker   // Write some value to file and read back.
399*acea8879SAndroid Build Coastguard Worker   TemporaryFile temp_file;
400*acea8879SAndroid Build Coastguard Worker   std::string script("write_value(\"foo\", \""s + temp_file.path + "\");");
401*acea8879SAndroid Build Coastguard Worker   expect("t", script, kNoCause);
402*acea8879SAndroid Build Coastguard Worker 
403*acea8879SAndroid Build Coastguard Worker   script = "read_file(\""s + temp_file.path + "\") == \"foo\"";
404*acea8879SAndroid Build Coastguard Worker   expect("t", script, kNoCause);
405*acea8879SAndroid Build Coastguard Worker 
406*acea8879SAndroid Build Coastguard Worker   script = "read_file(\""s + temp_file.path + "\") == \"bar\"";
407*acea8879SAndroid Build Coastguard Worker   expect("", script, kNoCause);
408*acea8879SAndroid Build Coastguard Worker 
409*acea8879SAndroid Build Coastguard Worker   // It should fail gracefully when read fails.
410*acea8879SAndroid Build Coastguard Worker   script = "read_file(\"/doesntexist\")";
411*acea8879SAndroid Build Coastguard Worker   expect("", script, kNoCause);
412*acea8879SAndroid Build Coastguard Worker }
413*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,compute_hash_tree_smoke)414*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, compute_hash_tree_smoke) {
415*acea8879SAndroid Build Coastguard Worker   std::string data;
416*acea8879SAndroid Build Coastguard Worker   for (unsigned char i = 0; i < 128; i++) {
417*acea8879SAndroid Build Coastguard Worker     data += std::string(4096, i);
418*acea8879SAndroid Build Coastguard Worker   }
419*acea8879SAndroid Build Coastguard Worker   // Appends an additional block for verity data.
420*acea8879SAndroid Build Coastguard Worker   data += std::string(4096, 0);
421*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(129 * 4096, data.size());
422*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(data, image_file_));
423*acea8879SAndroid Build Coastguard Worker 
424*acea8879SAndroid Build Coastguard Worker   std::string salt = "aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7";
425*acea8879SAndroid Build Coastguard Worker   std::string expected_root_hash =
426*acea8879SAndroid Build Coastguard Worker       "7e0a8d8747f54384014ab996f5b2dc4eb7ff00c630eede7134c9e3f05c0dd8ca";
427*acea8879SAndroid Build Coastguard Worker   // hash_tree_ranges, source_ranges, hash_algorithm, salt_hex, root_hash
428*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> tokens{ "compute_hash_tree", "2,128,129", "2,0,128", "sha256", salt,
429*acea8879SAndroid Build Coastguard Worker                                    expected_root_hash };
430*acea8879SAndroid Build Coastguard Worker   std::string hash_tree_command = android::base::Join(tokens, " ");
431*acea8879SAndroid Build Coastguard Worker 
432*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> transfer_list{
433*acea8879SAndroid Build Coastguard Worker     "4", "2", "0", "2", hash_tree_command,
434*acea8879SAndroid Build Coastguard Worker   };
435*acea8879SAndroid Build Coastguard Worker 
436*acea8879SAndroid Build Coastguard Worker   PackageEntries entries{
437*acea8879SAndroid Build Coastguard Worker     { "new_data", "" },
438*acea8879SAndroid Build Coastguard Worker     { "patch_data", "" },
439*acea8879SAndroid Build Coastguard Worker     { "transfer_list", android::base::Join(transfer_list, "\n") },
440*acea8879SAndroid Build Coastguard Worker   };
441*acea8879SAndroid Build Coastguard Worker 
442*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "t");
443*acea8879SAndroid Build Coastguard Worker 
444*acea8879SAndroid Build Coastguard Worker   std::string updated;
445*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(image_file_, &updated));
446*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(129 * 4096, updated.size());
447*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(data.substr(0, 128 * 4096), updated.substr(0, 128 * 4096));
448*acea8879SAndroid Build Coastguard Worker 
449*acea8879SAndroid Build Coastguard Worker   // Computes the SHA256 of the salt + hash_tree_data and expects the result to match with the
450*acea8879SAndroid Build Coastguard Worker   // root_hash.
451*acea8879SAndroid Build Coastguard Worker   std::vector<unsigned char> salt_bytes;
452*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(HashTreeBuilder::ParseBytesArrayFromString(salt, &salt_bytes));
453*acea8879SAndroid Build Coastguard Worker   std::vector<unsigned char> hash_tree = std::move(salt_bytes);
454*acea8879SAndroid Build Coastguard Worker   hash_tree.insert(hash_tree.end(), updated.begin() + 128 * 4096, updated.end());
455*acea8879SAndroid Build Coastguard Worker 
456*acea8879SAndroid Build Coastguard Worker   std::vector<unsigned char> digest(SHA256_DIGEST_LENGTH);
457*acea8879SAndroid Build Coastguard Worker   SHA256(hash_tree.data(), hash_tree.size(), digest.data());
458*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(expected_root_hash, HashTreeBuilder::BytesArrayToString(digest));
459*acea8879SAndroid Build Coastguard Worker }
460*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,compute_hash_tree_root_mismatch)461*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, compute_hash_tree_root_mismatch) {
462*acea8879SAndroid Build Coastguard Worker   std::string data;
463*acea8879SAndroid Build Coastguard Worker   for (size_t i = 0; i < 128; i++) {
464*acea8879SAndroid Build Coastguard Worker     data += std::string(4096, i);
465*acea8879SAndroid Build Coastguard Worker   }
466*acea8879SAndroid Build Coastguard Worker   // Appends an additional block for verity data.
467*acea8879SAndroid Build Coastguard Worker   data += std::string(4096, 0);
468*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(129 * 4096, data.size());
469*acea8879SAndroid Build Coastguard Worker   // Corrupts one bit
470*acea8879SAndroid Build Coastguard Worker   data[4096] = 'A';
471*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(data, image_file_));
472*acea8879SAndroid Build Coastguard Worker 
473*acea8879SAndroid Build Coastguard Worker   std::string salt = "aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7";
474*acea8879SAndroid Build Coastguard Worker   std::string expected_root_hash =
475*acea8879SAndroid Build Coastguard Worker       "7e0a8d8747f54384014ab996f5b2dc4eb7ff00c630eede7134c9e3f05c0dd8ca";
476*acea8879SAndroid Build Coastguard Worker   // hash_tree_ranges, source_ranges, hash_algorithm, salt_hex, root_hash
477*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> tokens{ "compute_hash_tree", "2,128,129", "2,0,128", "sha256", salt,
478*acea8879SAndroid Build Coastguard Worker                                    expected_root_hash };
479*acea8879SAndroid Build Coastguard Worker   std::string hash_tree_command = android::base::Join(tokens, " ");
480*acea8879SAndroid Build Coastguard Worker 
481*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> transfer_list{
482*acea8879SAndroid Build Coastguard Worker     "4", "2", "0", "2", hash_tree_command,
483*acea8879SAndroid Build Coastguard Worker   };
484*acea8879SAndroid Build Coastguard Worker 
485*acea8879SAndroid Build Coastguard Worker   PackageEntries entries{
486*acea8879SAndroid Build Coastguard Worker     { "new_data", "" },
487*acea8879SAndroid Build Coastguard Worker     { "patch_data", "" },
488*acea8879SAndroid Build Coastguard Worker     { "transfer_list", android::base::Join(transfer_list, "\n") },
489*acea8879SAndroid Build Coastguard Worker   };
490*acea8879SAndroid Build Coastguard Worker 
491*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "", kHashTreeComputationFailure);
492*acea8879SAndroid Build Coastguard Worker }
493*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,write_value)494*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, write_value) {
495*acea8879SAndroid Build Coastguard Worker   // write_value() expects two arguments.
496*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "write_value()", kArgsParsingFailure);
497*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "write_value(\"arg1\")", kArgsParsingFailure);
498*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "write_value(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
499*acea8879SAndroid Build Coastguard Worker 
500*acea8879SAndroid Build Coastguard Worker   // filename cannot be empty.
501*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "write_value(\"value\", \"\")", kArgsParsingFailure);
502*acea8879SAndroid Build Coastguard Worker 
503*acea8879SAndroid Build Coastguard Worker   // Write some value to file.
504*acea8879SAndroid Build Coastguard Worker   TemporaryFile temp_file;
505*acea8879SAndroid Build Coastguard Worker   std::string value = "magicvalue";
506*acea8879SAndroid Build Coastguard Worker   std::string script("write_value(\"" + value + "\", \"" + std::string(temp_file.path) + "\")");
507*acea8879SAndroid Build Coastguard Worker   expect("t", script, kNoCause);
508*acea8879SAndroid Build Coastguard Worker 
509*acea8879SAndroid Build Coastguard Worker   // Verify the content.
510*acea8879SAndroid Build Coastguard Worker   std::string content;
511*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(temp_file.path, &content));
512*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(value, content);
513*acea8879SAndroid Build Coastguard Worker 
514*acea8879SAndroid Build Coastguard Worker   // Allow writing empty string.
515*acea8879SAndroid Build Coastguard Worker   script = "write_value(\"\", \"" + std::string(temp_file.path) + "\")";
516*acea8879SAndroid Build Coastguard Worker   expect("t", script, kNoCause);
517*acea8879SAndroid Build Coastguard Worker 
518*acea8879SAndroid Build Coastguard Worker   // Verify the content.
519*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(temp_file.path, &content));
520*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ("", content);
521*acea8879SAndroid Build Coastguard Worker 
522*acea8879SAndroid Build Coastguard Worker   // It should fail gracefully when write fails.
523*acea8879SAndroid Build Coastguard Worker   script = "write_value(\"value\", \"/proc/0/file1\")";
524*acea8879SAndroid Build Coastguard Worker   expect("", script, kNoCause);
525*acea8879SAndroid Build Coastguard Worker }
526*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,get_stage)527*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, get_stage) {
528*acea8879SAndroid Build Coastguard Worker   // get_stage() expects one argument.
529*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "get_stage()", kArgsParsingFailure);
530*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "get_stage(\"arg1\", \"arg2\")", kArgsParsingFailure);
531*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "get_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
532*acea8879SAndroid Build Coastguard Worker 
533*acea8879SAndroid Build Coastguard Worker   // Set up a local file as BCB.
534*acea8879SAndroid Build Coastguard Worker   TemporaryFile tf;
535*acea8879SAndroid Build Coastguard Worker   std::string temp_file(tf.path);
536*acea8879SAndroid Build Coastguard Worker   bootloader_message boot;
537*acea8879SAndroid Build Coastguard Worker   strlcpy(boot.stage, "2/3", sizeof(boot.stage));
538*acea8879SAndroid Build Coastguard Worker   std::string err;
539*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err));
540*acea8879SAndroid Build Coastguard Worker 
541*acea8879SAndroid Build Coastguard Worker   // Can read the stage value.
542*acea8879SAndroid Build Coastguard Worker   std::string script("get_stage(\"" + temp_file + "\")");
543*acea8879SAndroid Build Coastguard Worker   expect("2/3", script, kNoCause);
544*acea8879SAndroid Build Coastguard Worker 
545*acea8879SAndroid Build Coastguard Worker   // Bad BCB path.
546*acea8879SAndroid Build Coastguard Worker   script = "get_stage(\"doesntexist\")";
547*acea8879SAndroid Build Coastguard Worker   expect("", script, kNoCause);
548*acea8879SAndroid Build Coastguard Worker }
549*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,set_stage)550*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, set_stage) {
551*acea8879SAndroid Build Coastguard Worker   // set_stage() expects two arguments.
552*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "set_stage()", kArgsParsingFailure);
553*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "set_stage(\"arg1\")", kArgsParsingFailure);
554*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "set_stage(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
555*acea8879SAndroid Build Coastguard Worker 
556*acea8879SAndroid Build Coastguard Worker   // Set up a local file as BCB.
557*acea8879SAndroid Build Coastguard Worker   TemporaryFile tf;
558*acea8879SAndroid Build Coastguard Worker   std::string temp_file(tf.path);
559*acea8879SAndroid Build Coastguard Worker   bootloader_message boot;
560*acea8879SAndroid Build Coastguard Worker   strlcpy(boot.command, "command", sizeof(boot.command));
561*acea8879SAndroid Build Coastguard Worker   strlcpy(boot.stage, "2/3", sizeof(boot.stage));
562*acea8879SAndroid Build Coastguard Worker   std::string err;
563*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(write_bootloader_message_to(boot, temp_file, &err));
564*acea8879SAndroid Build Coastguard Worker 
565*acea8879SAndroid Build Coastguard Worker   // Write with set_stage().
566*acea8879SAndroid Build Coastguard Worker   std::string script("set_stage(\"" + temp_file + "\", \"1/3\")");
567*acea8879SAndroid Build Coastguard Worker   expect(tf.path, script, kNoCause);
568*acea8879SAndroid Build Coastguard Worker 
569*acea8879SAndroid Build Coastguard Worker   // Verify.
570*acea8879SAndroid Build Coastguard Worker   bootloader_message boot_verify;
571*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(read_bootloader_message_from(&boot_verify, temp_file, &err));
572*acea8879SAndroid Build Coastguard Worker 
573*acea8879SAndroid Build Coastguard Worker   // Stage should be updated, with command part untouched.
574*acea8879SAndroid Build Coastguard Worker   ASSERT_STREQ("1/3", boot_verify.stage);
575*acea8879SAndroid Build Coastguard Worker   ASSERT_STREQ(boot.command, boot_verify.command);
576*acea8879SAndroid Build Coastguard Worker 
577*acea8879SAndroid Build Coastguard Worker   // Bad BCB path.
578*acea8879SAndroid Build Coastguard Worker   script = "set_stage(\"doesntexist\", \"1/3\")";
579*acea8879SAndroid Build Coastguard Worker   expect("", script, kNoCause);
580*acea8879SAndroid Build Coastguard Worker 
581*acea8879SAndroid Build Coastguard Worker   script = "set_stage(\"/dev/full\", \"1/3\")";
582*acea8879SAndroid Build Coastguard Worker   expect("", script, kNoCause);
583*acea8879SAndroid Build Coastguard Worker }
584*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,set_progress)585*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, set_progress) {
586*acea8879SAndroid Build Coastguard Worker   // set_progress() expects one argument.
587*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "set_progress()", kArgsParsingFailure);
588*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "set_progress(\"arg1\", \"arg2\")", kArgsParsingFailure);
589*acea8879SAndroid Build Coastguard Worker 
590*acea8879SAndroid Build Coastguard Worker   // Invalid progress argument.
591*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "set_progress(\"arg1\")", kArgsParsingFailure);
592*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "set_progress(\"3x+5\")", kArgsParsingFailure);
593*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "set_progress(\".3.5\")", kArgsParsingFailure);
594*acea8879SAndroid Build Coastguard Worker 
595*acea8879SAndroid Build Coastguard Worker   TemporaryFile tf;
596*acea8879SAndroid Build Coastguard Worker   SetUpdaterCmdPipe(tf.release());
597*acea8879SAndroid Build Coastguard Worker   expect(".52", "set_progress(\".52\")", kNoCause, &updater_);
598*acea8879SAndroid Build Coastguard Worker   FlushUpdaterCommandPipe();
599*acea8879SAndroid Build Coastguard Worker 
600*acea8879SAndroid Build Coastguard Worker   std::string cmd;
601*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(tf.path, &cmd));
602*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(android::base::StringPrintf("set_progress %f\n", .52), cmd);
603*acea8879SAndroid Build Coastguard Worker   // recovery-updater protocol expects 2 tokens ("set_progress <frac>").
604*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(2U, android::base::Split(cmd, " ").size());
605*acea8879SAndroid Build Coastguard Worker }
606*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,show_progress)607*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, show_progress) {
608*acea8879SAndroid Build Coastguard Worker   // show_progress() expects two arguments.
609*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "show_progress()", kArgsParsingFailure);
610*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "show_progress(\"arg1\")", kArgsParsingFailure);
611*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "show_progress(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure);
612*acea8879SAndroid Build Coastguard Worker 
613*acea8879SAndroid Build Coastguard Worker   // Invalid progress arguments.
614*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "show_progress(\"arg1\", \"arg2\")", kArgsParsingFailure);
615*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "show_progress(\"3x+5\", \"10\")", kArgsParsingFailure);
616*acea8879SAndroid Build Coastguard Worker   expect(nullptr, "show_progress(\".3\", \"5a\")", kArgsParsingFailure);
617*acea8879SAndroid Build Coastguard Worker 
618*acea8879SAndroid Build Coastguard Worker   TemporaryFile tf;
619*acea8879SAndroid Build Coastguard Worker   SetUpdaterCmdPipe(tf.release());
620*acea8879SAndroid Build Coastguard Worker   expect(".52", "show_progress(\".52\", \"10\")", kNoCause, &updater_);
621*acea8879SAndroid Build Coastguard Worker   FlushUpdaterCommandPipe();
622*acea8879SAndroid Build Coastguard Worker 
623*acea8879SAndroid Build Coastguard Worker   std::string cmd;
624*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(tf.path, &cmd));
625*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(android::base::StringPrintf("progress %f %d\n", .52, 10), cmd);
626*acea8879SAndroid Build Coastguard Worker   // recovery-updater protocol expects 3 tokens ("progress <frac> <secs>").
627*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(3U, android::base::Split(cmd, " ").size());
628*acea8879SAndroid Build Coastguard Worker }
629*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,block_image_update_parsing_error)630*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, block_image_update_parsing_error) {
631*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> transfer_list{
632*acea8879SAndroid Build Coastguard Worker     // clang-format off
633*acea8879SAndroid Build Coastguard Worker     "4",
634*acea8879SAndroid Build Coastguard Worker     "2",
635*acea8879SAndroid Build Coastguard Worker     "0",
636*acea8879SAndroid Build Coastguard Worker     // clang-format on
637*acea8879SAndroid Build Coastguard Worker   };
638*acea8879SAndroid Build Coastguard Worker 
639*acea8879SAndroid Build Coastguard Worker   PackageEntries entries{
640*acea8879SAndroid Build Coastguard Worker     { "new_data", "" },
641*acea8879SAndroid Build Coastguard Worker     { "patch_data", "" },
642*acea8879SAndroid Build Coastguard Worker     { "transfer_list", android::base::Join(transfer_list, '\n') },
643*acea8879SAndroid Build Coastguard Worker   };
644*acea8879SAndroid Build Coastguard Worker 
645*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "", kArgsParsingFailure);
646*acea8879SAndroid Build Coastguard Worker }
647*acea8879SAndroid Build Coastguard Worker 
648*acea8879SAndroid Build Coastguard Worker // Generates the bsdiff of the given source and target images, and writes the result entries.
649*acea8879SAndroid Build Coastguard Worker // target_blocks specifies the block count to be written into the `bsdiff` command, which may be
650*acea8879SAndroid Build Coastguard Worker // different from the given target size in order to trigger overrun / underrun paths.
GetEntriesForBsdiff(std::string_view source,std::string_view target,size_t target_blocks,PackageEntries * entries)651*acea8879SAndroid Build Coastguard Worker static void GetEntriesForBsdiff(std::string_view source, std::string_view target,
652*acea8879SAndroid Build Coastguard Worker                                 size_t target_blocks, PackageEntries* entries) {
653*acea8879SAndroid Build Coastguard Worker   // Generate the patch data.
654*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file;
655*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, bsdiff::bsdiff(reinterpret_cast<const uint8_t*>(source.data()), source.size(),
656*acea8879SAndroid Build Coastguard Worker                               reinterpret_cast<const uint8_t*>(target.data()), target.size(),
657*acea8879SAndroid Build Coastguard Worker                               patch_file.path, nullptr));
658*acea8879SAndroid Build Coastguard Worker   std::string patch_content;
659*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch_content));
660*acea8879SAndroid Build Coastguard Worker 
661*acea8879SAndroid Build Coastguard Worker   // Create the transfer list that contains a bsdiff.
662*acea8879SAndroid Build Coastguard Worker   std::string src_hash = GetSha1(source);
663*acea8879SAndroid Build Coastguard Worker   std::string tgt_hash = GetSha1(target);
664*acea8879SAndroid Build Coastguard Worker   size_t source_blocks = source.size() / 4096;
665*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> transfer_list{
666*acea8879SAndroid Build Coastguard Worker     // clang-format off
667*acea8879SAndroid Build Coastguard Worker     "4",
668*acea8879SAndroid Build Coastguard Worker     std::to_string(target_blocks),
669*acea8879SAndroid Build Coastguard Worker     "0",
670*acea8879SAndroid Build Coastguard Worker     "0",
671*acea8879SAndroid Build Coastguard Worker     // bsdiff patch_offset patch_length source_hash target_hash target_range source_block_count
672*acea8879SAndroid Build Coastguard Worker     // source_range
673*acea8879SAndroid Build Coastguard Worker     android::base::StringPrintf("bsdiff 0 %zu %s %s 2,0,%zu %zu 2,0,%zu", patch_content.size(),
674*acea8879SAndroid Build Coastguard Worker                                 src_hash.c_str(), tgt_hash.c_str(), target_blocks, source_blocks,
675*acea8879SAndroid Build Coastguard Worker                                 source_blocks),
676*acea8879SAndroid Build Coastguard Worker     // clang-format on
677*acea8879SAndroid Build Coastguard Worker   };
678*acea8879SAndroid Build Coastguard Worker 
679*acea8879SAndroid Build Coastguard Worker   *entries = {
680*acea8879SAndroid Build Coastguard Worker     { "new_data", "" },
681*acea8879SAndroid Build Coastguard Worker     { "patch_data", patch_content },
682*acea8879SAndroid Build Coastguard Worker     { "transfer_list", android::base::Join(transfer_list, '\n') },
683*acea8879SAndroid Build Coastguard Worker   };
684*acea8879SAndroid Build Coastguard Worker }
685*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,block_image_update_patch_data)686*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, block_image_update_patch_data) {
687*acea8879SAndroid Build Coastguard Worker   // Both source and target images have 10 blocks.
688*acea8879SAndroid Build Coastguard Worker   std::string source =
689*acea8879SAndroid Build Coastguard Worker       std::string(4096, 'a') + std::string(4096, 'c') + std::string(4096 * 3, '\0');
690*acea8879SAndroid Build Coastguard Worker   std::string target =
691*acea8879SAndroid Build Coastguard Worker       std::string(4096, 'b') + std::string(4096, 'd') + std::string(4096 * 3, '\0');
692*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(source, image_file_));
693*acea8879SAndroid Build Coastguard Worker 
694*acea8879SAndroid Build Coastguard Worker   PackageEntries entries;
695*acea8879SAndroid Build Coastguard Worker   GetEntriesForBsdiff(std::string_view(source).substr(0, 4096 * 2),
696*acea8879SAndroid Build Coastguard Worker                       std::string_view(target).substr(0, 4096 * 2), 2, &entries);
697*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "t");
698*acea8879SAndroid Build Coastguard Worker 
699*acea8879SAndroid Build Coastguard Worker   // The update_file should be patched correctly.
700*acea8879SAndroid Build Coastguard Worker   std::string updated;
701*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(image_file_, &updated));
702*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(target, updated);
703*acea8879SAndroid Build Coastguard Worker }
704*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,block_image_update_patch_overrun)705*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, block_image_update_patch_overrun) {
706*acea8879SAndroid Build Coastguard Worker   // Both source and target images have 10 blocks.
707*acea8879SAndroid Build Coastguard Worker   std::string source =
708*acea8879SAndroid Build Coastguard Worker       std::string(4096, 'a') + std::string(4096, 'c') + std::string(4096 * 3, '\0');
709*acea8879SAndroid Build Coastguard Worker   std::string target =
710*acea8879SAndroid Build Coastguard Worker       std::string(4096, 'b') + std::string(4096, 'd') + std::string(4096 * 3, '\0');
711*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(source, image_file_));
712*acea8879SAndroid Build Coastguard Worker 
713*acea8879SAndroid Build Coastguard Worker   // Provide one less block to trigger the overrun path.
714*acea8879SAndroid Build Coastguard Worker   PackageEntries entries;
715*acea8879SAndroid Build Coastguard Worker   GetEntriesForBsdiff(std::string_view(source).substr(0, 4096 * 2),
716*acea8879SAndroid Build Coastguard Worker                       std::string_view(target).substr(0, 4096 * 2), 1, &entries);
717*acea8879SAndroid Build Coastguard Worker 
718*acea8879SAndroid Build Coastguard Worker   // The update should fail due to overrun.
719*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "", kPatchApplicationFailure);
720*acea8879SAndroid Build Coastguard Worker }
721*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,block_image_update_patch_underrun)722*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, block_image_update_patch_underrun) {
723*acea8879SAndroid Build Coastguard Worker   // Both source and target images have 10 blocks.
724*acea8879SAndroid Build Coastguard Worker   std::string source =
725*acea8879SAndroid Build Coastguard Worker       std::string(4096, 'a') + std::string(4096, 'c') + std::string(4096 * 3, '\0');
726*acea8879SAndroid Build Coastguard Worker   std::string target =
727*acea8879SAndroid Build Coastguard Worker       std::string(4096, 'b') + std::string(4096, 'd') + std::string(4096 * 3, '\0');
728*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(source, image_file_));
729*acea8879SAndroid Build Coastguard Worker 
730*acea8879SAndroid Build Coastguard Worker   // Provide one more block to trigger the overrun path.
731*acea8879SAndroid Build Coastguard Worker   PackageEntries entries;
732*acea8879SAndroid Build Coastguard Worker   GetEntriesForBsdiff(std::string_view(source).substr(0, 4096 * 2),
733*acea8879SAndroid Build Coastguard Worker                       std::string_view(target).substr(0, 4096 * 2), 3, &entries);
734*acea8879SAndroid Build Coastguard Worker 
735*acea8879SAndroid Build Coastguard Worker   // The update should fail due to underrun.
736*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "", kPatchApplicationFailure);
737*acea8879SAndroid Build Coastguard Worker }
738*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,block_image_update_fail)739*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, block_image_update_fail) {
740*acea8879SAndroid Build Coastguard Worker   std::string src_content(4096 * 2, 'e');
741*acea8879SAndroid Build Coastguard Worker   std::string src_hash = GetSha1(src_content);
742*acea8879SAndroid Build Coastguard Worker   // Stash and free some blocks, then fail the update intentionally.
743*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> transfer_list{
744*acea8879SAndroid Build Coastguard Worker     // clang-format off
745*acea8879SAndroid Build Coastguard Worker     "4",
746*acea8879SAndroid Build Coastguard Worker     "2",
747*acea8879SAndroid Build Coastguard Worker     "0",
748*acea8879SAndroid Build Coastguard Worker     "2",
749*acea8879SAndroid Build Coastguard Worker     "stash " + src_hash + " 2,0,2",
750*acea8879SAndroid Build Coastguard Worker     "free " + src_hash,
751*acea8879SAndroid Build Coastguard Worker     "abort",
752*acea8879SAndroid Build Coastguard Worker     // clang-format on
753*acea8879SAndroid Build Coastguard Worker   };
754*acea8879SAndroid Build Coastguard Worker 
755*acea8879SAndroid Build Coastguard Worker   // Add a new data of 10 bytes to test the deadlock.
756*acea8879SAndroid Build Coastguard Worker   PackageEntries entries{
757*acea8879SAndroid Build Coastguard Worker     { "new_data", std::string(10, 0) },
758*acea8879SAndroid Build Coastguard Worker     { "patch_data", "" },
759*acea8879SAndroid Build Coastguard Worker     { "transfer_list", android::base::Join(transfer_list, '\n') },
760*acea8879SAndroid Build Coastguard Worker   };
761*acea8879SAndroid Build Coastguard Worker 
762*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(src_content, image_file_));
763*acea8879SAndroid Build Coastguard Worker 
764*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "");
765*acea8879SAndroid Build Coastguard Worker 
766*acea8879SAndroid Build Coastguard Worker   // Updater generates the stash name based on the input file name.
767*acea8879SAndroid Build Coastguard Worker   std::string name_digest = GetSha1(image_file_);
768*acea8879SAndroid Build Coastguard Worker   std::string stash_base = std::string(temp_stash_base_.path) + "/" + name_digest;
769*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, access(stash_base.c_str(), F_OK));
770*acea8879SAndroid Build Coastguard Worker   // Expect the stashed blocks to be freed.
771*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(-1, access((stash_base + src_hash).c_str(), F_OK));
772*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(0, rmdir(stash_base.c_str()));
773*acea8879SAndroid Build Coastguard Worker }
774*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,new_data_over_write)775*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, new_data_over_write) {
776*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> transfer_list{
777*acea8879SAndroid Build Coastguard Worker     // clang-format off
778*acea8879SAndroid Build Coastguard Worker     "4",
779*acea8879SAndroid Build Coastguard Worker     "1",
780*acea8879SAndroid Build Coastguard Worker     "0",
781*acea8879SAndroid Build Coastguard Worker     "0",
782*acea8879SAndroid Build Coastguard Worker     "new 2,0,1",
783*acea8879SAndroid Build Coastguard Worker     // clang-format on
784*acea8879SAndroid Build Coastguard Worker   };
785*acea8879SAndroid Build Coastguard Worker 
786*acea8879SAndroid Build Coastguard Worker   // Write 4096 + 100 bytes of new data.
787*acea8879SAndroid Build Coastguard Worker   PackageEntries entries{
788*acea8879SAndroid Build Coastguard Worker     { "new_data", std::string(4196, 0) },
789*acea8879SAndroid Build Coastguard Worker     { "patch_data", "" },
790*acea8879SAndroid Build Coastguard Worker     { "transfer_list", android::base::Join(transfer_list, '\n') },
791*acea8879SAndroid Build Coastguard Worker   };
792*acea8879SAndroid Build Coastguard Worker 
793*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "t");
794*acea8879SAndroid Build Coastguard Worker }
795*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,new_data_short_write)796*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, new_data_short_write) {
797*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> transfer_list{
798*acea8879SAndroid Build Coastguard Worker     // clang-format off
799*acea8879SAndroid Build Coastguard Worker     "4",
800*acea8879SAndroid Build Coastguard Worker     "1",
801*acea8879SAndroid Build Coastguard Worker     "0",
802*acea8879SAndroid Build Coastguard Worker     "0",
803*acea8879SAndroid Build Coastguard Worker     "new 2,0,1",
804*acea8879SAndroid Build Coastguard Worker     // clang-format on
805*acea8879SAndroid Build Coastguard Worker   };
806*acea8879SAndroid Build Coastguard Worker 
807*acea8879SAndroid Build Coastguard Worker   PackageEntries entries{
808*acea8879SAndroid Build Coastguard Worker     { "patch_data", "" },
809*acea8879SAndroid Build Coastguard Worker     { "transfer_list", android::base::Join(transfer_list, '\n') },
810*acea8879SAndroid Build Coastguard Worker   };
811*acea8879SAndroid Build Coastguard Worker 
812*acea8879SAndroid Build Coastguard Worker   // Updater should report the failure gracefully rather than stuck in deadlock.
813*acea8879SAndroid Build Coastguard Worker   entries["new_data"] = "";
814*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "");
815*acea8879SAndroid Build Coastguard Worker 
816*acea8879SAndroid Build Coastguard Worker   entries["new_data"] = std::string(10, 'a');
817*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "");
818*acea8879SAndroid Build Coastguard Worker 
819*acea8879SAndroid Build Coastguard Worker   // Expect to write 1 block of new data successfully.
820*acea8879SAndroid Build Coastguard Worker   entries["new_data"] = std::string(4096, 'a');
821*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "t");
822*acea8879SAndroid Build Coastguard Worker }
823*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,brotli_new_data)824*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, brotli_new_data) {
825*acea8879SAndroid Build Coastguard Worker   auto generator = []() { return rand() % 128; };
826*acea8879SAndroid Build Coastguard Worker   // Generate 100 blocks of random data.
827*acea8879SAndroid Build Coastguard Worker   std::string brotli_new_data;
828*acea8879SAndroid Build Coastguard Worker   brotli_new_data.reserve(4096 * 100);
829*acea8879SAndroid Build Coastguard Worker   generate_n(back_inserter(brotli_new_data), 4096 * 100, generator);
830*acea8879SAndroid Build Coastguard Worker 
831*acea8879SAndroid Build Coastguard Worker   size_t encoded_size = BrotliEncoderMaxCompressedSize(brotli_new_data.size());
832*acea8879SAndroid Build Coastguard Worker   std::string encoded_data(encoded_size, 0);
833*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(BrotliEncoderCompress(
834*acea8879SAndroid Build Coastguard Worker       BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW, BROTLI_DEFAULT_MODE, brotli_new_data.size(),
835*acea8879SAndroid Build Coastguard Worker       reinterpret_cast<const uint8_t*>(brotli_new_data.data()), &encoded_size,
836*acea8879SAndroid Build Coastguard Worker       reinterpret_cast<uint8_t*>(const_cast<char*>(encoded_data.data()))));
837*acea8879SAndroid Build Coastguard Worker   encoded_data.resize(encoded_size);
838*acea8879SAndroid Build Coastguard Worker 
839*acea8879SAndroid Build Coastguard Worker   // Write a few small chunks of new data, then a large chunk, and finally a few small chunks.
840*acea8879SAndroid Build Coastguard Worker   // This helps us to catch potential short writes.
841*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> transfer_list = {
842*acea8879SAndroid Build Coastguard Worker     "4",
843*acea8879SAndroid Build Coastguard Worker     "100",
844*acea8879SAndroid Build Coastguard Worker     "0",
845*acea8879SAndroid Build Coastguard Worker     "0",
846*acea8879SAndroid Build Coastguard Worker     "new 2,0,1",
847*acea8879SAndroid Build Coastguard Worker     "new 2,1,2",
848*acea8879SAndroid Build Coastguard Worker     "new 4,2,50,50,97",
849*acea8879SAndroid Build Coastguard Worker     "new 2,97,98",
850*acea8879SAndroid Build Coastguard Worker     "new 2,98,99",
851*acea8879SAndroid Build Coastguard Worker     "new 2,99,100",
852*acea8879SAndroid Build Coastguard Worker   };
853*acea8879SAndroid Build Coastguard Worker 
854*acea8879SAndroid Build Coastguard Worker   PackageEntries entries{
855*acea8879SAndroid Build Coastguard Worker     { "new_data.br", std::move(encoded_data) },
856*acea8879SAndroid Build Coastguard Worker     { "patch_data", "" },
857*acea8879SAndroid Build Coastguard Worker     { "transfer_list", android::base::Join(transfer_list, '\n') },
858*acea8879SAndroid Build Coastguard Worker   };
859*acea8879SAndroid Build Coastguard Worker 
860*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "t");
861*acea8879SAndroid Build Coastguard Worker 
862*acea8879SAndroid Build Coastguard Worker   std::string updated_content;
863*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(image_file_, &updated_content));
864*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(brotli_new_data, updated_content);
865*acea8879SAndroid Build Coastguard Worker }
866*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,last_command_update)867*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, last_command_update) {
868*acea8879SAndroid Build Coastguard Worker   std::string block1(4096, '1');
869*acea8879SAndroid Build Coastguard Worker   std::string block2(4096, '2');
870*acea8879SAndroid Build Coastguard Worker   std::string block3(4096, '3');
871*acea8879SAndroid Build Coastguard Worker   std::string block1_hash = GetSha1(block1);
872*acea8879SAndroid Build Coastguard Worker   std::string block2_hash = GetSha1(block2);
873*acea8879SAndroid Build Coastguard Worker   std::string block3_hash = GetSha1(block3);
874*acea8879SAndroid Build Coastguard Worker 
875*acea8879SAndroid Build Coastguard Worker   // Compose the transfer list to fail the first update.
876*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> transfer_list_fail{
877*acea8879SAndroid Build Coastguard Worker     // clang-format off
878*acea8879SAndroid Build Coastguard Worker     "4",
879*acea8879SAndroid Build Coastguard Worker     "2",
880*acea8879SAndroid Build Coastguard Worker     "0",
881*acea8879SAndroid Build Coastguard Worker     "2",
882*acea8879SAndroid Build Coastguard Worker     "stash " + block1_hash + " 2,0,1",
883*acea8879SAndroid Build Coastguard Worker     "move " + block1_hash + " 2,1,2 1 2,0,1",
884*acea8879SAndroid Build Coastguard Worker     "stash " + block3_hash + " 2,2,3",
885*acea8879SAndroid Build Coastguard Worker     "abort",
886*acea8879SAndroid Build Coastguard Worker     // clang-format on
887*acea8879SAndroid Build Coastguard Worker   };
888*acea8879SAndroid Build Coastguard Worker 
889*acea8879SAndroid Build Coastguard Worker   // Mimic a resumed update with the same transfer commands.
890*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> transfer_list_continue{
891*acea8879SAndroid Build Coastguard Worker     // clang-format off
892*acea8879SAndroid Build Coastguard Worker     "4",
893*acea8879SAndroid Build Coastguard Worker     "2",
894*acea8879SAndroid Build Coastguard Worker     "0",
895*acea8879SAndroid Build Coastguard Worker     "2",
896*acea8879SAndroid Build Coastguard Worker     "stash " + block1_hash + " 2,0,1",
897*acea8879SAndroid Build Coastguard Worker     "move " + block1_hash + " 2,1,2 1 2,0,1",
898*acea8879SAndroid Build Coastguard Worker     "stash " + block3_hash + " 2,2,3",
899*acea8879SAndroid Build Coastguard Worker     "move " + block1_hash + " 2,2,3 1 2,0,1",
900*acea8879SAndroid Build Coastguard Worker     // clang-format on
901*acea8879SAndroid Build Coastguard Worker   };
902*acea8879SAndroid Build Coastguard Worker 
903*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(block1 + block2 + block3, image_file_));
904*acea8879SAndroid Build Coastguard Worker 
905*acea8879SAndroid Build Coastguard Worker   PackageEntries entries{
906*acea8879SAndroid Build Coastguard Worker     { "new_data", "" },
907*acea8879SAndroid Build Coastguard Worker     { "patch_data", "" },
908*acea8879SAndroid Build Coastguard Worker     { "transfer_list", android::base::Join(transfer_list_fail, '\n') },
909*acea8879SAndroid Build Coastguard Worker   };
910*acea8879SAndroid Build Coastguard Worker 
911*acea8879SAndroid Build Coastguard Worker   // "2\nstash " + block3_hash + " 2,2,3"
912*acea8879SAndroid Build Coastguard Worker   std::string last_command_content =
913*acea8879SAndroid Build Coastguard Worker       "2\n" + transfer_list_fail[TransferList::kTransferListHeaderLines + 2];
914*acea8879SAndroid Build Coastguard Worker 
915*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "");
916*acea8879SAndroid Build Coastguard Worker 
917*acea8879SAndroid Build Coastguard Worker   // Expect last_command to contain the last stash command.
918*acea8879SAndroid Build Coastguard Worker   std::string last_command_actual;
919*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(last_command_file_, &last_command_actual));
920*acea8879SAndroid Build Coastguard Worker   EXPECT_EQ(last_command_content, last_command_actual);
921*acea8879SAndroid Build Coastguard Worker 
922*acea8879SAndroid Build Coastguard Worker   std::string updated_contents;
923*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(image_file_, &updated_contents));
924*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(block1 + block1 + block3, updated_contents);
925*acea8879SAndroid Build Coastguard Worker 
926*acea8879SAndroid Build Coastguard Worker   // "Resume" the update. Expect the first 'move' to be skipped but the second 'move' to be
927*acea8879SAndroid Build Coastguard Worker   // executed. Note that we intentionally reset the image file.
928*acea8879SAndroid Build Coastguard Worker   entries["transfer_list"] = android::base::Join(transfer_list_continue, '\n');
929*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(block1 + block2 + block3, image_file_));
930*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "t");
931*acea8879SAndroid Build Coastguard Worker 
932*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(image_file_, &updated_contents));
933*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(block1 + block2 + block1, updated_contents);
934*acea8879SAndroid Build Coastguard Worker }
935*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,last_command_update_unresumable)936*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, last_command_update_unresumable) {
937*acea8879SAndroid Build Coastguard Worker   std::string block1(4096, '1');
938*acea8879SAndroid Build Coastguard Worker   std::string block2(4096, '2');
939*acea8879SAndroid Build Coastguard Worker   std::string block1_hash = GetSha1(block1);
940*acea8879SAndroid Build Coastguard Worker   std::string block2_hash = GetSha1(block2);
941*acea8879SAndroid Build Coastguard Worker 
942*acea8879SAndroid Build Coastguard Worker   // Construct an unresumable update with source blocks mismatch.
943*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> transfer_list_unresumable{
944*acea8879SAndroid Build Coastguard Worker     // clang-format off
945*acea8879SAndroid Build Coastguard Worker     "4",
946*acea8879SAndroid Build Coastguard Worker     "2",
947*acea8879SAndroid Build Coastguard Worker     "0",
948*acea8879SAndroid Build Coastguard Worker     "2",
949*acea8879SAndroid Build Coastguard Worker     "stash " + block1_hash + " 2,0,1",
950*acea8879SAndroid Build Coastguard Worker     "move " + block2_hash + " 2,1,2 1 2,0,1",
951*acea8879SAndroid Build Coastguard Worker     // clang-format on
952*acea8879SAndroid Build Coastguard Worker   };
953*acea8879SAndroid Build Coastguard Worker 
954*acea8879SAndroid Build Coastguard Worker   PackageEntries entries{
955*acea8879SAndroid Build Coastguard Worker     { "new_data", "" },
956*acea8879SAndroid Build Coastguard Worker     { "patch_data", "" },
957*acea8879SAndroid Build Coastguard Worker     { "transfer_list", android::base::Join(transfer_list_unresumable, '\n') },
958*acea8879SAndroid Build Coastguard Worker   };
959*acea8879SAndroid Build Coastguard Worker 
960*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(block1 + block1, image_file_));
961*acea8879SAndroid Build Coastguard Worker 
962*acea8879SAndroid Build Coastguard Worker   std::string last_command_content =
963*acea8879SAndroid Build Coastguard Worker       "0\n" + transfer_list_unresumable[TransferList::kTransferListHeaderLines];
964*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(last_command_content, last_command_file_));
965*acea8879SAndroid Build Coastguard Worker 
966*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, entries, image_file_, "");
967*acea8879SAndroid Build Coastguard Worker 
968*acea8879SAndroid Build Coastguard Worker   // The last_command_file will be deleted if the update encounters an unresumable failure later.
969*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(-1, access(last_command_file_.c_str(), R_OK));
970*acea8879SAndroid Build Coastguard Worker }
971*acea8879SAndroid Build Coastguard Worker 
TEST_F(UpdaterTest,last_command_verify)972*acea8879SAndroid Build Coastguard Worker TEST_F(UpdaterTest, last_command_verify) {
973*acea8879SAndroid Build Coastguard Worker   std::string block1(4096, '1');
974*acea8879SAndroid Build Coastguard Worker   std::string block2(4096, '2');
975*acea8879SAndroid Build Coastguard Worker   std::string block3(4096, '3');
976*acea8879SAndroid Build Coastguard Worker   std::string block1_hash = GetSha1(block1);
977*acea8879SAndroid Build Coastguard Worker   std::string block2_hash = GetSha1(block2);
978*acea8879SAndroid Build Coastguard Worker   std::string block3_hash = GetSha1(block3);
979*acea8879SAndroid Build Coastguard Worker 
980*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> transfer_list_verify{
981*acea8879SAndroid Build Coastguard Worker     // clang-format off
982*acea8879SAndroid Build Coastguard Worker     "4",
983*acea8879SAndroid Build Coastguard Worker     "2",
984*acea8879SAndroid Build Coastguard Worker     "0",
985*acea8879SAndroid Build Coastguard Worker     "2",
986*acea8879SAndroid Build Coastguard Worker     "stash " + block1_hash + " 2,0,1",
987*acea8879SAndroid Build Coastguard Worker     "move " + block1_hash + " 2,0,1 1 2,0,1",
988*acea8879SAndroid Build Coastguard Worker     "move " + block1_hash + " 2,1,2 1 2,0,1",
989*acea8879SAndroid Build Coastguard Worker     "stash " + block3_hash + " 2,2,3",
990*acea8879SAndroid Build Coastguard Worker     // clang-format on
991*acea8879SAndroid Build Coastguard Worker   };
992*acea8879SAndroid Build Coastguard Worker 
993*acea8879SAndroid Build Coastguard Worker   PackageEntries entries{
994*acea8879SAndroid Build Coastguard Worker     { "new_data", "" },
995*acea8879SAndroid Build Coastguard Worker     { "patch_data", "" },
996*acea8879SAndroid Build Coastguard Worker     { "transfer_list", android::base::Join(transfer_list_verify, '\n') },
997*acea8879SAndroid Build Coastguard Worker   };
998*acea8879SAndroid Build Coastguard Worker 
999*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(block1 + block1 + block3, image_file_));
1000*acea8879SAndroid Build Coastguard Worker 
1001*acea8879SAndroid Build Coastguard Worker   // Last command: "move " + block1_hash + " 2,1,2 1 2,0,1"
1002*acea8879SAndroid Build Coastguard Worker   std::string last_command_content =
1003*acea8879SAndroid Build Coastguard Worker       "2\n" + transfer_list_verify[TransferList::kTransferListHeaderLines + 2];
1004*acea8879SAndroid Build Coastguard Worker 
1005*acea8879SAndroid Build Coastguard Worker   // First run: expect the verification to succeed and the last_command_file is intact.
1006*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(last_command_content, last_command_file_));
1007*acea8879SAndroid Build Coastguard Worker 
1008*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(true, entries, image_file_, "t");
1009*acea8879SAndroid Build Coastguard Worker 
1010*acea8879SAndroid Build Coastguard Worker   std::string last_command_actual;
1011*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(last_command_file_, &last_command_actual));
1012*acea8879SAndroid Build Coastguard Worker   EXPECT_EQ(last_command_content, last_command_actual);
1013*acea8879SAndroid Build Coastguard Worker 
1014*acea8879SAndroid Build Coastguard Worker   // Second run with a mismatching block image: expect the verification to succeed but
1015*acea8879SAndroid Build Coastguard Worker   // last_command_file to be deleted; because the target blocks in the last command don't have the
1016*acea8879SAndroid Build Coastguard Worker   // expected contents for the second move command.
1017*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(block1 + block2 + block3, image_file_));
1018*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(true, entries, image_file_, "t");
1019*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(-1, access(last_command_file_.c_str(), R_OK));
1020*acea8879SAndroid Build Coastguard Worker }
1021*acea8879SAndroid Build Coastguard Worker 
1022*acea8879SAndroid Build Coastguard Worker class ResumableUpdaterTest : public UpdaterTestBase, public testing::TestWithParam<size_t> {
1023*acea8879SAndroid Build Coastguard Worker  protected:
SetUp()1024*acea8879SAndroid Build Coastguard Worker   void SetUp() override {
1025*acea8879SAndroid Build Coastguard Worker     UpdaterTestBase::SetUp();
1026*acea8879SAndroid Build Coastguard Worker     // Enable a special command "abort" to simulate interruption.
1027*acea8879SAndroid Build Coastguard Worker     Command::abort_allowed_ = true;
1028*acea8879SAndroid Build Coastguard Worker     index_ = GetParam();
1029*acea8879SAndroid Build Coastguard Worker   }
1030*acea8879SAndroid Build Coastguard Worker 
TearDown()1031*acea8879SAndroid Build Coastguard Worker   void TearDown() override {
1032*acea8879SAndroid Build Coastguard Worker     UpdaterTestBase::TearDown();
1033*acea8879SAndroid Build Coastguard Worker   }
1034*acea8879SAndroid Build Coastguard Worker 
1035*acea8879SAndroid Build Coastguard Worker   size_t index_;
1036*acea8879SAndroid Build Coastguard Worker };
1037*acea8879SAndroid Build Coastguard Worker 
1038*acea8879SAndroid Build Coastguard Worker static std::string g_source_image;
1039*acea8879SAndroid Build Coastguard Worker static std::string g_target_image;
1040*acea8879SAndroid Build Coastguard Worker static PackageEntries g_entries;
1041*acea8879SAndroid Build Coastguard Worker 
GenerateTransferList()1042*acea8879SAndroid Build Coastguard Worker static std::vector<std::string> GenerateTransferList() {
1043*acea8879SAndroid Build Coastguard Worker   std::string a(4096, 'a');
1044*acea8879SAndroid Build Coastguard Worker   std::string b(4096, 'b');
1045*acea8879SAndroid Build Coastguard Worker   std::string c(4096, 'c');
1046*acea8879SAndroid Build Coastguard Worker   std::string d(4096, 'd');
1047*acea8879SAndroid Build Coastguard Worker   std::string e(4096, 'e');
1048*acea8879SAndroid Build Coastguard Worker   std::string f(4096, 'f');
1049*acea8879SAndroid Build Coastguard Worker   std::string g(4096, 'g');
1050*acea8879SAndroid Build Coastguard Worker   std::string h(4096, 'h');
1051*acea8879SAndroid Build Coastguard Worker   std::string i(4096, 'i');
1052*acea8879SAndroid Build Coastguard Worker   std::string zero(4096, '\0');
1053*acea8879SAndroid Build Coastguard Worker 
1054*acea8879SAndroid Build Coastguard Worker   std::string a_hash = GetSha1(a);
1055*acea8879SAndroid Build Coastguard Worker   std::string b_hash = GetSha1(b);
1056*acea8879SAndroid Build Coastguard Worker   std::string c_hash = GetSha1(c);
1057*acea8879SAndroid Build Coastguard Worker   std::string e_hash = GetSha1(e);
1058*acea8879SAndroid Build Coastguard Worker 
1059*acea8879SAndroid Build Coastguard Worker   auto loc = [](const std::string& range_text) {
1060*acea8879SAndroid Build Coastguard Worker     std::vector<std::string> pieces = android::base::Split(range_text, "-");
1061*acea8879SAndroid Build Coastguard Worker     size_t left;
1062*acea8879SAndroid Build Coastguard Worker     size_t right;
1063*acea8879SAndroid Build Coastguard Worker     if (pieces.size() == 1) {
1064*acea8879SAndroid Build Coastguard Worker       CHECK(android::base::ParseUint(pieces[0], &left));
1065*acea8879SAndroid Build Coastguard Worker       right = left + 1;
1066*acea8879SAndroid Build Coastguard Worker     } else {
1067*acea8879SAndroid Build Coastguard Worker       CHECK_EQ(2u, pieces.size());
1068*acea8879SAndroid Build Coastguard Worker       CHECK(android::base::ParseUint(pieces[0], &left));
1069*acea8879SAndroid Build Coastguard Worker       CHECK(android::base::ParseUint(pieces[1], &right));
1070*acea8879SAndroid Build Coastguard Worker       right++;
1071*acea8879SAndroid Build Coastguard Worker     }
1072*acea8879SAndroid Build Coastguard Worker     return android::base::StringPrintf("2,%zu,%zu", left, right);
1073*acea8879SAndroid Build Coastguard Worker   };
1074*acea8879SAndroid Build Coastguard Worker 
1075*acea8879SAndroid Build Coastguard Worker   // patch 1: "b d c" -> "g"
1076*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file_bdc_g;
1077*acea8879SAndroid Build Coastguard Worker   std::string bdc = b + d + c;
1078*acea8879SAndroid Build Coastguard Worker   std::string bdc_hash = GetSha1(bdc);
1079*acea8879SAndroid Build Coastguard Worker   std::string g_hash = GetSha1(g);
1080*acea8879SAndroid Build Coastguard Worker   CHECK_EQ(0, bsdiff::bsdiff(reinterpret_cast<const uint8_t*>(bdc.data()), bdc.size(),
1081*acea8879SAndroid Build Coastguard Worker                              reinterpret_cast<const uint8_t*>(g.data()), g.size(),
1082*acea8879SAndroid Build Coastguard Worker                              patch_file_bdc_g.path, nullptr));
1083*acea8879SAndroid Build Coastguard Worker   std::string patch_bdc_g;
1084*acea8879SAndroid Build Coastguard Worker   CHECK(android::base::ReadFileToString(patch_file_bdc_g.path, &patch_bdc_g));
1085*acea8879SAndroid Build Coastguard Worker 
1086*acea8879SAndroid Build Coastguard Worker   // patch 2: "a b c d" -> "d c b"
1087*acea8879SAndroid Build Coastguard Worker   TemporaryFile patch_file_abcd_dcb;
1088*acea8879SAndroid Build Coastguard Worker   std::string abcd = a + b + c + d;
1089*acea8879SAndroid Build Coastguard Worker   std::string abcd_hash = GetSha1(abcd);
1090*acea8879SAndroid Build Coastguard Worker   std::string dcb = d + c + b;
1091*acea8879SAndroid Build Coastguard Worker   std::string dcb_hash = GetSha1(dcb);
1092*acea8879SAndroid Build Coastguard Worker   CHECK_EQ(0, bsdiff::bsdiff(reinterpret_cast<const uint8_t*>(abcd.data()), abcd.size(),
1093*acea8879SAndroid Build Coastguard Worker                              reinterpret_cast<const uint8_t*>(dcb.data()), dcb.size(),
1094*acea8879SAndroid Build Coastguard Worker                              patch_file_abcd_dcb.path, nullptr));
1095*acea8879SAndroid Build Coastguard Worker   std::string patch_abcd_dcb;
1096*acea8879SAndroid Build Coastguard Worker   CHECK(android::base::ReadFileToString(patch_file_abcd_dcb.path, &patch_abcd_dcb));
1097*acea8879SAndroid Build Coastguard Worker 
1098*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> transfer_list{
1099*acea8879SAndroid Build Coastguard Worker     "4",
1100*acea8879SAndroid Build Coastguard Worker     "10",  // total blocks written
1101*acea8879SAndroid Build Coastguard Worker     "2",   // maximum stash entries
1102*acea8879SAndroid Build Coastguard Worker     "2",   // maximum number of stashed blocks
1103*acea8879SAndroid Build Coastguard Worker 
1104*acea8879SAndroid Build Coastguard Worker     // a b c d e a b c d e
1105*acea8879SAndroid Build Coastguard Worker     "stash " + b_hash + " " + loc("1"),
1106*acea8879SAndroid Build Coastguard Worker     // a b c d e a b c d e    [b(1)]
1107*acea8879SAndroid Build Coastguard Worker     "stash " + c_hash + " " + loc("2"),
1108*acea8879SAndroid Build Coastguard Worker     // a b c d e a b c d e    [b(1)][c(2)]
1109*acea8879SAndroid Build Coastguard Worker     "new " + loc("1-2"),
1110*acea8879SAndroid Build Coastguard Worker     // a i h d e a b c d e    [b(1)][c(2)]
1111*acea8879SAndroid Build Coastguard Worker     "zero " + loc("0"),
1112*acea8879SAndroid Build Coastguard Worker     // 0 i h d e a b c d e    [b(1)][c(2)]
1113*acea8879SAndroid Build Coastguard Worker 
1114*acea8879SAndroid Build Coastguard Worker     // bsdiff "b d c" (from stash, 3, stash) to get g(3)
1115*acea8879SAndroid Build Coastguard Worker     android::base::StringPrintf(
1116*acea8879SAndroid Build Coastguard Worker         "bsdiff 0 %zu %s %s %s 3 %s %s %s:%s %s:%s",
1117*acea8879SAndroid Build Coastguard Worker         patch_bdc_g.size(),                  // patch start (0), patch length
1118*acea8879SAndroid Build Coastguard Worker         bdc_hash.c_str(),                    // source hash
1119*acea8879SAndroid Build Coastguard Worker         g_hash.c_str(),                      // target hash
1120*acea8879SAndroid Build Coastguard Worker         loc("3").c_str(),                    // target range
1121*acea8879SAndroid Build Coastguard Worker         loc("3").c_str(), loc("1").c_str(),  // load "d" from block 3, into buffer at offset 1
1122*acea8879SAndroid Build Coastguard Worker         b_hash.c_str(), loc("0").c_str(),    // load "b" from stash, into buffer at offset 0
1123*acea8879SAndroid Build Coastguard Worker         c_hash.c_str(), loc("2").c_str()),   // load "c" from stash, into buffer at offset 2
1124*acea8879SAndroid Build Coastguard Worker 
1125*acea8879SAndroid Build Coastguard Worker     // 0 i h g e a b c d e    [b(1)][c(2)]
1126*acea8879SAndroid Build Coastguard Worker     "free " + b_hash,
1127*acea8879SAndroid Build Coastguard Worker     // 0 i h g e a b c d e    [c(2)]
1128*acea8879SAndroid Build Coastguard Worker     "free " + a_hash,
1129*acea8879SAndroid Build Coastguard Worker     // 0 i h g e a b c d e
1130*acea8879SAndroid Build Coastguard Worker     "stash " + a_hash + " " + loc("5"),
1131*acea8879SAndroid Build Coastguard Worker     // 0 i h g e a b c d e    [a(5)]
1132*acea8879SAndroid Build Coastguard Worker     "move " + e_hash + " " + loc("5") + " 1 " + loc("4"),
1133*acea8879SAndroid Build Coastguard Worker     // 0 i h g e e b c d e    [a(5)]
1134*acea8879SAndroid Build Coastguard Worker 
1135*acea8879SAndroid Build Coastguard Worker     // bsdiff "a b c d" (from stash, 6-8) to "d c b" (6-8)
1136*acea8879SAndroid Build Coastguard Worker     android::base::StringPrintf(  //
1137*acea8879SAndroid Build Coastguard Worker         "bsdiff %zu %zu %s %s %s 4 %s %s %s:%s",
1138*acea8879SAndroid Build Coastguard Worker         patch_bdc_g.size(),                          // patch start
1139*acea8879SAndroid Build Coastguard Worker         patch_bdc_g.size() + patch_abcd_dcb.size(),  // patch length
1140*acea8879SAndroid Build Coastguard Worker         abcd_hash.c_str(),                           // source hash
1141*acea8879SAndroid Build Coastguard Worker         dcb_hash.c_str(),                            // target hash
1142*acea8879SAndroid Build Coastguard Worker         loc("6-8").c_str(),                          // target range
1143*acea8879SAndroid Build Coastguard Worker         loc("6-8").c_str(),                          // load "b c d" from blocks 6-8
1144*acea8879SAndroid Build Coastguard Worker         loc("1-3").c_str(),                          //   into buffer at offset 1-3
1145*acea8879SAndroid Build Coastguard Worker         a_hash.c_str(),                              // load "a" from stash
1146*acea8879SAndroid Build Coastguard Worker         loc("0").c_str()),                           //   into buffer at offset 0
1147*acea8879SAndroid Build Coastguard Worker 
1148*acea8879SAndroid Build Coastguard Worker     // 0 i h g e e d c b e    [a(5)]
1149*acea8879SAndroid Build Coastguard Worker     "new " + loc("4"),
1150*acea8879SAndroid Build Coastguard Worker     // 0 i h g f e d c b e    [a(5)]
1151*acea8879SAndroid Build Coastguard Worker     "move " + a_hash + " " + loc("9") + " 1 - " + a_hash + ":" + loc("0"),
1152*acea8879SAndroid Build Coastguard Worker     // 0 i h g f e d c b a    [a(5)]
1153*acea8879SAndroid Build Coastguard Worker     "free " + a_hash,
1154*acea8879SAndroid Build Coastguard Worker     // 0 i h g f e d c b a
1155*acea8879SAndroid Build Coastguard Worker   };
1156*acea8879SAndroid Build Coastguard Worker 
1157*acea8879SAndroid Build Coastguard Worker   std::string new_data = i + h + f;
1158*acea8879SAndroid Build Coastguard Worker   std::string patch_data = patch_bdc_g + patch_abcd_dcb;
1159*acea8879SAndroid Build Coastguard Worker 
1160*acea8879SAndroid Build Coastguard Worker   g_entries = {
1161*acea8879SAndroid Build Coastguard Worker     { "new_data", new_data },
1162*acea8879SAndroid Build Coastguard Worker     { "patch_data", patch_data },
1163*acea8879SAndroid Build Coastguard Worker   };
1164*acea8879SAndroid Build Coastguard Worker   g_source_image = a + b + c + d + e + a + b + c + d + e;
1165*acea8879SAndroid Build Coastguard Worker   g_target_image = zero + i + h + g + f + e + d + c + b + a;
1166*acea8879SAndroid Build Coastguard Worker 
1167*acea8879SAndroid Build Coastguard Worker   return transfer_list;
1168*acea8879SAndroid Build Coastguard Worker }
1169*acea8879SAndroid Build Coastguard Worker 
1170*acea8879SAndroid Build Coastguard Worker static const std::vector<std::string> g_transfer_list = GenerateTransferList();
1171*acea8879SAndroid Build Coastguard Worker 
1172*acea8879SAndroid Build Coastguard Worker INSTANTIATE_TEST_CASE_P(InterruptAfterEachCommand, ResumableUpdaterTest,
1173*acea8879SAndroid Build Coastguard Worker                         ::testing::Range(static_cast<size_t>(0),
1174*acea8879SAndroid Build Coastguard Worker                                          g_transfer_list.size() -
1175*acea8879SAndroid Build Coastguard Worker                                              TransferList::kTransferListHeaderLines));
1176*acea8879SAndroid Build Coastguard Worker 
TEST_P(ResumableUpdaterTest,InterruptVerifyResume)1177*acea8879SAndroid Build Coastguard Worker TEST_P(ResumableUpdaterTest, InterruptVerifyResume) {
1178*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::WriteStringToFile(g_source_image, image_file_));
1179*acea8879SAndroid Build Coastguard Worker 
1180*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "Interrupting at line " << index_ << " ("
1181*acea8879SAndroid Build Coastguard Worker             << g_transfer_list[TransferList::kTransferListHeaderLines + index_] << ")";
1182*acea8879SAndroid Build Coastguard Worker 
1183*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> transfer_list_copy{ g_transfer_list };
1184*acea8879SAndroid Build Coastguard Worker   transfer_list_copy[TransferList::kTransferListHeaderLines + index_] = "abort";
1185*acea8879SAndroid Build Coastguard Worker 
1186*acea8879SAndroid Build Coastguard Worker   g_entries["transfer_list"] = android::base::Join(transfer_list_copy, '\n');
1187*acea8879SAndroid Build Coastguard Worker 
1188*acea8879SAndroid Build Coastguard Worker   // Run update that's expected to fail.
1189*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, g_entries, image_file_, "");
1190*acea8879SAndroid Build Coastguard Worker 
1191*acea8879SAndroid Build Coastguard Worker   std::string last_command_expected;
1192*acea8879SAndroid Build Coastguard Worker 
1193*acea8879SAndroid Build Coastguard Worker   // Assert the last_command_file.
1194*acea8879SAndroid Build Coastguard Worker   if (index_ == 0) {
1195*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(-1, access(last_command_file_.c_str(), R_OK));
1196*acea8879SAndroid Build Coastguard Worker   } else {
1197*acea8879SAndroid Build Coastguard Worker     last_command_expected = std::to_string(index_ - 1) + "\n" +
1198*acea8879SAndroid Build Coastguard Worker                             g_transfer_list[TransferList::kTransferListHeaderLines + index_ - 1];
1199*acea8879SAndroid Build Coastguard Worker     std::string last_command_actual;
1200*acea8879SAndroid Build Coastguard Worker     ASSERT_TRUE(android::base::ReadFileToString(last_command_file_, &last_command_actual));
1201*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(last_command_expected, last_command_actual);
1202*acea8879SAndroid Build Coastguard Worker   }
1203*acea8879SAndroid Build Coastguard Worker 
1204*acea8879SAndroid Build Coastguard Worker   g_entries["transfer_list"] = android::base::Join(g_transfer_list, '\n');
1205*acea8879SAndroid Build Coastguard Worker 
1206*acea8879SAndroid Build Coastguard Worker   // Resume the interrupted update, by doing verification first.
1207*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(true, g_entries, image_file_, "t");
1208*acea8879SAndroid Build Coastguard Worker 
1209*acea8879SAndroid Build Coastguard Worker   // last_command_file should remain intact.
1210*acea8879SAndroid Build Coastguard Worker   if (index_ == 0) {
1211*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(-1, access(last_command_file_.c_str(), R_OK));
1212*acea8879SAndroid Build Coastguard Worker   } else {
1213*acea8879SAndroid Build Coastguard Worker     std::string last_command_actual;
1214*acea8879SAndroid Build Coastguard Worker     ASSERT_TRUE(android::base::ReadFileToString(last_command_file_, &last_command_actual));
1215*acea8879SAndroid Build Coastguard Worker     ASSERT_EQ(last_command_expected, last_command_actual);
1216*acea8879SAndroid Build Coastguard Worker   }
1217*acea8879SAndroid Build Coastguard Worker 
1218*acea8879SAndroid Build Coastguard Worker   // Resume the update.
1219*acea8879SAndroid Build Coastguard Worker   RunBlockImageUpdate(false, g_entries, image_file_, "t");
1220*acea8879SAndroid Build Coastguard Worker 
1221*acea8879SAndroid Build Coastguard Worker   // last_command_file should be gone after successful update.
1222*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(-1, access(last_command_file_.c_str(), R_OK));
1223*acea8879SAndroid Build Coastguard Worker 
1224*acea8879SAndroid Build Coastguard Worker   std::string updated_image_actual;
1225*acea8879SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFileToString(image_file_, &updated_image_actual));
1226*acea8879SAndroid Build Coastguard Worker   ASSERT_EQ(g_target_image, updated_image_actual);
1227*acea8879SAndroid Build Coastguard Worker }
1228