| // Copyright 2018 The Chromium OS Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "dlcservice/boot_slot.h" | |
| #include <utility> | |
| #include <gmock/gmock.h> | |
| #include <gtest/gtest.h> | |
| #include "dlcservice/mock_boot_device.h" | |
| namespace dlcservice { | |
| class BootSlotTest : public testing::Test { | |
| public: | |
| BootSlotTest() { | |
| auto mock_boot_device = std::make_unique<MockBootDevice>(); | |
| boot_device_ = mock_boot_device.get(); | |
| boot_slot_ = std::make_unique<BootSlot>(std::move(mock_boot_device)); | |
| } | |
| protected: | |
| MockBootDevice* boot_device_; | |
| std::unique_ptr<BootSlot> boot_slot_; | |
| }; | |
| TEST_F(BootSlotTest, SplitPartitionNameTest) { | |
| std::string disk; | |
| int part_num; | |
| EXPECT_TRUE(boot_slot_->SplitPartitionName("/dev/sda3", &disk, &part_num)); | |
| EXPECT_EQ("/dev/sda", disk); | |
| EXPECT_EQ(3, part_num); | |
| EXPECT_TRUE(boot_slot_->SplitPartitionName("/dev/sdp1234", &disk, &part_num)); | |
| EXPECT_EQ("/dev/sdp", disk); | |
| EXPECT_EQ(1234, part_num); | |
| EXPECT_TRUE( | |
| boot_slot_->SplitPartitionName("/dev/mmcblk0p3", &disk, &part_num)); | |
| EXPECT_EQ("/dev/mmcblk0", disk); | |
| EXPECT_EQ(3, part_num); | |
| EXPECT_TRUE( | |
| boot_slot_->SplitPartitionName("/dev/ubiblock3_2", &disk, &part_num)); | |
| EXPECT_EQ("/dev/ubiblock", disk); | |
| EXPECT_EQ(3, part_num); | |
| EXPECT_TRUE(boot_slot_->SplitPartitionName("/dev/loop10", &disk, &part_num)); | |
| EXPECT_EQ("/dev/loop", disk); | |
| EXPECT_EQ(10, part_num); | |
| EXPECT_TRUE( | |
| boot_slot_->SplitPartitionName("/dev/loop28p11", &disk, &part_num)); | |
| EXPECT_EQ("/dev/loop28", disk); | |
| EXPECT_EQ(11, part_num); | |
| EXPECT_TRUE( | |
| boot_slot_->SplitPartitionName("/dev/loop10_0", &disk, &part_num)); | |
| EXPECT_EQ("/dev/loop", disk); | |
| EXPECT_EQ(10, part_num); | |
| EXPECT_TRUE( | |
| boot_slot_->SplitPartitionName("/dev/loop28p11_0", &disk, &part_num)); | |
| EXPECT_EQ("/dev/loop28", disk); | |
| EXPECT_EQ(11, part_num); | |
| EXPECT_FALSE( | |
| boot_slot_->SplitPartitionName("/dev/mmcblk0p", &disk, &part_num)); | |
| EXPECT_FALSE(boot_slot_->SplitPartitionName("/dev/sda", &disk, &part_num)); | |
| EXPECT_FALSE( | |
| boot_slot_->SplitPartitionName("/dev/foo/bar", &disk, &part_num)); | |
| EXPECT_FALSE(boot_slot_->SplitPartitionName("/", &disk, &part_num)); | |
| EXPECT_FALSE(boot_slot_->SplitPartitionName("", &disk, &part_num)); | |
| } | |
| TEST_F(BootSlotTest, GetPartitionNumberTest) { | |
| // The partition name should not be case-sensitive. | |
| EXPECT_EQ(2, boot_slot_->GetPartitionNumber("kernel", 0, 2)); | |
| EXPECT_EQ(2, boot_slot_->GetPartitionNumber("KERNEL", 0, 2)); | |
| EXPECT_EQ(3, boot_slot_->GetPartitionNumber("ROOT", 0, 2)); | |
| EXPECT_EQ(3, boot_slot_->GetPartitionNumber("ROOT", 0, 2)); | |
| // Slot B. | |
| EXPECT_EQ(4, boot_slot_->GetPartitionNumber("KERNEL", 1, 2)); | |
| EXPECT_EQ(5, boot_slot_->GetPartitionNumber("ROOT", 1, 2)); | |
| // Slot C doesn't exists. | |
| EXPECT_EQ(-1, boot_slot_->GetPartitionNumber("KERNEL", 2, 2)); | |
| EXPECT_EQ(-1, boot_slot_->GetPartitionNumber("ROOT", 2, 2)); | |
| // Non A/B partitions are ignored. | |
| EXPECT_EQ(-1, boot_slot_->GetPartitionNumber("OEM", 0, 2)); | |
| EXPECT_EQ(-1, boot_slot_->GetPartitionNumber("A little panda", 0, 2)); | |
| // Number of slots is too small. | |
| EXPECT_EQ(-1, boot_slot_->GetPartitionNumber("kernel", 2, 2)); | |
| } | |
| TEST_F(BootSlotTest, GetCurrentSlotTest) { | |
| std::string boot_disk_name; | |
| int num_slots; | |
| int current_slot; | |
| // Boot from A slot. | |
| ON_CALL(*boot_device_, GetBootDevice()) | |
| .WillByDefault(testing::Return("/dev/sda3")); | |
| ON_CALL(*boot_device_, IsRemovableDevice(testing::_)) | |
| .WillByDefault(testing::Return(false)); | |
| EXPECT_TRUE( | |
| boot_slot_->GetCurrentSlot(&boot_disk_name, &num_slots, ¤t_slot)); | |
| EXPECT_EQ(boot_disk_name, "/dev/sda"); | |
| EXPECT_EQ(num_slots, 2); | |
| EXPECT_EQ(current_slot, 0); | |
| // Boot from B slot. | |
| ON_CALL(*boot_device_, GetBootDevice()) | |
| .WillByDefault(testing::Return("/dev/sda5")); | |
| ON_CALL(*boot_device_, IsRemovableDevice(testing::_)) | |
| .WillByDefault(testing::Return(false)); | |
| EXPECT_TRUE( | |
| boot_slot_->GetCurrentSlot(&boot_disk_name, &num_slots, ¤t_slot)); | |
| EXPECT_EQ(boot_disk_name, "/dev/sda"); | |
| EXPECT_EQ(num_slots, 2); | |
| EXPECT_EQ(current_slot, 1); | |
| // Boot from removable device. | |
| ON_CALL(*boot_device_, GetBootDevice()) | |
| .WillByDefault(testing::Return("/dev/sdb3")); | |
| ON_CALL(*boot_device_, IsRemovableDevice(testing::_)) | |
| .WillByDefault(testing::Return(true)); | |
| EXPECT_TRUE( | |
| boot_slot_->GetCurrentSlot(&boot_disk_name, &num_slots, ¤t_slot)); | |
| EXPECT_EQ(boot_disk_name, "/dev/sdb"); | |
| EXPECT_EQ(num_slots, 1); | |
| EXPECT_EQ(current_slot, 0); | |
| // Boot from an invalid device. | |
| ON_CALL(*boot_device_, GetBootDevice()) | |
| .WillByDefault(testing::Return("/dev/sda")); | |
| ON_CALL(*boot_device_, IsRemovableDevice(testing::_)) | |
| .WillByDefault(testing::Return(true)); | |
| EXPECT_FALSE( | |
| boot_slot_->GetCurrentSlot(&boot_disk_name, &num_slots, ¤t_slot)); | |
| } | |
| } // namespace dlcservice |