1 // 2 // Copyright (C) 2015 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #ifndef UPDATE_ENGINE_COMMON_FAKE_BOOT_CONTROL_H_ 18 #define UPDATE_ENGINE_COMMON_FAKE_BOOT_CONTROL_H_ 19 20 #include <map> 21 #include <memory> 22 #include <string> 23 #include <vector> 24 25 #include <base/time/time.h> 26 27 #include "update_engine/common/boot_control_interface.h" 28 #include "update_engine/common/dynamic_partition_control_stub.h" 29 30 namespace chromeos_update_engine { 31 32 // Implements a fake bootloader control interface used for testing. 33 class FakeBootControl : public BootControlInterface { 34 public: FakeBootControl()35 FakeBootControl() { 36 SetNumSlots(num_slots_); 37 // The current slot should be bootable. 38 is_bootable_[current_slot_] = true; 39 40 dynamic_partition_control_.reset(new DynamicPartitionControlStub()); 41 } 42 43 // BootControlInterface overrides. GetNumSlots()44 unsigned int GetNumSlots() const override { return num_slots_; } GetCurrentSlot()45 BootControlInterface::Slot GetCurrentSlot() const override { 46 return current_slot_; 47 } 48 GetPartitionDevice(const std::string & partition_name,BootControlInterface::Slot slot,bool not_in_payload,std::string * device,bool * is_dynamic)49 bool GetPartitionDevice(const std::string& partition_name, 50 BootControlInterface::Slot slot, 51 bool not_in_payload, 52 std::string* device, 53 bool* is_dynamic) const override { 54 if (slot >= num_slots_) 55 return false; 56 auto part_it = devices_[slot].find(partition_name); 57 if (part_it == devices_[slot].end()) 58 return false; 59 *device = part_it->second; 60 return true; 61 } 62 GetPartitionDevice(const std::string & partition_name,BootControlInterface::Slot slot,std::string * device)63 bool GetPartitionDevice(const std::string& partition_name, 64 BootControlInterface::Slot slot, 65 std::string* device) const override { 66 return GetPartitionDevice(partition_name, slot, false, device, nullptr); 67 } 68 IsSlotBootable(BootControlInterface::Slot slot)69 bool IsSlotBootable(BootControlInterface::Slot slot) const override { 70 return slot < num_slots_ && is_bootable_[slot]; 71 } 72 MarkSlotUnbootable(BootControlInterface::Slot slot)73 bool MarkSlotUnbootable(BootControlInterface::Slot slot) override { 74 if (slot >= num_slots_) 75 return false; 76 is_bootable_[slot] = false; 77 return true; 78 } 79 SetActiveBootSlot(Slot slot)80 bool SetActiveBootSlot(Slot slot) override { return true; } 81 MarkBootSuccessfulAsync(base::Callback<void (bool)> callback)82 bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) override { 83 // We run the callback directly from here to avoid having to setup a message 84 // loop in the test environment. 85 is_marked_successful_[GetCurrentSlot()] = true; 86 callback.Run(true); 87 return true; 88 } 89 IsSlotMarkedSuccessful(Slot slot)90 bool IsSlotMarkedSuccessful(Slot slot) const override { 91 return slot < num_slots_ && is_marked_successful_[slot]; 92 } 93 94 // Setters SetNumSlots(unsigned int num_slots)95 void SetNumSlots(unsigned int num_slots) { 96 num_slots_ = num_slots; 97 is_bootable_.resize(num_slots_, false); 98 is_marked_successful_.resize(num_slots_, false); 99 devices_.resize(num_slots_); 100 } 101 SetCurrentSlot(BootControlInterface::Slot slot)102 void SetCurrentSlot(BootControlInterface::Slot slot) { current_slot_ = slot; } 103 SetPartitionDevice(const std::string & partition_name,BootControlInterface::Slot slot,const std::string & device)104 void SetPartitionDevice(const std::string& partition_name, 105 BootControlInterface::Slot slot, 106 const std::string& device) { 107 DCHECK(slot < num_slots_); 108 devices_[slot][partition_name] = device; 109 } 110 SetSlotBootable(BootControlInterface::Slot slot,bool bootable)111 void SetSlotBootable(BootControlInterface::Slot slot, bool bootable) { 112 DCHECK(slot < num_slots_); 113 is_bootable_[slot] = bootable; 114 } 115 GetDynamicPartitionControl()116 DynamicPartitionControlInterface* GetDynamicPartitionControl() { 117 return dynamic_partition_control_.get(); 118 } 119 120 private: 121 BootControlInterface::Slot num_slots_{2}; 122 BootControlInterface::Slot current_slot_{0}; 123 124 std::vector<bool> is_bootable_; 125 std::vector<bool> is_marked_successful_; 126 std::vector<std::map<std::string, std::string>> devices_; 127 128 std::unique_ptr<DynamicPartitionControlInterface> dynamic_partition_control_; 129 130 DISALLOW_COPY_AND_ASSIGN(FakeBootControl); 131 }; 132 133 } // namespace chromeos_update_engine 134 135 #endif // UPDATE_ENGINE_COMMON_FAKE_BOOT_CONTROL_H_ 136