| // Copyright 2023 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "lvmd/lvmd.h" | |
| #include <optional> | |
| #include <tuple> | |
| #include <brillo/blkdev_utils/lvm_device.h> | |
| #include <brillo/blkdev_utils/mock_lvm.h> | |
| #include <gmock/gmock.h> | |
| #include <gtest/gtest.h> | |
| #include <lvmd/proto_bindings/lvmd.pb.h> | |
| using ::testing::Eq; | |
| using ::testing::InSequence; | |
| using ::testing::Ref; | |
| using ::testing::Return; | |
| namespace lvmd { | |
| MATCHER_P2(DictValueMatch, key, value, "") { | |
| return *arg.FindString(key) == value; | |
| } | |
| class LvmdTest : public ::testing::Test { | |
| public: | |
| LvmdTest() = default; | |
| LvmdTest(const LvmdTest&) = delete; | |
| LvmdTest& operator=(const LvmdTest&) = delete; | |
| void SetUp() override { | |
| auto lvm = std::make_unique<brillo::MockLogicalVolumeManager>(); | |
| lvm_ptr_ = lvm.get(); | |
| lvmd_ = std::make_unique<Lvmd>(std::move(lvm)); | |
| } | |
| protected: | |
| brillo::MockLogicalVolumeManager* lvm_ptr_; | |
| std::unique_ptr<Lvmd> lvmd_; | |
| }; | |
| TEST_F(LvmdTest, CreateLogicalVolumesEmpty) { | |
| brillo::ErrorPtr err; | |
| CreateLogicalVolumesRequest request; | |
| CreateLogicalVolumesResponse response; | |
| EXPECT_TRUE(lvmd_->CreateLogicalVolumes(&err, request, &response)); | |
| } | |
| TEST_F(LvmdTest, CreateLogicalVolumesLvmCallCheck) { | |
| brillo::ErrorPtr err; | |
| CreateLogicalVolumesRequest request; | |
| CreateLogicalVolumesResponse response; | |
| std::ignore = request.add_logical_volume_infos(); | |
| auto opt_lv = std::make_optional<brillo::LogicalVolume>("", "", nullptr); | |
| EXPECT_CALL(*lvm_ptr_, CreateLogicalVolume(_, _, _)).WillOnce(Return(opt_lv)); | |
| EXPECT_TRUE(lvmd_->CreateLogicalVolumes(&err, request, &response)); | |
| } | |
| TEST_F(LvmdTest, CreateLogicalVolumesLvmFailureCheck) { | |
| brillo::ErrorPtr err; | |
| CreateLogicalVolumesRequest request; | |
| CreateLogicalVolumesResponse response; | |
| std::ignore = request.add_logical_volume_infos(); | |
| std::optional<brillo::LogicalVolume> opt_lv; | |
| EXPECT_CALL(*lvm_ptr_, CreateLogicalVolume(_, _, _)).WillOnce(Return(opt_lv)); | |
| EXPECT_FALSE(lvmd_->CreateLogicalVolumes(&err, request, &response)); | |
| } | |
| TEST_F(LvmdTest, CreateLogicalVolumesSuccessfulLvsPopulated) { | |
| brillo::ErrorPtr err; | |
| CreateLogicalVolumesRequest request; | |
| CreateLogicalVolumesResponse response; | |
| for (const auto& name : {"lv1", "lv2", "some-more-lv1", "some-more-lv2"}) { | |
| auto* lv_info = request.add_logical_volume_infos(); | |
| lv_info->mutable_lv_config()->set_name(name); | |
| } | |
| { | |
| InSequence seq; | |
| { | |
| std::optional<brillo::LogicalVolume> opt_lv; | |
| EXPECT_CALL(*lvm_ptr_, | |
| CreateLogicalVolume(_, _, DictValueMatch("name", "lv1"))) | |
| .WillOnce((Return(opt_lv))); | |
| } | |
| { | |
| auto opt_lv = | |
| std::make_optional<brillo::LogicalVolume>("lv2", "some-vg", nullptr); | |
| EXPECT_CALL(*lvm_ptr_, | |
| CreateLogicalVolume(_, _, DictValueMatch("name", "lv2"))) | |
| .WillOnce((Return(opt_lv))); | |
| } | |
| { | |
| std::optional<brillo::LogicalVolume> opt_lv; | |
| EXPECT_CALL(*lvm_ptr_, CreateLogicalVolume(_, _, _)) | |
| .WillRepeatedly((Return(opt_lv))); | |
| } | |
| EXPECT_FALSE(lvmd_->CreateLogicalVolumes(&err, request, &response)); | |
| } | |
| ASSERT_TRUE(response.has_logical_volume_list()); | |
| EXPECT_EQ(response.logical_volume_list().logical_volume_size(), 1); | |
| EXPECT_EQ(response.logical_volume_list().logical_volume().at(0).name(), | |
| "lv2"); | |
| } | |
| TEST_F(LvmdTest, RemoveLogicalVolumesEmpty) { | |
| brillo::ErrorPtr err; | |
| RemoveLogicalVolumesRequest request; | |
| RemoveLogicalVolumesResponse response; | |
| EXPECT_TRUE(lvmd_->RemoveLogicalVolumes(&err, request, &response)); | |
| } | |
| TEST_F(LvmdTest, RemoveLogicalVolumesLvmCallCheck) { | |
| brillo::ErrorPtr err; | |
| RemoveLogicalVolumesRequest request; | |
| RemoveLogicalVolumesResponse response; | |
| std::ignore = request.mutable_logical_volume_list()->add_logical_volume(); | |
| EXPECT_CALL(*lvm_ptr_, RemoveLogicalVolume(_, _)).WillOnce((Return(true))); | |
| EXPECT_TRUE(lvmd_->RemoveLogicalVolumes(&err, request, &response)); | |
| } | |
| TEST_F(LvmdTest, RemoveLogicalVolumesLvmFailureCheck) { | |
| brillo::ErrorPtr err; | |
| RemoveLogicalVolumesRequest request; | |
| RemoveLogicalVolumesResponse response; | |
| std::ignore = request.mutable_logical_volume_list()->add_logical_volume(); | |
| EXPECT_CALL(*lvm_ptr_, RemoveLogicalVolume(_, _)).WillOnce((Return(false))); | |
| EXPECT_FALSE(lvmd_->RemoveLogicalVolumes(&err, request, &response)); | |
| } | |
| TEST_F(LvmdTest, RemoveLogicalVolumesFailedLvsPopulated) { | |
| brillo::ErrorPtr err; | |
| RemoveLogicalVolumesRequest request; | |
| RemoveLogicalVolumesResponse response; | |
| for (const auto& name : {"lv1", "lv2"}) { | |
| auto* lv = request.mutable_logical_volume_list()->add_logical_volume(); | |
| lv->set_name(name); | |
| } | |
| { | |
| InSequence seq; | |
| EXPECT_CALL(*lvm_ptr_, RemoveLogicalVolume(_, "lv1")) | |
| .WillOnce((Return(true))); | |
| EXPECT_CALL(*lvm_ptr_, RemoveLogicalVolume(_, "lv2")) | |
| .WillOnce(Return(false)); | |
| EXPECT_FALSE(lvmd_->RemoveLogicalVolumes(&err, request, &response)); | |
| } | |
| ASSERT_TRUE(response.has_logical_volume_list()); | |
| EXPECT_EQ(response.logical_volume_list().logical_volume_size(), 1); | |
| EXPECT_EQ(response.logical_volume_list().logical_volume().at(0).name(), | |
| "lv2"); | |
| } | |
| } // namespace lvmd |