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_map> 21 #include <unordered_set> 22 23 #include <android-base/file.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 #include "utility.h" 34 35 namespace android { 36 namespace snapshot { 37 38 using aidl::android::hardware::boot::MergeStatus; 39 using android::fs_mgr::IPropertyFetcher; 40 using android::fs_mgr::MetadataBuilder; 41 using android::fs_mgr::testing::MockPropertyFetcher; 42 using chromeos_update_engine::DeltaArchiveManifest; 43 using chromeos_update_engine::PartitionUpdate; 44 using testing::_; 45 using testing::AssertionResult; 46 using testing::NiceMock; 47 48 using namespace android::storage_literals; 49 using namespace std::string_literals; 50 51 // These are not reset between each test because it's expensive to create 52 // these resources (starting+connecting to gsid, zero-filling images). 53 extern std::unique_ptr<SnapshotManager> sm; 54 extern class TestDeviceInfo* test_device; 55 extern std::string fake_super; 56 static constexpr uint64_t kSuperSize = 32_MiB + 4_KiB; 57 static constexpr uint64_t kGroupSize = 32_MiB; 58 59 // Redirect requests for "super" to our fake super partition. 60 class TestPartitionOpener final : public android::fs_mgr::PartitionOpener { 61 public: TestPartitionOpener(const std::string & fake_super_path)62 explicit TestPartitionOpener(const std::string& fake_super_path) 63 : fake_super_path_(fake_super_path) {} 64 65 android::base::unique_fd Open(const std::string& partition_name, int flags) const override; 66 bool GetInfo(const std::string& partition_name, 67 android::fs_mgr::BlockDeviceInfo* info) const override; 68 std::string GetDeviceString(const std::string& partition_name) const override; 69 70 private: 71 std::string fake_super_path_; 72 }; 73 74 class TestDeviceInfo : public SnapshotManager::IDeviceInfo { 75 public: TestDeviceInfo()76 TestDeviceInfo() {} TestDeviceInfo(const std::string & fake_super)77 explicit TestDeviceInfo(const std::string& fake_super) { set_fake_super(fake_super); } TestDeviceInfo(const std::string & fake_super,const std::string & slot_suffix)78 TestDeviceInfo(const std::string& fake_super, const std::string& slot_suffix) 79 : TestDeviceInfo(fake_super) { 80 set_slot_suffix(slot_suffix); 81 } GetMetadataDir()82 std::string GetMetadataDir() const override { return metadata_dir_; } GetSlotSuffix()83 std::string GetSlotSuffix() const override { return slot_suffix_; } GetOtherSlotSuffix()84 std::string GetOtherSlotSuffix() const override { return slot_suffix_ == "_a" ? "_b" : "_a"; } GetSuperDevice(uint32_t slot)85 std::string GetSuperDevice([[maybe_unused]] uint32_t slot) const override { return "super"; } GetPartitionOpener()86 const android::fs_mgr::IPartitionOpener& GetPartitionOpener() const override { 87 return *opener_.get(); 88 } SetBootControlMergeStatus(MergeStatus status)89 bool SetBootControlMergeStatus(MergeStatus status) override { 90 merge_status_ = status; 91 return true; 92 } IsOverlayfsSetup()93 bool IsOverlayfsSetup() const override { return false; } IsRecovery()94 bool IsRecovery() const override { return recovery_; } SetActiveBootSlot(unsigned int slot)95 bool SetActiveBootSlot([[maybe_unused]] unsigned int slot) override { return true; } SetSlotAsUnbootable(unsigned int slot)96 bool SetSlotAsUnbootable(unsigned int slot) override { 97 unbootable_slots_.insert(slot); 98 return true; 99 } IsTestDevice()100 bool IsTestDevice() const override { return true; } IsFirstStageInit()101 bool IsFirstStageInit() const override { return first_stage_init_; } OpenImageManager()102 std::unique_ptr<IImageManager> OpenImageManager() const override { 103 return IDeviceInfo::OpenImageManager("ota/test"); 104 } GetDeviceMapper()105 android::dm::IDeviceMapper& GetDeviceMapper() override { 106 if (dm_) { 107 return *dm_; 108 } 109 return android::dm::DeviceMapper::Instance(); 110 } 111 IsSlotUnbootable(uint32_t slot)112 bool IsSlotUnbootable(uint32_t slot) { return unbootable_slots_.count(slot) != 0; } 113 set_slot_suffix(const std::string & suffix)114 void set_slot_suffix(const std::string& suffix) { slot_suffix_ = suffix; } set_fake_super(const std::string & path)115 void set_fake_super(const std::string& path) { 116 opener_ = std::make_unique<TestPartitionOpener>(path); 117 } set_recovery(bool value)118 void set_recovery(bool value) { recovery_ = value; } set_first_stage_init(bool value)119 void set_first_stage_init(bool value) { first_stage_init_ = value; } set_dm(android::dm::IDeviceMapper * dm)120 void set_dm(android::dm::IDeviceMapper* dm) { dm_ = dm; } 121 merge_status()122 MergeStatus merge_status() const { return merge_status_; } IsTempMetadata()123 bool IsTempMetadata() const override { return temp_metadata_; } 124 125 private: 126 std::string slot_suffix_ = "_a"; 127 std::unique_ptr<TestPartitionOpener> opener_; 128 MergeStatus merge_status_; 129 bool recovery_ = false; 130 bool first_stage_init_ = false; 131 std::unordered_set<uint32_t> unbootable_slots_; 132 android::dm::IDeviceMapper* dm_ = nullptr; 133 std::string metadata_dir_ = "/metadata/ota/test"; 134 bool temp_metadata_ = false; 135 }; 136 137 class DeviceMapperWrapper : public android::dm::IDeviceMapper { 138 using DmDeviceState = android::dm::DmDeviceState; 139 using DmTable = android::dm::DmTable; 140 141 public: DeviceMapperWrapper()142 DeviceMapperWrapper() : impl_(android::dm::DeviceMapper::Instance()) {} DeviceMapperWrapper(android::dm::IDeviceMapper & impl)143 explicit DeviceMapperWrapper(android::dm::IDeviceMapper& impl) : impl_(impl) {} 144 CreateDevice(const std::string & name,const DmTable & table,std::string * path,const std::chrono::milliseconds & timeout_ms)145 virtual bool CreateDevice(const std::string& name, const DmTable& table, std::string* path, 146 const std::chrono::milliseconds& timeout_ms) override { 147 return impl_.CreateDevice(name, table, path, timeout_ms); 148 } GetState(const std::string & name)149 virtual DmDeviceState GetState(const std::string& name) const override { 150 return impl_.GetState(name); 151 } LoadTable(const std::string & name,const DmTable & table)152 virtual bool LoadTable(const std::string& name, const DmTable& table) { 153 return impl_.LoadTable(name, table); 154 } LoadTableAndActivate(const std::string & name,const DmTable & table)155 virtual bool LoadTableAndActivate(const std::string& name, const DmTable& table) { 156 return impl_.LoadTableAndActivate(name, table); 157 } GetTableInfo(const std::string & name,std::vector<TargetInfo> * table)158 virtual bool GetTableInfo(const std::string& name, std::vector<TargetInfo>* table) { 159 return impl_.GetTableInfo(name, table); 160 } GetTableStatus(const std::string & name,std::vector<TargetInfo> * table)161 virtual bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) { 162 return impl_.GetTableStatus(name, table); 163 } GetTableStatusIma(const std::string & name,std::vector<TargetInfo> * table)164 virtual bool GetTableStatusIma(const std::string& name, std::vector<TargetInfo>* table) { 165 return impl_.GetTableStatusIma(name, table); 166 } GetDmDevicePathByName(const std::string & name,std::string * path)167 virtual bool GetDmDevicePathByName(const std::string& name, std::string* path) { 168 return impl_.GetDmDevicePathByName(name, path); 169 } GetDeviceString(const std::string & name,std::string * dev)170 virtual bool GetDeviceString(const std::string& name, std::string* dev) { 171 return impl_.GetDeviceString(name, dev); 172 } DeleteDeviceIfExists(const std::string & name)173 virtual bool DeleteDeviceIfExists(const std::string& name) { 174 return impl_.DeleteDeviceIfExists(name); 175 } 176 177 private: 178 android::dm::IDeviceMapper& impl_; 179 }; 180 181 class SnapshotTestPropertyFetcher : public android::fs_mgr::IPropertyFetcher { 182 public: 183 explicit SnapshotTestPropertyFetcher(const std::string& slot_suffix, 184 std::unordered_map<std::string, std::string>&& props = {}); 185 186 std::string GetProperty(const std::string& key, const std::string& defaultValue) override; 187 bool GetBoolProperty(const std::string& key, bool defaultValue) override; 188 189 static void SetUp(const std::string& slot_suffix = "_a") { Reset(slot_suffix); } TearDown()190 static void TearDown() { Reset("_a"); } 191 192 private: Reset(const std::string & slot_suffix)193 static void Reset(const std::string& slot_suffix) { 194 IPropertyFetcher::OverrideForTesting( 195 std::make_unique<SnapshotTestPropertyFetcher>(slot_suffix)); 196 } 197 198 private: 199 std::unordered_map<std::string, std::string> properties_; 200 }; 201 202 // Helper for error-spam-free cleanup. 203 void DeleteBackingImage(android::fiemap::IImageManager* manager, const std::string& name); 204 205 // Write some random data to the given device. 206 // If expect_size is not specified, will write until reaching end of the device. 207 // Expect space of |path| is multiple of 4K. 208 bool WriteRandomData(const std::string& path, std::optional<size_t> expect_size = std::nullopt, 209 std::string* hash = nullptr); 210 std::string HashSnapshot(ICowWriter::FileDescriptor* writer); 211 212 std::string ToHexString(const uint8_t* buf, size_t len); 213 214 std::optional<std::string> GetHash(const std::string& path); 215 216 // Add partitions and groups described by |manifest|. 217 AssertionResult FillFakeMetadata(MetadataBuilder* builder, const DeltaArchiveManifest& manifest, 218 const std::string& suffix); 219 220 // In the update package metadata, set a partition with the given size. 221 void SetSize(PartitionUpdate* partition_update, uint64_t size); 222 223 // Get partition size from update package metadata. 224 uint64_t GetSize(PartitionUpdate* partition_update); 225 226 bool IsVirtualAbEnabled(); 227 228 #define SKIP_IF_NON_VIRTUAL_AB() \ 229 do { \ 230 if (!IsVirtualAbEnabled()) GTEST_SKIP() << "Test for Virtual A/B devices only"; \ 231 } while (0) 232 233 #define RETURN_IF_NON_VIRTUAL_AB_MSG(msg) \ 234 do { \ 235 if (!IsVirtualAbEnabled()) { \ 236 std::cerr << (msg); \ 237 return; \ 238 } \ 239 } while (0) 240 241 #define RETURN_IF_NON_VIRTUAL_AB() RETURN_IF_NON_VIRTUAL_AB_MSG("") 242 243 #define SKIP_IF_VENDOR_ON_ANDROID_S() \ 244 do { \ 245 if (IsVendorFromAndroid12()) \ 246 GTEST_SKIP() << "Skip test as Vendor partition is on Android S"; \ 247 } while (0) 248 249 #define RETURN_IF_VENDOR_ON_ANDROID_S_MSG(msg) \ 250 do { \ 251 if (IsVendorFromAndroid12()) { \ 252 std::cerr << (msg); \ 253 return; \ 254 } \ 255 } while (0) 256 257 #define RETURN_IF_VENDOR_ON_ANDROID_S() RETURN_IF_VENDOR_ON_ANDROID_S_MSG("") 258 259 } // namespace snapshot 260 } // namespace android 261