summaryrefslogtreecommitdiff
path: root/boot_control_android_unittest.cc
diff options
context:
space:
mode:
authorAmin Hassani <ahassani@chromium.org>2020-09-16 11:19:28 -0700
committerAmin Hassani <ahassani@chromium.org>2020-09-17 10:17:36 -0700
commite53b39b8b9c5c0871841bbbb86f23657c0b7f91b (patch)
tree12746e5e7e4716ba7fc94d3ed5c1a36c4d47d474 /boot_control_android_unittest.cc
parenta02a1f1dc837f22226499d9856a949fb180d099a (diff)
parent9956320ffa4edb340d20bd7f3c852a9e87437bd3 (diff)
update_engine: Merge remote-tracking branch 'cros/upstream' into cros/master
Done with: git merge cros/upstream --commit -s recursive - Added EC key support and its unittests. - Resolved a conlict on error codes. Since Android versions are not uploading any UMA metrics, I gave the priority to the Android version Since they can't be changed. - Changed the openssl functions to get1 version (from get0) version because of a current issue with gale. Once the issue is resolved we need to change them back. - Some remaining styling issues fixed by clang-format BUG=b:163153182 TEST=CQ passes TEST=unittests Change-Id: Ib95034422b92433ce26e28336bc4806b34910d38
Diffstat (limited to 'boot_control_android_unittest.cc')
-rw-r--r--boot_control_android_unittest.cc853
1 files changed, 0 insertions, 853 deletions
diff --git a/boot_control_android_unittest.cc b/boot_control_android_unittest.cc
deleted file mode 100644
index bb9903e2..00000000
--- a/boot_control_android_unittest.cc
+++ /dev/null
@@ -1,853 +0,0 @@
-//
-// Copyright (C) 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#include "update_engine/boot_control_android.h"
-
-#include <set>
-#include <vector>
-
-#include <base/logging.h>
-#include <base/strings/string_util.h>
-#include <fs_mgr.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <libdm/dm.h>
-
-#include "update_engine/mock_boot_control_hal.h"
-#include "update_engine/mock_dynamic_partition_control.h"
-
-using android::dm::DmDeviceState;
-using android::fs_mgr::MetadataBuilder;
-using android::hardware::Void;
-using std::string;
-using testing::_;
-using testing::AnyNumber;
-using testing::Contains;
-using testing::Eq;
-using testing::Invoke;
-using testing::Key;
-using testing::MakeMatcher;
-using testing::Matcher;
-using testing::MatcherInterface;
-using testing::MatchResultListener;
-using testing::NiceMock;
-using testing::Not;
-using testing::Return;
-
-namespace chromeos_update_engine {
-
-constexpr const uint32_t kMaxNumSlots = 2;
-constexpr const char* kSlotSuffixes[kMaxNumSlots] = {"_a", "_b"};
-constexpr const char* kFakeDevicePath = "/fake/dev/path/";
-constexpr const char* kFakeDmDevicePath = "/fake/dm/dev/path/";
-constexpr const uint32_t kFakeMetadataSize = 65536;
-constexpr const char* kDefaultGroup = "foo";
-
-// A map describing the size of each partition.
-// "{name, size}"
-using PartitionSizes = std::map<string, uint64_t>;
-
-// "{name_a, size}"
-using PartitionSuffixSizes = std::map<string, uint64_t>;
-
-using PartitionMetadata = BootControlInterface::PartitionMetadata;
-
-// C++ standards do not allow uint64_t (aka unsigned long) to be the parameter
-// of user-defined literal operators.
-constexpr unsigned long long operator"" _MiB(unsigned long long x) { // NOLINT
- return x << 20;
-}
-constexpr unsigned long long operator"" _GiB(unsigned long long x) { // NOLINT
- return x << 30;
-}
-
-constexpr uint64_t kDefaultGroupSize = 5_GiB;
-// Super device size. 1 MiB for metadata.
-constexpr uint64_t kDefaultSuperSize = kDefaultGroupSize * 2 + 1_MiB;
-
-template <typename U, typename V>
-std::ostream& operator<<(std::ostream& os, const std::map<U, V>& param) {
- os << "{";
- bool first = true;
- for (const auto& pair : param) {
- if (!first)
- os << ", ";
- os << pair.first << ":" << pair.second;
- first = false;
- }
- return os << "}";
-}
-
-template <typename T>
-std::ostream& operator<<(std::ostream& os, const std::vector<T>& param) {
- os << "[";
- bool first = true;
- for (const auto& e : param) {
- if (!first)
- os << ", ";
- os << e;
- first = false;
- }
- return os << "]";
-}
-
-std::ostream& operator<<(std::ostream& os,
- const PartitionMetadata::Partition& p) {
- return os << "{" << p.name << ", " << p.size << "}";
-}
-
-std::ostream& operator<<(std::ostream& os, const PartitionMetadata::Group& g) {
- return os << "{" << g.name << ", " << g.size << ", " << g.partitions << "}";
-}
-
-std::ostream& operator<<(std::ostream& os, const PartitionMetadata& m) {
- return os << m.groups;
-}
-
-inline string GetDevice(const string& name) {
- return kFakeDevicePath + name;
-}
-
-inline string GetDmDevice(const string& name) {
- return kFakeDmDevicePath + name;
-}
-
-// TODO(elsk): fs_mgr_get_super_partition_name should be mocked.
-inline string GetSuperDevice(uint32_t slot) {
- return GetDevice(fs_mgr_get_super_partition_name(slot));
-}
-
-struct TestParam {
- uint32_t source;
- uint32_t target;
-};
-std::ostream& operator<<(std::ostream& os, const TestParam& param) {
- return os << "{source: " << param.source << ", target:" << param.target
- << "}";
-}
-
-// To support legacy tests, auto-convert {name_a: size} map to
-// PartitionMetadata.
-PartitionMetadata partitionSuffixSizesToMetadata(
- const PartitionSuffixSizes& partition_sizes) {
- PartitionMetadata metadata;
- for (const char* suffix : kSlotSuffixes) {
- metadata.groups.push_back(
- {string(kDefaultGroup) + suffix, kDefaultGroupSize, {}});
- }
- for (const auto& pair : partition_sizes) {
- for (size_t suffix_idx = 0; suffix_idx < kMaxNumSlots; ++suffix_idx) {
- if (base::EndsWith(pair.first,
- kSlotSuffixes[suffix_idx],
- base::CompareCase::SENSITIVE)) {
- metadata.groups[suffix_idx].partitions.push_back(
- {pair.first, pair.second});
- }
- }
- }
- return metadata;
-}
-
-// To support legacy tests, auto-convert {name: size} map to PartitionMetadata.
-PartitionMetadata partitionSizesToMetadata(
- const PartitionSizes& partition_sizes) {
- PartitionMetadata metadata;
- metadata.groups.push_back({string{kDefaultGroup}, kDefaultGroupSize, {}});
- for (const auto& pair : partition_sizes) {
- metadata.groups[0].partitions.push_back({pair.first, pair.second});
- }
- return metadata;
-}
-
-std::unique_ptr<MetadataBuilder> NewFakeMetadata(
- const PartitionMetadata& metadata) {
- auto builder =
- MetadataBuilder::New(kDefaultSuperSize, kFakeMetadataSize, kMaxNumSlots);
- EXPECT_GE(builder->AllocatableSpace(), kDefaultGroupSize * 2);
- EXPECT_NE(nullptr, builder);
- if (builder == nullptr)
- return nullptr;
- for (const auto& group : metadata.groups) {
- EXPECT_TRUE(builder->AddGroup(group.name, group.size));
- for (const auto& partition : group.partitions) {
- auto p = builder->AddPartition(partition.name, group.name, 0 /* attr */);
- EXPECT_TRUE(p && builder->ResizePartition(p, partition.size));
- }
- }
- return builder;
-}
-
-class MetadataMatcher : public MatcherInterface<MetadataBuilder*> {
- public:
- explicit MetadataMatcher(const PartitionSuffixSizes& partition_sizes)
- : partition_metadata_(partitionSuffixSizesToMetadata(partition_sizes)) {}
- explicit MetadataMatcher(const PartitionMetadata& partition_metadata)
- : partition_metadata_(partition_metadata) {}
-
- bool MatchAndExplain(MetadataBuilder* metadata,
- MatchResultListener* listener) const override {
- bool success = true;
- for (const auto& group : partition_metadata_.groups) {
- for (const auto& partition : group.partitions) {
- auto p = metadata->FindPartition(partition.name);
- if (p == nullptr) {
- if (!success)
- *listener << "; ";
- *listener << "No partition " << partition.name;
- success = false;
- continue;
- }
- if (p->size() != partition.size) {
- if (!success)
- *listener << "; ";
- *listener << "Partition " << partition.name << " has size "
- << p->size() << ", expected " << partition.size;
- success = false;
- }
- if (p->group_name() != group.name) {
- if (!success)
- *listener << "; ";
- *listener << "Partition " << partition.name << " has group "
- << p->group_name() << ", expected " << group.name;
- success = false;
- }
- }
- }
- return success;
- }
-
- void DescribeTo(std::ostream* os) const override {
- *os << "expect: " << partition_metadata_;
- }
-
- void DescribeNegationTo(std::ostream* os) const override {
- *os << "expect not: " << partition_metadata_;
- }
-
- private:
- PartitionMetadata partition_metadata_;
-};
-
-inline Matcher<MetadataBuilder*> MetadataMatches(
- const PartitionSuffixSizes& partition_sizes) {
- return MakeMatcher(new MetadataMatcher(partition_sizes));
-}
-
-inline Matcher<MetadataBuilder*> MetadataMatches(
- const PartitionMetadata& partition_metadata) {
- return MakeMatcher(new MetadataMatcher(partition_metadata));
-}
-
-MATCHER_P(HasGroup, group, " has group " + group) {
- auto groups = arg->ListGroups();
- return std::find(groups.begin(), groups.end(), group) != groups.end();
-}
-
-class BootControlAndroidTest : public ::testing::Test {
- protected:
- void SetUp() override {
- // Fake init bootctl_
- bootctl_.module_ = new NiceMock<MockBootControlHal>();
- bootctl_.dynamic_control_ =
- std::make_unique<NiceMock<MockDynamicPartitionControl>>();
-
- ON_CALL(module(), getNumberSlots()).WillByDefault(Invoke([] {
- return kMaxNumSlots;
- }));
- ON_CALL(module(), getSuffix(_, _))
- .WillByDefault(Invoke([](auto slot, auto cb) {
- EXPECT_LE(slot, kMaxNumSlots);
- cb(slot < kMaxNumSlots ? kSlotSuffixes[slot] : "");
- return Void();
- }));
-
- ON_CALL(dynamicControl(), IsDynamicPartitionsEnabled())
- .WillByDefault(Return(true));
- ON_CALL(dynamicControl(), IsDynamicPartitionsRetrofit())
- .WillByDefault(Return(false));
- ON_CALL(dynamicControl(), DeviceExists(_)).WillByDefault(Return(true));
- ON_CALL(dynamicControl(), GetDeviceDir(_))
- .WillByDefault(Invoke([](auto path) {
- *path = kFakeDevicePath;
- return true;
- }));
- ON_CALL(dynamicControl(), GetDmDevicePathByName(_, _))
- .WillByDefault(Invoke([](auto partition_name_suffix, auto device) {
- *device = GetDmDevice(partition_name_suffix);
- return true;
- }));
- }
-
- // Return the mocked HAL module.
- NiceMock<MockBootControlHal>& module() {
- return static_cast<NiceMock<MockBootControlHal>&>(*bootctl_.module_);
- }
-
- // Return the mocked DynamicPartitionControlInterface.
- NiceMock<MockDynamicPartitionControl>& dynamicControl() {
- return static_cast<NiceMock<MockDynamicPartitionControl>&>(
- *bootctl_.dynamic_control_);
- }
-
- // Set the fake metadata to return when LoadMetadataBuilder is called on
- // |slot|.
- void SetMetadata(uint32_t slot, const PartitionSuffixSizes& sizes) {
- SetMetadata(slot, partitionSuffixSizesToMetadata(sizes));
- }
-
- void SetMetadata(uint32_t slot, const PartitionMetadata& metadata) {
- EXPECT_CALL(dynamicControl(),
- LoadMetadataBuilder(GetSuperDevice(slot), slot, _))
- .Times(AnyNumber())
- .WillRepeatedly(Invoke([metadata](auto, auto, auto) {
- return NewFakeMetadata(metadata);
- }));
- }
-
- // Expect that UnmapPartitionOnDeviceMapper is called on target() metadata
- // slot with each partition in |partitions|.
- void ExpectUnmap(const std::set<string>& partitions) {
- // Error when UnmapPartitionOnDeviceMapper is called on unknown arguments.
- ON_CALL(dynamicControl(), UnmapPartitionOnDeviceMapper(_, _))
- .WillByDefault(Return(false));
-
- for (const auto& partition : partitions) {
- EXPECT_CALL(dynamicControl(), UnmapPartitionOnDeviceMapper(partition, _))
- .WillOnce(Invoke([this](auto partition, auto) {
- mapped_devices_.erase(partition);
- return true;
- }));
- }
- }
-
- void ExpectDevicesAreMapped(const std::set<string>& partitions) {
- ASSERT_EQ(partitions.size(), mapped_devices_.size());
- for (const auto& partition : partitions) {
- EXPECT_THAT(mapped_devices_, Contains(Key(Eq(partition))))
- << "Expect that " << partition << " is mapped, but it is not.";
- }
- }
-
- void ExpectStoreMetadata(const PartitionSuffixSizes& partition_sizes) {
- ExpectStoreMetadataMatch(MetadataMatches(partition_sizes));
- }
-
- virtual void ExpectStoreMetadataMatch(
- const Matcher<MetadataBuilder*>& matcher) {
- EXPECT_CALL(dynamicControl(),
- StoreMetadata(GetSuperDevice(target()), matcher, target()))
- .WillOnce(Return(true));
- }
-
- uint32_t source() { return slots_.source; }
-
- uint32_t target() { return slots_.target; }
-
- // Return partition names with suffix of source().
- string S(const string& name) { return name + kSlotSuffixes[source()]; }
-
- // Return partition names with suffix of target().
- string T(const string& name) { return name + kSlotSuffixes[target()]; }
-
- // Set source and target slots to use before testing.
- void SetSlots(const TestParam& slots) {
- slots_ = slots;
-
- ON_CALL(module(), getCurrentSlot()).WillByDefault(Invoke([this] {
- return source();
- }));
- // Should not store metadata to source slot.
- EXPECT_CALL(dynamicControl(),
- StoreMetadata(GetSuperDevice(source()), _, source()))
- .Times(0);
- // Should not load metadata from target slot.
- EXPECT_CALL(dynamicControl(),
- LoadMetadataBuilder(GetSuperDevice(target()), target(), _))
- .Times(0);
- }
-
- bool InitPartitionMetadata(uint32_t slot,
- PartitionSizes partition_sizes,
- bool update_metadata = true) {
- auto m = partitionSizesToMetadata(partition_sizes);
- LOG(INFO) << m;
- return bootctl_.InitPartitionMetadata(slot, m, update_metadata);
- }
-
- BootControlAndroid bootctl_; // BootControlAndroid under test.
- TestParam slots_;
- // mapped devices through MapPartitionOnDeviceMapper.
- std::map<string, string> mapped_devices_;
-};
-
-class BootControlAndroidTestP
- : public BootControlAndroidTest,
- public ::testing::WithParamInterface<TestParam> {
- public:
- void SetUp() override {
- BootControlAndroidTest::SetUp();
- SetSlots(GetParam());
- }
-};
-
-// Test resize case. Grow if target metadata contains a partition with a size
-// less than expected.
-TEST_P(BootControlAndroidTestP, NeedGrowIfSizeNotMatchWhenResizing) {
- SetMetadata(source(),
- {{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 2_GiB},
- {T("vendor"), 1_GiB}});
- ExpectStoreMetadata({{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 3_GiB},
- {T("vendor"), 1_GiB}});
- ExpectUnmap({T("system"), T("vendor")});
-
- EXPECT_TRUE(
- InitPartitionMetadata(target(), {{"system", 3_GiB}, {"vendor", 1_GiB}}));
-}
-
-// Test resize case. Shrink if target metadata contains a partition with a size
-// greater than expected.
-TEST_P(BootControlAndroidTestP, NeedShrinkIfSizeNotMatchWhenResizing) {
- SetMetadata(source(),
- {{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 2_GiB},
- {T("vendor"), 1_GiB}});
- ExpectStoreMetadata({{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 2_GiB},
- {T("vendor"), 150_MiB}});
- ExpectUnmap({T("system"), T("vendor")});
-
- EXPECT_TRUE(InitPartitionMetadata(target(),
- {{"system", 2_GiB}, {"vendor", 150_MiB}}));
-}
-
-// Test adding partitions on the first run.
-TEST_P(BootControlAndroidTestP, AddPartitionToEmptyMetadata) {
- SetMetadata(source(), PartitionSuffixSizes{});
- ExpectStoreMetadata({{T("system"), 2_GiB}, {T("vendor"), 1_GiB}});
- ExpectUnmap({T("system"), T("vendor")});
-
- EXPECT_TRUE(
- InitPartitionMetadata(target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}));
-}
-
-// Test subsequent add case.
-TEST_P(BootControlAndroidTestP, AddAdditionalPartition) {
- SetMetadata(source(), {{S("system"), 2_GiB}, {T("system"), 2_GiB}});
- ExpectStoreMetadata(
- {{S("system"), 2_GiB}, {T("system"), 2_GiB}, {T("vendor"), 1_GiB}});
- ExpectUnmap({T("system"), T("vendor")});
-
- EXPECT_TRUE(
- InitPartitionMetadata(target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}));
-}
-
-// Test delete one partition.
-TEST_P(BootControlAndroidTestP, DeletePartition) {
- SetMetadata(source(),
- {{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 2_GiB},
- {T("vendor"), 1_GiB}});
- // No T("vendor")
- ExpectStoreMetadata(
- {{S("system"), 2_GiB}, {S("vendor"), 1_GiB}, {T("system"), 2_GiB}});
- ExpectUnmap({T("system")});
-
- EXPECT_TRUE(InitPartitionMetadata(target(), {{"system", 2_GiB}}));
-}
-
-// Test delete all partitions.
-TEST_P(BootControlAndroidTestP, DeleteAll) {
- SetMetadata(source(),
- {{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 2_GiB},
- {T("vendor"), 1_GiB}});
- ExpectStoreMetadata({{S("system"), 2_GiB}, {S("vendor"), 1_GiB}});
-
- EXPECT_TRUE(InitPartitionMetadata(target(), {}));
-}
-
-// Test corrupt source metadata case.
-TEST_P(BootControlAndroidTestP, CorruptedSourceMetadata) {
- EXPECT_CALL(dynamicControl(),
- LoadMetadataBuilder(GetSuperDevice(source()), source(), _))
- .WillOnce(Invoke([](auto, auto, auto) { return nullptr; }));
- ExpectUnmap({T("system")});
-
- EXPECT_FALSE(InitPartitionMetadata(target(), {{"system", 1_GiB}}))
- << "Should not be able to continue with corrupt source metadata";
-}
-
-// Test that InitPartitionMetadata fail if there is not enough space on the
-// device.
-TEST_P(BootControlAndroidTestP, NotEnoughSpace) {
- SetMetadata(source(),
- {{S("system"), 3_GiB},
- {S("vendor"), 2_GiB},
- {T("system"), 0},
- {T("vendor"), 0}});
- EXPECT_FALSE(
- InitPartitionMetadata(target(), {{"system", 3_GiB}, {"vendor", 3_GiB}}))
- << "Should not be able to fit 11GiB data into 10GiB space";
-}
-
-TEST_P(BootControlAndroidTestP, NotEnoughSpaceForSlot) {
- SetMetadata(source(),
- {{S("system"), 1_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 0},
- {T("vendor"), 0}});
- EXPECT_FALSE(
- InitPartitionMetadata(target(), {{"system", 3_GiB}, {"vendor", 3_GiB}}))
- << "Should not be able to grow over size of super / 2";
-}
-
-// Test applying retrofit update on a build with dynamic partitions enabled.
-TEST_P(BootControlAndroidTestP,
- ApplyRetrofitUpdateOnDynamicPartitionsEnabledBuild) {
- SetMetadata(source(),
- {{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 2_GiB},
- {T("vendor"), 1_GiB}});
- // Should not try to unmap any target partition.
- EXPECT_CALL(dynamicControl(), UnmapPartitionOnDeviceMapper(_, _)).Times(0);
- // Should not store metadata to target slot.
- EXPECT_CALL(dynamicControl(),
- StoreMetadata(GetSuperDevice(target()), _, target()))
- .Times(0);
-
- // Not calling through BootControlAndroidTest::InitPartitionMetadata(), since
- // we don't want any default group in the PartitionMetadata.
- EXPECT_TRUE(bootctl_.InitPartitionMetadata(target(), {}, true));
-
- // Should use dynamic source partitions.
- EXPECT_CALL(dynamicControl(), GetState(S("system")))
- .Times(1)
- .WillOnce(Return(DmDeviceState::ACTIVE));
- string system_device;
- EXPECT_TRUE(bootctl_.GetPartitionDevice("system", source(), &system_device));
- EXPECT_EQ(GetDmDevice(S("system")), system_device);
-
- // Should use static target partitions without querying dynamic control.
- EXPECT_CALL(dynamicControl(), GetState(T("system"))).Times(0);
- EXPECT_TRUE(bootctl_.GetPartitionDevice("system", target(), &system_device));
- EXPECT_EQ(GetDevice(T("system")), system_device);
-
- // Static partition "bar".
- EXPECT_CALL(dynamicControl(), GetState(S("bar"))).Times(0);
- std::string bar_device;
- EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", source(), &bar_device));
- EXPECT_EQ(GetDevice(S("bar")), bar_device);
-
- EXPECT_CALL(dynamicControl(), GetState(T("bar"))).Times(0);
- EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", target(), &bar_device));
- EXPECT_EQ(GetDevice(T("bar")), bar_device);
-}
-
-TEST_P(BootControlAndroidTestP, GetPartitionDeviceWhenResumingUpdate) {
- // Both of the two slots contain valid partition metadata, since this is
- // resuming an update.
- SetMetadata(source(),
- {{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 2_GiB},
- {T("vendor"), 1_GiB}});
- SetMetadata(target(),
- {{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 2_GiB},
- {T("vendor"), 1_GiB}});
- EXPECT_CALL(dynamicControl(),
- StoreMetadata(GetSuperDevice(target()), _, target()))
- .Times(0);
- EXPECT_TRUE(InitPartitionMetadata(
- target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}, false));
-
- // Dynamic partition "system".
- EXPECT_CALL(dynamicControl(), GetState(S("system")))
- .Times(1)
- .WillOnce(Return(DmDeviceState::ACTIVE));
- string system_device;
- EXPECT_TRUE(bootctl_.GetPartitionDevice("system", source(), &system_device));
- EXPECT_EQ(GetDmDevice(S("system")), system_device);
-
- EXPECT_CALL(dynamicControl(), GetState(T("system")))
- .Times(1)
- .WillOnce(Return(DmDeviceState::ACTIVE));
- EXPECT_TRUE(bootctl_.GetPartitionDevice("system", target(), &system_device));
- EXPECT_EQ(GetDmDevice(T("system")), system_device);
-
- // Static partition "bar".
- EXPECT_CALL(dynamicControl(), GetState(S("bar"))).Times(0);
- std::string bar_device;
- EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", source(), &bar_device));
- EXPECT_EQ(GetDevice(S("bar")), bar_device);
-
- EXPECT_CALL(dynamicControl(), GetState(T("bar"))).Times(0);
- EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", target(), &bar_device));
- EXPECT_EQ(GetDevice(T("bar")), bar_device);
-}
-
-INSTANTIATE_TEST_CASE_P(BootControlAndroidTest,
- BootControlAndroidTestP,
- testing::Values(TestParam{0, 1}, TestParam{1, 0}));
-
-const PartitionSuffixSizes update_sizes_0() {
- // Initial state is 0 for "other" slot.
- return {
- {"grown_a", 2_GiB},
- {"shrunk_a", 1_GiB},
- {"same_a", 100_MiB},
- {"deleted_a", 150_MiB},
- // no added_a
- {"grown_b", 200_MiB},
- // simulate system_other
- {"shrunk_b", 0},
- {"same_b", 0},
- {"deleted_b", 0},
- // no added_b
- };
-}
-
-const PartitionSuffixSizes update_sizes_1() {
- return {
- {"grown_a", 2_GiB},
- {"shrunk_a", 1_GiB},
- {"same_a", 100_MiB},
- {"deleted_a", 150_MiB},
- // no added_a
- {"grown_b", 3_GiB},
- {"shrunk_b", 150_MiB},
- {"same_b", 100_MiB},
- {"added_b", 150_MiB},
- // no deleted_b
- };
-}
-
-const PartitionSuffixSizes update_sizes_2() {
- return {
- {"grown_a", 4_GiB},
- {"shrunk_a", 100_MiB},
- {"same_a", 100_MiB},
- {"deleted_a", 64_MiB},
- // no added_a
- {"grown_b", 3_GiB},
- {"shrunk_b", 150_MiB},
- {"same_b", 100_MiB},
- {"added_b", 150_MiB},
- // no deleted_b
- };
-}
-
-// Test case for first update after the device is manufactured, in which
-// case the "other" slot is likely of size "0" (except system, which is
-// non-zero because of system_other partition)
-TEST_F(BootControlAndroidTest, SimulatedFirstUpdate) {
- SetSlots({0, 1});
-
- SetMetadata(source(), update_sizes_0());
- SetMetadata(target(), update_sizes_0());
- ExpectStoreMetadata(update_sizes_1());
- ExpectUnmap({"grown_b", "shrunk_b", "same_b", "added_b"});
-
- EXPECT_TRUE(InitPartitionMetadata(target(),
- {{"grown", 3_GiB},
- {"shrunk", 150_MiB},
- {"same", 100_MiB},
- {"added", 150_MiB}}));
-}
-
-// After first update, test for the second update. In the second update, the
-// "added" partition is deleted and "deleted" partition is re-added.
-TEST_F(BootControlAndroidTest, SimulatedSecondUpdate) {
- SetSlots({1, 0});
-
- SetMetadata(source(), update_sizes_1());
- SetMetadata(target(), update_sizes_0());
-
- ExpectStoreMetadata(update_sizes_2());
- ExpectUnmap({"grown_a", "shrunk_a", "same_a", "deleted_a"});
-
- EXPECT_TRUE(InitPartitionMetadata(target(),
- {{"grown", 4_GiB},
- {"shrunk", 100_MiB},
- {"same", 100_MiB},
- {"deleted", 64_MiB}}));
-}
-
-TEST_F(BootControlAndroidTest, ApplyingToCurrentSlot) {
- SetSlots({1, 1});
- EXPECT_FALSE(InitPartitionMetadata(target(), {}))
- << "Should not be able to apply to current slot.";
-}
-
-class BootControlAndroidGroupTestP : public BootControlAndroidTestP {
- public:
- void SetUp() override {
- BootControlAndroidTestP::SetUp();
- SetMetadata(
- source(),
- {.groups = {SimpleGroup(S("android"), 3_GiB, S("system"), 2_GiB),
- SimpleGroup(S("oem"), 2_GiB, S("vendor"), 1_GiB),
- SimpleGroup(T("android"), 3_GiB, T("system"), 0),
- SimpleGroup(T("oem"), 2_GiB, T("vendor"), 0)}});
- }
-
- // Return a simple group with only one partition.
- PartitionMetadata::Group SimpleGroup(const string& group,
- uint64_t group_size,
- const string& partition,
- uint64_t partition_size) {
- return {.name = group,
- .size = group_size,
- .partitions = {{.name = partition, .size = partition_size}}};
- }
-
- void ExpectStoreMetadata(const PartitionMetadata& partition_metadata) {
- ExpectStoreMetadataMatch(MetadataMatches(partition_metadata));
- }
-
- // Expect that target slot is stored with target groups.
- void ExpectStoreMetadataMatch(
- const Matcher<MetadataBuilder*>& matcher) override {
- BootControlAndroidTestP::ExpectStoreMetadataMatch(AllOf(
- MetadataMatches(PartitionMetadata{
- .groups = {SimpleGroup(S("android"), 3_GiB, S("system"), 2_GiB),
- SimpleGroup(S("oem"), 2_GiB, S("vendor"), 1_GiB)}}),
- matcher));
- }
-};
-
-// Allow to resize within group.
-TEST_P(BootControlAndroidGroupTestP, ResizeWithinGroup) {
- ExpectStoreMetadata(PartitionMetadata{
- .groups = {SimpleGroup(T("android"), 3_GiB, T("system"), 3_GiB),
- SimpleGroup(T("oem"), 2_GiB, T("vendor"), 2_GiB)}});
- ExpectUnmap({T("system"), T("vendor")});
-
- EXPECT_TRUE(bootctl_.InitPartitionMetadata(
- target(),
- PartitionMetadata{
- .groups = {SimpleGroup("android", 3_GiB, "system", 3_GiB),
- SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
- true));
-}
-
-TEST_P(BootControlAndroidGroupTestP, NotEnoughSpaceForGroup) {
- EXPECT_FALSE(bootctl_.InitPartitionMetadata(
- target(),
- PartitionMetadata{
- .groups = {SimpleGroup("android", 3_GiB, "system", 1_GiB),
- SimpleGroup("oem", 2_GiB, "vendor", 3_GiB)}},
- true))
- << "Should not be able to grow over maximum size of group";
-}
-
-TEST_P(BootControlAndroidGroupTestP, GroupTooBig) {
- EXPECT_FALSE(bootctl_.InitPartitionMetadata(
- target(),
- PartitionMetadata{.groups = {{.name = "android", .size = 3_GiB},
- {.name = "oem", .size = 3_GiB}}},
- true))
- << "Should not be able to grow over size of super / 2";
-}
-
-TEST_P(BootControlAndroidGroupTestP, AddPartitionToGroup) {
- ExpectStoreMetadata(PartitionMetadata{
- .groups = {
- {.name = T("android"),
- .size = 3_GiB,
- .partitions = {{.name = T("system"), .size = 2_GiB},
- {.name = T("product_services"), .size = 1_GiB}}}}});
- ExpectUnmap({T("system"), T("vendor"), T("product_services")});
-
- EXPECT_TRUE(bootctl_.InitPartitionMetadata(
- target(),
- PartitionMetadata{
- .groups = {{.name = "android",
- .size = 3_GiB,
- .partitions = {{.name = "system", .size = 2_GiB},
- {.name = "product_services",
- .size = 1_GiB}}},
- SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
- true));
-}
-
-TEST_P(BootControlAndroidGroupTestP, RemovePartitionFromGroup) {
- ExpectStoreMetadata(PartitionMetadata{
- .groups = {{.name = T("android"), .size = 3_GiB, .partitions = {}}}});
- ExpectUnmap({T("vendor")});
-
- EXPECT_TRUE(bootctl_.InitPartitionMetadata(
- target(),
- PartitionMetadata{
- .groups = {{.name = "android", .size = 3_GiB, .partitions = {}},
- SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
- true));
-}
-
-TEST_P(BootControlAndroidGroupTestP, AddGroup) {
- ExpectStoreMetadata(PartitionMetadata{
- .groups = {
- SimpleGroup(T("new_group"), 2_GiB, T("new_partition"), 2_GiB)}});
- ExpectUnmap({T("system"), T("vendor"), T("new_partition")});
-
- EXPECT_TRUE(bootctl_.InitPartitionMetadata(
- target(),
- PartitionMetadata{
- .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB),
- SimpleGroup("oem", 1_GiB, "vendor", 1_GiB),
- SimpleGroup("new_group", 2_GiB, "new_partition", 2_GiB)}},
- true));
-}
-
-TEST_P(BootControlAndroidGroupTestP, RemoveGroup) {
- ExpectStoreMetadataMatch(Not(HasGroup(T("oem"))));
- ExpectUnmap({T("system")});
- EXPECT_TRUE(bootctl_.InitPartitionMetadata(
- target(),
- PartitionMetadata{
- .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB)}},
- true));
-}
-
-TEST_P(BootControlAndroidGroupTestP, ResizeGroup) {
- ExpectStoreMetadata(PartitionMetadata{
- .groups = {SimpleGroup(T("android"), 2_GiB, T("system"), 2_GiB),
- SimpleGroup(T("oem"), 3_GiB, T("vendor"), 3_GiB)}});
- ExpectUnmap({T("system"), T("vendor")});
-
- EXPECT_TRUE(bootctl_.InitPartitionMetadata(
- target(),
- PartitionMetadata{
- .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB),
- SimpleGroup("oem", 3_GiB, "vendor", 3_GiB)}},
- true));
-}
-
-INSTANTIATE_TEST_CASE_P(BootControlAndroidTest,
- BootControlAndroidGroupTestP,
- testing::Values(TestParam{0, 1}, TestParam{1, 0}));
-
-} // namespace chromeos_update_engine