• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = 32_MiB + 4_KiB;
55 static constexpr uint64_t kGroupSize = 32_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     }
GetMetadataDir()80     std::string GetMetadataDir() const override { return "/metadata/ota/test"s; }
GetSlotSuffix()81     std::string GetSlotSuffix() const override { return slot_suffix_; }
GetOtherSlotSuffix()82     std::string GetOtherSlotSuffix() const override { return slot_suffix_ == "_a" ? "_b" : "_a"; }
GetSuperDevice(uint32_t slot)83     std::string GetSuperDevice([[maybe_unused]] uint32_t slot) const override { return "super"; }
GetPartitionOpener()84     const android::fs_mgr::IPartitionOpener& GetPartitionOpener() const override {
85         return *opener_.get();
86     }
SetBootControlMergeStatus(MergeStatus status)87     bool SetBootControlMergeStatus(MergeStatus status) override {
88         merge_status_ = status;
89         return true;
90     }
IsOverlayfsSetup()91     bool IsOverlayfsSetup() const override { return false; }
IsRecovery()92     bool IsRecovery() const override { return recovery_; }
SetSlotAsUnbootable(unsigned int slot)93     bool SetSlotAsUnbootable(unsigned int slot) override {
94         unbootable_slots_.insert(slot);
95         return true;
96     }
IsTestDevice()97     bool IsTestDevice() const override { return true; }
IsFirstStageInit()98     bool IsFirstStageInit() const override { return first_stage_init_; }
OpenImageManager()99     std::unique_ptr<IImageManager> OpenImageManager() const override {
100         return IDeviceInfo::OpenImageManager("ota/test");
101     }
GetDeviceMapper()102     android::dm::IDeviceMapper& GetDeviceMapper() override {
103         if (dm_) {
104             return *dm_;
105         }
106         return android::dm::DeviceMapper::Instance();
107     }
108 
IsSlotUnbootable(uint32_t slot)109     bool IsSlotUnbootable(uint32_t slot) { return unbootable_slots_.count(slot) != 0; }
110 
set_slot_suffix(const std::string & suffix)111     void set_slot_suffix(const std::string& suffix) { slot_suffix_ = suffix; }
set_fake_super(const std::string & path)112     void set_fake_super(const std::string& path) {
113         opener_ = std::make_unique<TestPartitionOpener>(path);
114     }
set_recovery(bool value)115     void set_recovery(bool value) { recovery_ = value; }
set_first_stage_init(bool value)116     void set_first_stage_init(bool value) { first_stage_init_ = value; }
set_dm(android::dm::IDeviceMapper * dm)117     void set_dm(android::dm::IDeviceMapper* dm) { dm_ = dm; }
118 
merge_status()119     MergeStatus merge_status() const { return merge_status_; }
120 
121   private:
122     std::string slot_suffix_ = "_a";
123     std::unique_ptr<TestPartitionOpener> opener_;
124     MergeStatus merge_status_;
125     bool recovery_ = false;
126     bool first_stage_init_ = false;
127     std::unordered_set<uint32_t> unbootable_slots_;
128     android::dm::IDeviceMapper* dm_ = nullptr;
129 };
130 
131 class DeviceMapperWrapper : public android::dm::IDeviceMapper {
132     using DmDeviceState = android::dm::DmDeviceState;
133     using DmTable = android::dm::DmTable;
134 
135   public:
DeviceMapperWrapper()136     DeviceMapperWrapper() : impl_(android::dm::DeviceMapper::Instance()) {}
DeviceMapperWrapper(android::dm::IDeviceMapper & impl)137     explicit DeviceMapperWrapper(android::dm::IDeviceMapper& impl) : impl_(impl) {}
138 
CreateDevice(const std::string & name,const DmTable & table,std::string * path,const std::chrono::milliseconds & timeout_ms)139     virtual bool CreateDevice(const std::string& name, const DmTable& table, std::string* path,
140                               const std::chrono::milliseconds& timeout_ms) override {
141         return impl_.CreateDevice(name, table, path, timeout_ms);
142     }
GetState(const std::string & name)143     virtual DmDeviceState GetState(const std::string& name) const override {
144         return impl_.GetState(name);
145     }
LoadTableAndActivate(const std::string & name,const DmTable & table)146     virtual bool LoadTableAndActivate(const std::string& name, const DmTable& table) {
147         return impl_.LoadTableAndActivate(name, table);
148     }
GetTableInfo(const std::string & name,std::vector<TargetInfo> * table)149     virtual bool GetTableInfo(const std::string& name, std::vector<TargetInfo>* table) {
150         return impl_.GetTableInfo(name, table);
151     }
GetTableStatus(const std::string & name,std::vector<TargetInfo> * table)152     virtual bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) {
153         return impl_.GetTableStatus(name, table);
154     }
GetDmDevicePathByName(const std::string & name,std::string * path)155     virtual bool GetDmDevicePathByName(const std::string& name, std::string* path) {
156         return impl_.GetDmDevicePathByName(name, path);
157     }
GetDeviceString(const std::string & name,std::string * dev)158     virtual bool GetDeviceString(const std::string& name, std::string* dev) {
159         return impl_.GetDeviceString(name, dev);
160     }
DeleteDeviceIfExists(const std::string & name)161     virtual bool DeleteDeviceIfExists(const std::string& name) {
162         return impl_.DeleteDeviceIfExists(name);
163     }
164 
165   private:
166     android::dm::IDeviceMapper& impl_;
167 };
168 
169 class SnapshotTestPropertyFetcher : public android::fs_mgr::testing::MockPropertyFetcher {
170   public:
SnapshotTestPropertyFetcher(const std::string & slot_suffix)171     SnapshotTestPropertyFetcher(const std::string& slot_suffix) {
172         using testing::Return;
173         ON_CALL(*this, GetProperty("ro.boot.slot_suffix", _)).WillByDefault(Return(slot_suffix));
174         ON_CALL(*this, GetBoolProperty("ro.boot.dynamic_partitions", _))
175                 .WillByDefault(Return(true));
176         ON_CALL(*this, GetBoolProperty("ro.boot.dynamic_partitions_retrofit", _))
177                 .WillByDefault(Return(false));
178         ON_CALL(*this, GetBoolProperty("ro.virtual_ab.enabled", _)).WillByDefault(Return(true));
179     }
180 
181     static void SetUp(const std::string& slot_suffix = "_a") { Reset(slot_suffix); }
182 
TearDown()183     static void TearDown() { Reset("_a"); }
184 
185   private:
Reset(const std::string & slot_suffix)186     static void Reset(const std::string& slot_suffix) {
187         IPropertyFetcher::OverrideForTesting(
188                 std::make_unique<NiceMock<SnapshotTestPropertyFetcher>>(slot_suffix));
189     }
190 };
191 
192 // Helper for error-spam-free cleanup.
193 void DeleteBackingImage(android::fiemap::IImageManager* manager, const std::string& name);
194 
195 // Write some random data to the given device.
196 // If expect_size is not specified, will write until reaching end of the device.
197 // Expect space of |path| is multiple of 4K.
198 bool WriteRandomData(const std::string& path, std::optional<size_t> expect_size = std::nullopt,
199                      std::string* hash = nullptr);
200 bool WriteRandomData(ICowWriter* writer, std::string* hash = nullptr);
201 std::string HashSnapshot(ISnapshotWriter* writer);
202 
203 std::optional<std::string> GetHash(const std::string& path);
204 
205 // Add partitions and groups described by |manifest|.
206 AssertionResult FillFakeMetadata(MetadataBuilder* builder, const DeltaArchiveManifest& manifest,
207                                  const std::string& suffix);
208 
209 // In the update package metadata, set a partition with the given size.
210 void SetSize(PartitionUpdate* partition_update, uint64_t size);
211 
212 // Get partition size from update package metadata.
213 uint64_t GetSize(PartitionUpdate* partition_update);
214 
215 // Util class for test cases on low space scenario. These tests assumes image manager
216 // uses /data as backup device.
217 class LowSpaceUserdata {
218   public:
219     // Set the maximum free space allowed for this test. If /userdata has more space than the given
220     // number, a file is allocated to consume space.
221     AssertionResult Init(uint64_t max_free_space);
222 
223     uint64_t free_space() const;
224     uint64_t available_space() const;
225     uint64_t bsize() const;
226 
227   private:
228     AssertionResult ReadUserdataStats();
229 
230     static constexpr const char* kUserDataDevice = "/data";
231     std::unique_ptr<TemporaryFile> big_file_;
232     bool initialized_ = false;
233     uint64_t free_space_ = 0;
234     uint64_t available_space_ = 0;
235     uint64_t bsize_ = 0;
236 };
237 
238 bool IsVirtualAbEnabled();
239 
240 #define SKIP_IF_NON_VIRTUAL_AB()                                                        \
241     do {                                                                                \
242         if (!IsVirtualAbEnabled()) GTEST_SKIP() << "Test for Virtual A/B devices only"; \
243     } while (0)
244 
245 #define RETURN_IF_NON_VIRTUAL_AB_MSG(msg) \
246     do {                                  \
247         if (!IsVirtualAbEnabled()) {      \
248             std::cerr << (msg);           \
249             return;                       \
250         }                                 \
251     } while (0)
252 
253 #define RETURN_IF_NON_VIRTUAL_AB() RETURN_IF_NON_VIRTUAL_AB_MSG("")
254 
255 }  // namespace snapshot
256 }  // namespace android
257