1 // Copyright (C) 2019 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #pragma once 16 17 #include <memory> 18 #include <optional> 19 #include <string> 20 #include <unordered_set> 21 22 #include <android-base/file.h> 23 #include <android/hardware/boot/1.1/IBootControl.h> 24 #include <gmock/gmock.h> 25 #include <gtest/gtest.h> 26 #include <libfiemap/image_manager.h> 27 #include <liblp/mock_property_fetcher.h> 28 #include <liblp/partition_opener.h> 29 #include <libsnapshot/snapshot.h> 30 #include <storage_literals/storage_literals.h> 31 #include <update_engine/update_metadata.pb.h> 32 33 namespace android { 34 namespace snapshot { 35 36 using android::fs_mgr::IPropertyFetcher; 37 using android::fs_mgr::MetadataBuilder; 38 using android::fs_mgr::testing::MockPropertyFetcher; 39 using android::hardware::boot::V1_1::MergeStatus; 40 using chromeos_update_engine::DeltaArchiveManifest; 41 using chromeos_update_engine::PartitionUpdate; 42 using testing::_; 43 using testing::AssertionResult; 44 using testing::NiceMock; 45 46 using namespace android::storage_literals; 47 using namespace std::string_literals; 48 49 // These are not reset between each test because it's expensive to create 50 // these resources (starting+connecting to gsid, zero-filling images). 51 extern std::unique_ptr<SnapshotManager> sm; 52 extern class TestDeviceInfo* test_device; 53 extern std::string fake_super; 54 static constexpr uint64_t kSuperSize = 16_MiB + 4_KiB; 55 static constexpr uint64_t kGroupSize = 16_MiB; 56 57 // Redirect requests for "super" to our fake super partition. 58 class TestPartitionOpener final : public android::fs_mgr::PartitionOpener { 59 public: TestPartitionOpener(const std::string & fake_super_path)60 explicit TestPartitionOpener(const std::string& fake_super_path) 61 : fake_super_path_(fake_super_path) {} 62 63 android::base::unique_fd Open(const std::string& partition_name, int flags) const override; 64 bool GetInfo(const std::string& partition_name, 65 android::fs_mgr::BlockDeviceInfo* info) const override; 66 std::string GetDeviceString(const std::string& partition_name) const override; 67 68 private: 69 std::string fake_super_path_; 70 }; 71 72 class TestDeviceInfo : public SnapshotManager::IDeviceInfo { 73 public: TestDeviceInfo()74 TestDeviceInfo() {} TestDeviceInfo(const std::string & fake_super)75 explicit TestDeviceInfo(const std::string& fake_super) { set_fake_super(fake_super); } TestDeviceInfo(const std::string & fake_super,const std::string & slot_suffix)76 TestDeviceInfo(const std::string& fake_super, const std::string& slot_suffix) 77 : TestDeviceInfo(fake_super) { 78 set_slot_suffix(slot_suffix); 79 } GetGsidDir()80 std::string GetGsidDir() const override { return "ota/test"s; } GetMetadataDir()81 std::string GetMetadataDir() const override { return "/metadata/ota/test"s; } GetSlotSuffix()82 std::string GetSlotSuffix() const override { return slot_suffix_; } GetOtherSlotSuffix()83 std::string GetOtherSlotSuffix() const override { return slot_suffix_ == "_a" ? "_b" : "_a"; } GetSuperDevice(uint32_t slot)84 std::string GetSuperDevice([[maybe_unused]] uint32_t slot) const override { return "super"; } GetPartitionOpener()85 const android::fs_mgr::IPartitionOpener& GetPartitionOpener() const override { 86 return *opener_.get(); 87 } SetBootControlMergeStatus(MergeStatus status)88 bool SetBootControlMergeStatus(MergeStatus status) override { 89 merge_status_ = status; 90 return true; 91 } IsOverlayfsSetup()92 bool IsOverlayfsSetup() const override { return false; } IsRecovery()93 bool IsRecovery() const override { return recovery_; } SetSlotAsUnbootable(unsigned int slot)94 bool SetSlotAsUnbootable(unsigned int slot) override { 95 unbootable_slots_.insert(slot); 96 return true; 97 } 98 IsSlotUnbootable(uint32_t slot)99 bool IsSlotUnbootable(uint32_t slot) { return unbootable_slots_.count(slot) != 0; } 100 set_slot_suffix(const std::string & suffix)101 void set_slot_suffix(const std::string& suffix) { slot_suffix_ = suffix; } set_fake_super(const std::string & path)102 void set_fake_super(const std::string& path) { 103 opener_ = std::make_unique<TestPartitionOpener>(path); 104 } set_recovery(bool value)105 void set_recovery(bool value) { recovery_ = value; } merge_status()106 MergeStatus merge_status() const { return merge_status_; } 107 108 private: 109 std::string slot_suffix_ = "_a"; 110 std::unique_ptr<TestPartitionOpener> opener_; 111 MergeStatus merge_status_; 112 bool recovery_ = false; 113 std::unordered_set<uint32_t> unbootable_slots_; 114 }; 115 116 class SnapshotTestPropertyFetcher : public android::fs_mgr::testing::MockPropertyFetcher { 117 public: SnapshotTestPropertyFetcher(const std::string & slot_suffix)118 SnapshotTestPropertyFetcher(const std::string& slot_suffix) { 119 using testing::Return; 120 ON_CALL(*this, GetProperty("ro.boot.slot_suffix", _)).WillByDefault(Return(slot_suffix)); 121 ON_CALL(*this, GetBoolProperty("ro.boot.dynamic_partitions", _)) 122 .WillByDefault(Return(true)); 123 ON_CALL(*this, GetBoolProperty("ro.boot.dynamic_partitions_retrofit", _)) 124 .WillByDefault(Return(false)); 125 ON_CALL(*this, GetBoolProperty("ro.virtual_ab.enabled", _)).WillByDefault(Return(true)); 126 } 127 128 static void SetUp(const std::string& slot_suffix = "_a") { Reset(slot_suffix); } 129 TearDown()130 static void TearDown() { Reset("_a"); } 131 132 private: Reset(const std::string & slot_suffix)133 static void Reset(const std::string& slot_suffix) { 134 IPropertyFetcher::OverrideForTesting( 135 std::make_unique<NiceMock<SnapshotTestPropertyFetcher>>(slot_suffix)); 136 } 137 }; 138 139 // Helper for error-spam-free cleanup. 140 void DeleteBackingImage(android::fiemap::IImageManager* manager, const std::string& name); 141 142 // Write some random data to the given device. 143 // If expect_size is not specified, will write until reaching end of the device. 144 // Expect space of |path| is multiple of 4K. 145 bool WriteRandomData(const std::string& path, std::optional<size_t> expect_size = std::nullopt, 146 std::string* hash = nullptr); 147 148 std::optional<std::string> GetHash(const std::string& path); 149 150 // Add partitions and groups described by |manifest|. 151 AssertionResult FillFakeMetadata(MetadataBuilder* builder, const DeltaArchiveManifest& manifest, 152 const std::string& suffix); 153 154 // In the update package metadata, set a partition with the given size. 155 void SetSize(PartitionUpdate* partition_update, uint64_t size); 156 157 // Get partition size from update package metadata. 158 uint64_t GetSize(PartitionUpdate* partition_update); 159 160 // Util class for test cases on low space scenario. These tests assumes image manager 161 // uses /data as backup device. 162 class LowSpaceUserdata { 163 public: 164 // Set the maximum free space allowed for this test. If /userdata has more space than the given 165 // number, a file is allocated to consume space. 166 AssertionResult Init(uint64_t max_free_space); 167 168 uint64_t free_space() const; 169 uint64_t available_space() const; 170 uint64_t bsize() const; 171 172 private: 173 AssertionResult ReadUserdataStats(); 174 175 static constexpr const char* kUserDataDevice = "/data"; 176 std::unique_ptr<TemporaryFile> big_file_; 177 bool initialized_ = false; 178 uint64_t free_space_ = 0; 179 uint64_t available_space_ = 0; 180 uint64_t bsize_ = 0; 181 }; 182 183 } // namespace snapshot 184 } // namespace android 185