Merge "Add the hash_tree_info class in Command"
am: c0195801dc
Change-Id: I32500b2045271d498d3a67b85e5ec0a51ac8da0c
This commit is contained in:
@@ -333,6 +333,25 @@ TEST(CommandsTest, Parse_ZERO) {
|
|||||||
ASSERT_EQ(PatchInfo(), command.patch());
|
ASSERT_EQ(PatchInfo(), command.patch());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(CommandsTest, Parse_COMPUTE_HASH_TREE) {
|
||||||
|
const std::string input{ "compute_hash_tree 2,0,1 2,3,4 sha1 unknown-salt unknown-root-hash" };
|
||||||
|
std::string err;
|
||||||
|
Command command = Command::Parse(input, 9, &err);
|
||||||
|
ASSERT_TRUE(command);
|
||||||
|
|
||||||
|
ASSERT_EQ(Command::Type::COMPUTE_HASH_TREE, command.type());
|
||||||
|
ASSERT_EQ(9, command.index());
|
||||||
|
ASSERT_EQ(input, command.cmdline());
|
||||||
|
|
||||||
|
HashTreeInfo expected_info(RangeSet({ { 0, 1 } }), RangeSet({ { 3, 4 } }), "sha1", "unknown-salt",
|
||||||
|
"unknown-root-hash");
|
||||||
|
ASSERT_EQ(expected_info, command.hash_tree_info());
|
||||||
|
ASSERT_EQ(TargetInfo(), command.target());
|
||||||
|
ASSERT_EQ(SourceInfo(), command.source());
|
||||||
|
ASSERT_EQ(StashInfo(), command.stash());
|
||||||
|
ASSERT_EQ(PatchInfo(), command.patch());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(CommandsTest, Parse_InvalidNumberOfArgs) {
|
TEST(CommandsTest, Parse_InvalidNumberOfArgs) {
|
||||||
Command::abort_allowed_ = true;
|
Command::abort_allowed_ = true;
|
||||||
|
|
||||||
@@ -341,6 +360,7 @@ TEST(CommandsTest, Parse_InvalidNumberOfArgs) {
|
|||||||
std::vector<std::string> inputs{
|
std::vector<std::string> inputs{
|
||||||
"abort foo",
|
"abort foo",
|
||||||
"bsdiff",
|
"bsdiff",
|
||||||
|
"compute_hash_tree, 2,0,1 2,0,1 unknown-algorithm unknown-salt",
|
||||||
"erase",
|
"erase",
|
||||||
"erase 4,3,5,10,12 hash1",
|
"erase 4,3,5,10,12 hash1",
|
||||||
"free",
|
"free",
|
||||||
|
|||||||
+41
-1
@@ -31,6 +31,14 @@ using namespace std::string_literals;
|
|||||||
|
|
||||||
bool Command::abort_allowed_ = false;
|
bool Command::abort_allowed_ = false;
|
||||||
|
|
||||||
|
Command::Command(Type type, size_t index, std::string cmdline, HashTreeInfo hash_tree_info)
|
||||||
|
: type_(type),
|
||||||
|
index_(index),
|
||||||
|
cmdline_(std::move(cmdline)),
|
||||||
|
hash_tree_info_(std::move(hash_tree_info)) {
|
||||||
|
CHECK(type == Type::COMPUTE_HASH_TREE);
|
||||||
|
}
|
||||||
|
|
||||||
Command::Type Command::ParseType(const std::string& type_str) {
|
Command::Type Command::ParseType(const std::string& type_str) {
|
||||||
if (type_str == "abort") {
|
if (type_str == "abort") {
|
||||||
if (!abort_allowed_) {
|
if (!abort_allowed_) {
|
||||||
@@ -177,7 +185,6 @@ Command Command::Parse(const std::string& line, size_t index, std::string* err)
|
|||||||
SourceInfo source_info;
|
SourceInfo source_info;
|
||||||
StashInfo stash_info;
|
StashInfo stash_info;
|
||||||
|
|
||||||
// TODO(xunchang) add the parse code of compute_hash_tree
|
|
||||||
if (op == Type::ZERO || op == Type::NEW || op == Type::ERASE) {
|
if (op == Type::ZERO || op == Type::NEW || op == Type::ERASE) {
|
||||||
// zero/new/erase <rangeset>
|
// zero/new/erase <rangeset>
|
||||||
if (pos + 1 != tokens.size()) {
|
if (pos + 1 != tokens.size()) {
|
||||||
@@ -255,6 +262,39 @@ Command Command::Parse(const std::string& line, size_t index, std::string* err)
|
|||||||
tokens.size() - pos);
|
tokens.size() - pos);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
} else if (op == Type::COMPUTE_HASH_TREE) {
|
||||||
|
// <hash_tree_ranges> <source_ranges> <hash_algorithm> <salt_hex> <root_hash>
|
||||||
|
if (pos + 5 != tokens.size()) {
|
||||||
|
*err = android::base::StringPrintf("invalid number of args: %zu (expected 5)",
|
||||||
|
tokens.size() - pos);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expects the hash_tree data to be contiguous.
|
||||||
|
RangeSet hash_tree_ranges = RangeSet::Parse(tokens[pos++]);
|
||||||
|
if (!hash_tree_ranges || hash_tree_ranges.size() != 1) {
|
||||||
|
*err = "invalid hash tree ranges in: " + line;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
RangeSet source_ranges = RangeSet::Parse(tokens[pos++]);
|
||||||
|
if (!source_ranges) {
|
||||||
|
*err = "invalid source ranges in: " + line;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string hash_algorithm = tokens[pos++];
|
||||||
|
std::string salt_hex = tokens[pos++];
|
||||||
|
std::string root_hash = tokens[pos++];
|
||||||
|
if (hash_algorithm.empty() || salt_hex.empty() || root_hash.empty()) {
|
||||||
|
*err = "invalid hash tree arguments in " + line;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
HashTreeInfo hash_tree_info(std::move(hash_tree_ranges), std::move(source_ranges),
|
||||||
|
std::move(hash_algorithm), std::move(salt_hex),
|
||||||
|
std::move(root_hash));
|
||||||
|
return Command(op, index, line, std::move(hash_tree_info));
|
||||||
} else {
|
} else {
|
||||||
*err = "invalid op";
|
*err = "invalid op";
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
@@ -166,6 +166,50 @@ class PatchInfo {
|
|||||||
size_t length_{ 0 };
|
size_t length_{ 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The arguments to build a hash tree from blocks on the block device.
|
||||||
|
class HashTreeInfo {
|
||||||
|
public:
|
||||||
|
HashTreeInfo() = default;
|
||||||
|
|
||||||
|
HashTreeInfo(RangeSet hash_tree_ranges, RangeSet source_ranges, std::string hash_algorithm,
|
||||||
|
std::string salt_hex, std::string root_hash)
|
||||||
|
: hash_tree_ranges_(std::move(hash_tree_ranges)),
|
||||||
|
source_ranges_(std::move(source_ranges)),
|
||||||
|
hash_algorithm_(std::move(hash_algorithm)),
|
||||||
|
salt_hex_(std::move(salt_hex)),
|
||||||
|
root_hash_(std::move(root_hash)) {}
|
||||||
|
|
||||||
|
const RangeSet& hash_tree_ranges() const {
|
||||||
|
return hash_tree_ranges_;
|
||||||
|
}
|
||||||
|
const RangeSet& source_ranges() const {
|
||||||
|
return source_ranges_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& hash_algorithm() const {
|
||||||
|
return hash_algorithm_;
|
||||||
|
}
|
||||||
|
const std::string& salt_hex() const {
|
||||||
|
return salt_hex_;
|
||||||
|
}
|
||||||
|
const std::string& root_hash() const {
|
||||||
|
return root_hash_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const HashTreeInfo& other) const {
|
||||||
|
return hash_tree_ranges_ == other.hash_tree_ranges_ && source_ranges_ == other.source_ranges_ &&
|
||||||
|
hash_algorithm_ == other.hash_algorithm_ && salt_hex_ == other.salt_hex_ &&
|
||||||
|
root_hash_ == other.root_hash_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
RangeSet hash_tree_ranges_;
|
||||||
|
RangeSet source_ranges_;
|
||||||
|
std::string hash_algorithm_;
|
||||||
|
std::string salt_hex_;
|
||||||
|
std::string root_hash_;
|
||||||
|
};
|
||||||
|
|
||||||
// Command class holds the info for an update command that performs block-based OTA (BBOTA). Each
|
// Command class holds the info for an update command that performs block-based OTA (BBOTA). Each
|
||||||
// command consists of one or several args, namely TargetInfo, SourceInfo, StashInfo and PatchInfo.
|
// command consists of one or several args, namely TargetInfo, SourceInfo, StashInfo and PatchInfo.
|
||||||
// The currently used BBOTA version is v4.
|
// The currently used BBOTA version is v4.
|
||||||
@@ -248,6 +292,8 @@ class Command {
|
|||||||
source_(std::move(source)),
|
source_(std::move(source)),
|
||||||
stash_(std::move(stash)) {}
|
stash_(std::move(stash)) {}
|
||||||
|
|
||||||
|
Command(Type type, size_t index, std::string cmdline, HashTreeInfo hash_tree_info);
|
||||||
|
|
||||||
// Parses the given command 'line' into a Command object and returns it. The 'index' is specified
|
// Parses the given command 'line' into a Command object and returns it. The 'index' is specified
|
||||||
// by the caller to index the object. On parsing error, it returns an empty Command object that
|
// by the caller to index the object. On parsing error, it returns an empty Command object that
|
||||||
// evaluates to false, and the specific error message will be set in 'err'.
|
// evaluates to false, and the specific error message will be set in 'err'.
|
||||||
@@ -284,6 +330,10 @@ class Command {
|
|||||||
return stash_;
|
return stash_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const HashTreeInfo& hash_tree_info() const {
|
||||||
|
return hash_tree_info_;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr explicit operator bool() const {
|
constexpr explicit operator bool() const {
|
||||||
return type_ != Type::LAST;
|
return type_ != Type::LAST;
|
||||||
}
|
}
|
||||||
@@ -325,6 +375,8 @@ class Command {
|
|||||||
// The stash info. Only meaningful for STASH and FREE commands. Note that although SourceInfo may
|
// The stash info. Only meaningful for STASH and FREE commands. Note that although SourceInfo may
|
||||||
// also load data from stash, such info will be owned and managed by SourceInfo (i.e. in source_).
|
// also load data from stash, such info will be owned and managed by SourceInfo (i.e. in source_).
|
||||||
StashInfo stash_;
|
StashInfo stash_;
|
||||||
|
// The hash_tree info. Only meaningful for COMPUTE_HASH_TREE.
|
||||||
|
HashTreeInfo hash_tree_info_;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, const Command& command);
|
std::ostream& operator<<(std::ostream& os, const Command& command);
|
||||||
|
|||||||
Reference in New Issue
Block a user