| // Copyright 2024 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #pragma once |
| |
| #include "command/test/dbus_command_mock.hpp" |
| #include "hoth_skmhss.hpp" |
| #include "hoth_util_mock.hpp" |
| |
| #include <sdbusplus/exception.hpp> |
| #include <sdbusplus/test/sdbus_mock.hpp> |
| #include <xyz/openbmc_project/Control/Hoth/error.hpp> |
| |
| #include <array> |
| #include <cstdint> |
| #include <memory> |
| #include <span> |
| #include <string> |
| #include <string_view> |
| #include <vector> |
| |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| using ipmi_hoth::internal::DbusCommand; |
| using ::testing::_; |
| using ::testing::NotNull; |
| using ::testing::Return; |
| using ResponseFailure = |
| sdbusplus::xyz::openbmc_project::Control::Hoth::Error::ResponseFailure; |
| |
| namespace ipmi_hoth |
| { |
| |
| struct MockCancel : public stdplus::Cancelable |
| { |
| MOCK_METHOD(void, cancel, (), (noexcept, override)); |
| }; |
| |
| class HothSKMHSSTest : public ::testing::Test |
| { |
| public: |
| void expectCmd(uint8_t i, fu2::unique_function<void()>& cb, |
| MockCancel& cancel, std::span<const uint8_t> data) |
| { |
| bool has_data = data.data() != nullptr; |
| EXPECT_CALL(dbus, |
| SendHostCommand( |
| "", testing::ElementsAre(static_cast<uint8_t>(10 + i)), |
| _)) |
| .WillOnce([&cb, &cancel, i, |
| has_data](std::string_view, const std::vector<uint8_t>&, |
| DbusCommand::Cb&& icb) { |
| if (has_data) |
| { |
| cb = [icb = std::move(icb), i]() mutable { |
| icb(std::vector<uint8_t>{static_cast<uint8_t>(20 + i)}); |
| }; |
| } |
| else |
| { |
| cb = [icb = std::move(icb)]() mutable { |
| icb(std::nullopt); |
| }; |
| } |
| return stdplus::Cancel(&cancel); |
| }); |
| if (has_data) |
| { |
| EXPECT_CALL(hvnutil, payloadECResponse(testing::ElementsAre( |
| static_cast<uint8_t>(20 + i)))) |
| .WillOnce(Return(data)); |
| } |
| EXPECT_CALL(cancel, cancel()).WillOnce(Return()); |
| } |
| |
| void expectRead(uint8_t i, fu2::unique_function<void()>& cb, |
| MockCancel& cancel, std::span<const uint8_t> data) |
| { |
| EXPECT_CALL(hvnutil, readSKMHSS(i)) |
| .WillOnce( |
| Return(std::vector<uint8_t>{static_cast<uint8_t>(10 + i)})); |
| expectCmd(i, cb, cancel, data); |
| } |
| |
| std::unique_ptr<HothSKMHSSBlobHandler> |
| createHandler(const std::vector<uint8_t>& data) |
| { |
| std::array<fu2::unique_function<void()>, 4> cbs; |
| std::array<testing::StrictMock<MockCancel>, 4> cancels; |
| for (uint8_t i = 0; i < 4; ++i) |
| { |
| expectRead(i, cbs[i], cancels[i], data); |
| } |
| auto ret = std::make_unique<HothSKMHSSBlobHandler>(&dbus, &hvnutil); |
| for (uint8_t i = 0; i < 4; ++i) |
| { |
| cbs[i](); |
| } |
| testing::Mock::VerifyAndClearExpectations(&hvnutil); |
| testing::Mock::VerifyAndClearExpectations(&dbus); |
| return ret; |
| } |
| |
| // Create a handler with empty HSS cache. |
| std::unique_ptr<HothSKMHSSBlobHandler> createHandlerWithEmptyCache() |
| { |
| return createHandler({}); |
| } |
| |
| // Create a handler with test HSS cache. |
| std::unique_ptr<HothSKMHSSBlobHandler> createHandlerWithTestCache() |
| { |
| return createHandler(testHSSBytes); |
| } |
| |
| protected: |
| // dbus mock object |
| testing::StrictMock<internal::DbusCommandMock> dbus; |
| |
| // Hoth utility mock object |
| testing::StrictMock<internal::HothUtilMock> hvnutil; |
| |
| const uint16_t session = 0; |
| const std::vector<std::string> legacyPath = { |
| "/skm/hss-backup/0", |
| "/skm/hss-backup/1", |
| "/skm/hss-backup/2", |
| "/skm/hss-backup/3", |
| }; |
| const std::vector<uint8_t> testHSSBytes = std::vector<uint8_t>(64, 0x0b); |
| }; |
| |
| class HothSKMHSSBasicTest : public HothSKMHSSTest |
| { |
| public: |
| HothSKMHSSBasicTest() : |
| hvn(HothSKMHSSBasicTest::createHandlerWithTestCache()) |
| {} |
| std::unique_ptr<HothSKMHSSBlobHandler> hvn; |
| }; |
| |
| } // namespace ipmi_hoth |