Merge "Adding testing for optimized flash super" into main
This commit is contained in:
commit
7d8ac7f122
7 changed files with 152 additions and 51 deletions
|
@ -1286,7 +1286,7 @@ std::string get_current_slot() {
|
|||
return current_slot;
|
||||
}
|
||||
|
||||
static int get_slot_count() {
|
||||
static int get_slot_count(fastboot::IFastBootDriver* fb) {
|
||||
std::string var;
|
||||
int count = 0;
|
||||
if (fb->GetVar("slot-count", &var) != fastboot::SUCCESS ||
|
||||
|
@ -1296,8 +1296,8 @@ static int get_slot_count() {
|
|||
return count;
|
||||
}
|
||||
|
||||
bool supports_AB() {
|
||||
return get_slot_count() >= 2;
|
||||
bool supports_AB(fastboot::IFastBootDriver* fb) {
|
||||
return get_slot_count(fb) >= 2;
|
||||
}
|
||||
|
||||
// Given a current slot, this returns what the 'other' slot is.
|
||||
|
@ -1309,7 +1309,7 @@ static std::string get_other_slot(const std::string& current_slot, int count) {
|
|||
}
|
||||
|
||||
static std::string get_other_slot(const std::string& current_slot) {
|
||||
return get_other_slot(current_slot, get_slot_count());
|
||||
return get_other_slot(current_slot, get_slot_count(fb));
|
||||
}
|
||||
|
||||
static std::string get_other_slot(int count) {
|
||||
|
@ -1317,7 +1317,7 @@ static std::string get_other_slot(int count) {
|
|||
}
|
||||
|
||||
static std::string get_other_slot() {
|
||||
return get_other_slot(get_current_slot(), get_slot_count());
|
||||
return get_other_slot(get_current_slot(), get_slot_count(fb));
|
||||
}
|
||||
|
||||
static std::string verify_slot(const std::string& slot_name, bool allow_all) {
|
||||
|
@ -1326,7 +1326,7 @@ static std::string verify_slot(const std::string& slot_name, bool allow_all) {
|
|||
if (allow_all) {
|
||||
return "all";
|
||||
} else {
|
||||
int count = get_slot_count();
|
||||
int count = get_slot_count(fb);
|
||||
if (count > 0) {
|
||||
return "a";
|
||||
} else {
|
||||
|
@ -1335,7 +1335,7 @@ static std::string verify_slot(const std::string& slot_name, bool allow_all) {
|
|||
}
|
||||
}
|
||||
|
||||
int count = get_slot_count();
|
||||
int count = get_slot_count(fb);
|
||||
if (count == 0) die("Device does not support slots");
|
||||
|
||||
if (slot == "other") {
|
||||
|
@ -1408,7 +1408,7 @@ void do_for_partitions(const std::string& part, const std::string& slot,
|
|||
slot.c_str());
|
||||
}
|
||||
if (has_slot == "yes") {
|
||||
for (int i = 0; i < get_slot_count(); i++) {
|
||||
for (int i = 0; i < get_slot_count(fb); i++) {
|
||||
do_for_partition(part, std::string(1, (char)(i + 'a')), func, force_slot);
|
||||
}
|
||||
} else {
|
||||
|
@ -1529,7 +1529,7 @@ void do_flash(const char* pname, const char* fname, const bool apply_vbmeta,
|
|||
// Sets slot_override as the active slot. If slot_override is blank,
|
||||
// set current slot as active instead. This clears slot-unbootable.
|
||||
static void set_active(const std::string& slot_override) {
|
||||
if (!supports_AB()) return;
|
||||
if (!supports_AB(fb)) return;
|
||||
|
||||
if (slot_override != "") {
|
||||
fb->SetActive(slot_override);
|
||||
|
@ -1844,7 +1844,7 @@ void FlashAllTool::DetermineSlot() {
|
|||
fp_->secondary_slot = get_other_slot();
|
||||
}
|
||||
if (fp_->secondary_slot == "") {
|
||||
if (supports_AB()) {
|
||||
if (supports_AB(fb)) {
|
||||
fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n");
|
||||
}
|
||||
fp_->skip_secondary = true;
|
||||
|
|
|
@ -29,10 +29,8 @@
|
|||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include "fastboot_driver.h"
|
||||
#include "fastboot_driver_interface.h"
|
||||
#include "filesystem.h"
|
||||
#include "super_flash_helper.h"
|
||||
#include "task.h"
|
||||
#include "util.h"
|
||||
|
||||
|
@ -183,12 +181,12 @@ struct NetworkSerial {
|
|||
};
|
||||
|
||||
Result<NetworkSerial, FastbootError> ParseNetworkSerial(const std::string& serial);
|
||||
bool supports_AB();
|
||||
std::string GetPartitionName(const ImageEntry& entry, const std::string& current_slot_);
|
||||
void flash_partition_files(const std::string& partition, const std::vector<SparsePtr>& files);
|
||||
int64_t get_sparse_limit(int64_t size, const FlashingPlan* fp);
|
||||
std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size);
|
||||
|
||||
bool supports_AB(fastboot::IFastBootDriver* fb);
|
||||
bool is_retrofit_device(fastboot::IFastBootDriver* fb);
|
||||
bool is_logical(const std::string& partition);
|
||||
void fb_perform_format(const std::string& partition, int skip_if_not_supported,
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include <cstdlib>
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
@ -38,10 +37,8 @@
|
|||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <bootimg.h>
|
||||
#include <inttypes.h>
|
||||
#include <sparse/sparse.h>
|
||||
|
||||
#include "constants.h"
|
||||
#include "fastboot_driver_interface.h"
|
||||
#include "transport.h"
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <sparse/sparse.h>
|
||||
|
||||
#include "constants.h"
|
||||
#include "fastboot_driver.h"
|
||||
#include "usb.h"
|
||||
|
||||
|
@ -928,8 +929,7 @@ TEST_F(Fuzz, BadCommandTooLarge) {
|
|||
|
||||
ASSERT_TRUE(UsbStillAvailible()) << USB_PORT_GONE;
|
||||
std::string resp;
|
||||
EXPECT_EQ(fb->GetVar("product", &resp), SUCCESS)
|
||||
<< "Device is unresponsive to getvar command";
|
||||
EXPECT_EQ(fb->GetVar("product", &resp), SUCCESS) << "Device is unresponsive to getvar command";
|
||||
}
|
||||
|
||||
TEST_F(Fuzz, CommandTooLarge) {
|
||||
|
@ -985,11 +985,10 @@ TEST_F(Fuzz, SparseZeroLength) {
|
|||
TEST_F(Fuzz, SparseZeroBlkSize) {
|
||||
// handcrafted malform sparse file with zero as block size
|
||||
const std::vector<char> buf = {
|
||||
'\x3a', '\xff', '\x26', '\xed', '\x01', '\x00', '\x00', '\x00', '\x1c', '\x00', '\x0c', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x01', '\x00', '\x00', '\x00', '\x01', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\xc2', '\xca', '\x00', '\x00', '\x01', '\x00', '\x00', '\x00',
|
||||
'\x10', '\x00', '\x00', '\x00', '\x11', '\x22', '\x33', '\x44'
|
||||
};
|
||||
'\x3a', '\xff', '\x26', '\xed', '\x01', '\x00', '\x00', '\x00', '\x1c', '\x00', '\x0c',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x01', '\x00', '\x00', '\x00', '\x01', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\xc2', '\xca', '\x00', '\x00', '\x01',
|
||||
'\x00', '\x00', '\x00', '\x10', '\x00', '\x00', '\x00', '\x11', '\x22', '\x33', '\x44'};
|
||||
|
||||
ASSERT_EQ(DownloadCommand(buf.size()), SUCCESS) << "Device rejected download command";
|
||||
ASSERT_EQ(SendBuffer(buf), SUCCESS) << "Downloading payload failed";
|
||||
|
@ -1004,13 +1003,10 @@ TEST_F(Fuzz, SparseZeroBlkSize) {
|
|||
TEST_F(Fuzz, SparseVeryLargeBlkSize) {
|
||||
// handcrafted sparse file with block size of ~4GB and divisible 4
|
||||
const std::vector<char> buf = {
|
||||
'\x3a', '\xff', '\x26', '\xed', '\x01', '\x00', '\x00', '\x00',
|
||||
'\x1c', '\x00', '\x0c', '\x00', '\xF0', '\xFF', '\xFF', '\xFF',
|
||||
'\x01', '\x00', '\x00', '\x00', '\x01', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\xc3', '\xca', '\x00', '\x00',
|
||||
'\x01', '\x00', '\x00', '\x00', '\x0c', '\x00', '\x00', '\x00',
|
||||
'\x11', '\x22', '\x33', '\x44'
|
||||
};
|
||||
'\x3a', '\xff', '\x26', '\xed', '\x01', '\x00', '\x00', '\x00', '\x1c', '\x00', '\x0c',
|
||||
'\x00', '\xF0', '\xFF', '\xFF', '\xFF', '\x01', '\x00', '\x00', '\x00', '\x01', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\xc3', '\xca', '\x00', '\x00', '\x01',
|
||||
'\x00', '\x00', '\x00', '\x0c', '\x00', '\x00', '\x00', '\x11', '\x22', '\x33', '\x44'};
|
||||
|
||||
ASSERT_EQ(DownloadCommand(buf.size()), SUCCESS) << "Device rejected download command";
|
||||
ASSERT_EQ(SendBuffer(buf), SUCCESS) << "Downloading payload failed";
|
||||
|
@ -1021,11 +1017,10 @@ TEST_F(Fuzz, SparseVeryLargeBlkSize) {
|
|||
TEST_F(Fuzz, SparseTrimmed) {
|
||||
// handcrafted malform sparse file which is trimmed
|
||||
const std::vector<char> buf = {
|
||||
'\x3a', '\xff', '\x26', '\xed', '\x01', '\x00', '\x00', '\x00', '\x1c', '\x00', '\x0c', '\x00',
|
||||
'\x00', '\x10', '\x00', '\x00', '\x00', '\x00', '\x08', '\x00', '\x01', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\xc1', '\xca', '\x00', '\x00', '\x01', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x80', '\x11', '\x22', '\x33', '\x44'
|
||||
};
|
||||
'\x3a', '\xff', '\x26', '\xed', '\x01', '\x00', '\x00', '\x00', '\x1c', '\x00', '\x0c',
|
||||
'\x00', '\x00', '\x10', '\x00', '\x00', '\x00', '\x00', '\x08', '\x00', '\x01', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\xc1', '\xca', '\x00', '\x00', '\x01',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x80', '\x11', '\x22', '\x33', '\x44'};
|
||||
|
||||
ASSERT_EQ(DownloadCommand(buf.size()), SUCCESS) << "Device rejected download command";
|
||||
ASSERT_EQ(SendBuffer(buf), SUCCESS) << "Downloading payload failed";
|
||||
|
@ -1040,11 +1035,10 @@ TEST_F(Fuzz, SparseTrimmed) {
|
|||
TEST_F(Fuzz, SparseInvalidChurk) {
|
||||
// handcrafted malform sparse file with invalid churk
|
||||
const std::vector<char> buf = {
|
||||
'\x3a', '\xff', '\x26', '\xed', '\x01', '\x00', '\x00', '\x00', '\x1c', '\x00', '\x0c', '\x00',
|
||||
'\x00', '\x10', '\x00', '\x00', '\x00', '\x00', '\x08', '\x00', '\x01', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\xc1', '\xca', '\x00', '\x00', '\x01', '\x00', '\x00', '\x00',
|
||||
'\x10', '\x00', '\x00', '\x00', '\x11', '\x22', '\x33', '\x44'
|
||||
};
|
||||
'\x3a', '\xff', '\x26', '\xed', '\x01', '\x00', '\x00', '\x00', '\x1c', '\x00', '\x0c',
|
||||
'\x00', '\x00', '\x10', '\x00', '\x00', '\x00', '\x00', '\x08', '\x00', '\x01', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\xc1', '\xca', '\x00', '\x00', '\x01',
|
||||
'\x00', '\x00', '\x00', '\x10', '\x00', '\x00', '\x00', '\x11', '\x22', '\x33', '\x44'};
|
||||
|
||||
ASSERT_EQ(DownloadCommand(buf.size()), SUCCESS) << "Device rejected download command";
|
||||
ASSERT_EQ(SendBuffer(buf), SUCCESS) << "Downloading payload failed";
|
||||
|
@ -1894,7 +1888,8 @@ int main(int argc, char** argv) {
|
|||
if (!fastboot::FastBootTest::IsFastbootOverTcp()) {
|
||||
printf("<Waiting for Device>\n");
|
||||
const auto matcher = [](usb_ifc_info* info) -> int {
|
||||
return fastboot::FastBootTest::MatchFastboot(info, fastboot::FastBootTest::device_serial);
|
||||
return fastboot::FastBootTest::MatchFastboot(info,
|
||||
fastboot::FastBootTest::device_serial);
|
||||
};
|
||||
std::unique_ptr<Transport> transport;
|
||||
while (!transport) {
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
//
|
||||
#include "task.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include "fastboot_driver.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/parseint.h>
|
||||
|
@ -130,6 +129,7 @@ void OptimizedFlashSuperTask::Run() {
|
|||
// Send the data to the device.
|
||||
flash_partition_files(super_name_, files);
|
||||
}
|
||||
|
||||
std::string OptimizedFlashSuperTask::ToString() const {
|
||||
return "optimized-flash-super";
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ std::unique_ptr<OptimizedFlashSuperTask> OptimizedFlashSuperTask::Initialize(
|
|||
LOG(INFO) << "super optimization is disabled";
|
||||
return nullptr;
|
||||
}
|
||||
if (!supports_AB()) {
|
||||
if (!supports_AB(fp->fb)) {
|
||||
LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device";
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -218,17 +218,21 @@ std::unique_ptr<OptimizedFlashSuperTask> OptimizedFlashSuperTask::Initialize(
|
|||
|
||||
auto s = helper->GetSparseLayout();
|
||||
if (!s) return nullptr;
|
||||
// Remove images that we already flashed, just in case we have non-dynamic OS images.
|
||||
|
||||
// Remove tasks that are concatenated into this optimized task
|
||||
auto remove_if_callback = [&](const auto& task) -> bool {
|
||||
if (auto flash_task = task->AsFlashTask()) {
|
||||
return helper->WillFlash(flash_task->GetPartitionAndSlot());
|
||||
} else if (auto update_super_task = task->AsUpdateSuperTask()) {
|
||||
return true;
|
||||
} else if (auto reboot_task = task->AsRebootTask()) {
|
||||
return true;
|
||||
if (reboot_task->GetTarget() == "fastboot") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
tasks.erase(std::remove_if(tasks.begin(), tasks.end(), remove_if_callback), tasks.end());
|
||||
|
||||
return std::make_unique<OptimizedFlashSuperTask>(super_name, std::move(helper), std::move(s),
|
||||
|
|
|
@ -15,10 +15,8 @@
|
|||
//
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "fastboot_driver.h"
|
||||
#include "super_flash_helper.h"
|
||||
#include "util.h"
|
||||
|
||||
|
@ -29,6 +27,7 @@ using ImageEntry = std::pair<const Image*, std::string>;
|
|||
class FlashTask;
|
||||
class RebootTask;
|
||||
class UpdateSuperTask;
|
||||
class OptimizedFlashSuperTask;
|
||||
class WipeTask;
|
||||
class ResizeTask;
|
||||
class Task {
|
||||
|
@ -40,6 +39,7 @@ class Task {
|
|||
virtual FlashTask* AsFlashTask() { return nullptr; }
|
||||
virtual RebootTask* AsRebootTask() { return nullptr; }
|
||||
virtual UpdateSuperTask* AsUpdateSuperTask() { return nullptr; }
|
||||
virtual OptimizedFlashSuperTask* AsOptimizedFlashSuperTask() { return nullptr; }
|
||||
virtual WipeTask* AsWipeTask() { return nullptr; }
|
||||
virtual ResizeTask* AsResizeTask() { return nullptr; }
|
||||
|
||||
|
@ -86,13 +86,13 @@ class OptimizedFlashSuperTask : public Task {
|
|||
public:
|
||||
OptimizedFlashSuperTask(const std::string& super_name, std::unique_ptr<SuperFlashHelper> helper,
|
||||
SparsePtr sparse_layout, uint64_t super_size, const FlashingPlan* fp);
|
||||
virtual OptimizedFlashSuperTask* AsOptimizedFlashSuperTask() override { return this; }
|
||||
|
||||
static std::unique_ptr<OptimizedFlashSuperTask> Initialize(
|
||||
const FlashingPlan* fp, std::vector<std::unique_ptr<Task>>& tasks);
|
||||
static bool CanOptimize(const ImageSource* source,
|
||||
const std::vector<std::unique_ptr<Task>>& tasks);
|
||||
|
||||
using ImageEntry = std::pair<const Image*, std::string>;
|
||||
void Run() override;
|
||||
std::string ToString() const override;
|
||||
|
||||
|
|
|
@ -19,11 +19,10 @@
|
|||
#include "fastboot_driver_mock.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include "android-base/strings.h"
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
using android::base::Split;
|
||||
using testing::_;
|
||||
|
@ -235,3 +234,111 @@ TEST_F(ParseTest, CorrectTaskLists) {
|
|||
<< "size of fastboot-info task list: " << fastboot_info_tasks.size()
|
||||
<< " size of hardcoded task list: " << hardcoded_tasks.size();
|
||||
}
|
||||
|
||||
TEST_F(ParseTest, CanOptimizeTest) {
|
||||
if (!get_android_product_out()) {
|
||||
GTEST_SKIP();
|
||||
}
|
||||
|
||||
LocalImageSource s;
|
||||
fp->source = &s;
|
||||
fp->sparse_limit = std::numeric_limits<int64_t>::max();
|
||||
|
||||
fastboot::MockFastbootDriver fb;
|
||||
fp->fb = &fb;
|
||||
fp->should_optimize_flash_super = false;
|
||||
fp->should_use_fastboot_info = true;
|
||||
|
||||
std::vector<std::pair<std::vector<std::string>, bool>> patternmatchtest = {
|
||||
{{"flash boot", "flash init_boot", "flash vendor_boot", "reboot fastboot",
|
||||
"update-super", "flash product", "flash system", "flash system_ext", "flash odm",
|
||||
"if-wipe erase userdata"},
|
||||
true},
|
||||
{{"flash boot", "flash init_boot", "flash vendor_boot", "reboot fastboot",
|
||||
"update-super", "flash product", "flash system", "flash system_ext", "flash odm",
|
||||
"if-wipe erase userdata"},
|
||||
true},
|
||||
{{"flash boot", "flash init_boot", "flash vendor_boot", "reboot fastboot",
|
||||
"flash product", "flash system", "flash system_ext", "flash odm",
|
||||
"if-wipe erase userdata"},
|
||||
false},
|
||||
{{"flash boot", "flash init_boot", "flash vendor_boot", "update-super", "flash product",
|
||||
"flash system", "flash system_ext", "flash odm", "if-wipe erase userdata"},
|
||||
false},
|
||||
};
|
||||
|
||||
auto remove_if_callback = [&](const auto& task) -> bool { return !!task->AsResizeTask(); };
|
||||
|
||||
for (auto& test : patternmatchtest) {
|
||||
std::vector<std::unique_ptr<Task>> tasks = ParseFastbootInfo(fp.get(), test.first);
|
||||
tasks.erase(std::remove_if(tasks.begin(), tasks.end(), remove_if_callback), tasks.end());
|
||||
ASSERT_EQ(OptimizedFlashSuperTask::CanOptimize(fp->source, tasks), test.second);
|
||||
}
|
||||
}
|
||||
// Note: this test is exclusively testing that optimized flash super pattern matches a given task
|
||||
// list and is able to optimized based on a correct sequence of tasks
|
||||
TEST_F(ParseTest, OptimizedFlashSuperPatternMatchTest) {
|
||||
if (!get_android_product_out()) {
|
||||
GTEST_SKIP();
|
||||
}
|
||||
|
||||
LocalImageSource s;
|
||||
fp->source = &s;
|
||||
fp->sparse_limit = std::numeric_limits<int64_t>::max();
|
||||
|
||||
fastboot::MockFastbootDriver fb;
|
||||
fp->fb = &fb;
|
||||
fp->should_optimize_flash_super = true;
|
||||
fp->should_use_fastboot_info = true;
|
||||
|
||||
ON_CALL(fb, GetVar("super-partition-name", _, _))
|
||||
.WillByDefault(testing::Return(fastboot::BAD_ARG));
|
||||
|
||||
ON_CALL(fb, GetVar("slot-count", _, _))
|
||||
.WillByDefault(testing::DoAll(testing::SetArgPointee<1>("2"),
|
||||
testing::Return(fastboot::SUCCESS)));
|
||||
|
||||
ON_CALL(fb, GetVar("partition-size:super", _, _))
|
||||
.WillByDefault(testing::DoAll(testing::SetArgPointee<1>("1000"),
|
||||
testing::Return(fastboot::SUCCESS)));
|
||||
|
||||
std::vector<std::pair<std::vector<std::string>, bool>> patternmatchtest = {
|
||||
{{"flash boot", "flash init_boot", "flash vendor_boot", "reboot fastboot",
|
||||
"update-super", "flash product", "flash system", "flash system_ext", "flash odm",
|
||||
"if-wipe erase userdata"},
|
||||
true},
|
||||
{{"flash boot", "flash init_boot", "flash vendor_boot", "reboot fastboot",
|
||||
"update-super", "flash product", "flash system", "flash system_ext", "flash odm",
|
||||
"if-wipe erase userdata"},
|
||||
true},
|
||||
{{"flash boot", "flash init_boot", "flash vendor_boot", "reboot fastboot",
|
||||
"flash product", "flash system", "flash system_ext", "flash odm",
|
||||
"if-wipe erase userdata"},
|
||||
false},
|
||||
{{"flash boot", "flash init_boot", "flash vendor_boot", "update-super", "flash product",
|
||||
"flash system", "flash system_ext", "flash odm", "if-wipe erase userdata"},
|
||||
false},
|
||||
};
|
||||
|
||||
for (auto& test : patternmatchtest) {
|
||||
std::vector<std::unique_ptr<Task>> tasks = ParseFastbootInfo(fp.get(), test.first);
|
||||
// Check to make sure we have an optimized flash super task && no more dynamic partition
|
||||
// flashing tasks
|
||||
auto&& IsOptimized = [](const FlashingPlan* fp,
|
||||
const std::vector<std::unique_ptr<Task>>& tasks) {
|
||||
bool contains_optimized_task = false;
|
||||
for (auto& task : tasks) {
|
||||
if (auto optimized_task = task->AsOptimizedFlashSuperTask()) {
|
||||
contains_optimized_task = true;
|
||||
}
|
||||
if (auto flash_task = task->AsFlashTask()) {
|
||||
if (FlashTask::IsDynamicParitition(fp->source, flash_task)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return contains_optimized_task;
|
||||
};
|
||||
ASSERT_EQ(IsOptimized(fp.get(), tasks), test.second);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue