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