| // 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 "libec/flash_read_command.h" |
| |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| namespace ec { |
| namespace { |
| |
| using ::testing::Return; |
| |
| TEST(FlashReadCommand, FlashReadCommand) { |
| auto cmd = FlashReadCommand::Create(3, 10, 128); |
| EXPECT_EQ(cmd->Version(), 0); |
| EXPECT_EQ(cmd->Command(), EC_CMD_FLASH_READ); |
| } |
| |
| TEST(FlashReadCommand, MaxReadSizeTooLarge) { |
| constexpr int kInvalidMaxReadSize = 545; |
| EXPECT_FALSE(FlashReadCommand::Create(0, 10, kInvalidMaxReadSize)); |
| } |
| |
| TEST(FlashReadCommand, MaxReadSizeZero) { |
| constexpr int kInvalidMaxReadSize = 0; |
| EXPECT_FALSE(FlashReadCommand::Create(0, 10, kInvalidMaxReadSize)); |
| } |
| |
| TEST(FlashReadCommand, OffsetBoundaryCondition) { |
| constexpr uint32_t kOffset = 4294967295; // 2^32 - 1 |
| uint32_t read_size = 1; |
| EXPECT_TRUE(FlashReadCommand::Create(kOffset, read_size, 128)); |
| read_size = 2; |
| EXPECT_FALSE(FlashReadCommand::Create(kOffset, read_size, 128)); |
| } |
| |
| // Mock the underlying EcCommand to test. |
| class FlashReadCommandTest : public testing::Test { |
| public: |
| class MockFlashReadCommand : public FlashReadCommand { |
| public: |
| using FlashReadCommand::FlashReadCommand; |
| MOCK_METHOD(FlashReadPacket*, Resp, (), (override)); |
| MOCK_METHOD(bool, EcCommandRun, (int fd), (override)); |
| MOCK_METHOD(uint32_t, Result, (), (const, override)); |
| }; |
| }; |
| |
| TEST_F(FlashReadCommandTest, SinglePacketGetData) { |
| auto mock_command = |
| FlashReadCommand::Create<MockFlashReadCommand>(0, 5, kMaxPacketSize); |
| FlashReadPacket response; |
| for (int i = 0; i < response.size(); ++i) { |
| response[i] = i; |
| } |
| |
| EXPECT_CALL(*mock_command, EcCommandRun) |
| .WillOnce([&mock_command, &response](int fd) { |
| EXPECT_EQ(mock_command->Req()->offset, 0); |
| EXPECT_EQ(mock_command->Req()->size, 5); |
| EXPECT_CALL(*mock_command, Resp).WillRepeatedly(Return(&response)); |
| EXPECT_CALL(*mock_command, Result) |
| .WillRepeatedly(Return(EC_RES_SUCCESS)); |
| return true; |
| }); |
| |
| EXPECT_TRUE(mock_command->Run(-1)); |
| |
| EXPECT_EQ(mock_command->GetData(), (std::vector<uint8_t>{0, 1, 2, 3, 4})); |
| } |
| |
| TEST_F(FlashReadCommandTest, MultiplePacketsGetData) { |
| constexpr int kReadSize = kMaxPacketSize + 10; |
| auto mock_command = FlashReadCommand::Create<MockFlashReadCommand>( |
| 3, kReadSize, kMaxPacketSize); |
| EXPECT_TRUE(mock_command); |
| |
| FlashReadPacket response1; |
| for (int i = 0; i < response1.size(); ++i) { |
| response1[i] = i; |
| } |
| FlashReadPacket response2; |
| for (int i = 0; i < response2.size(); ++i) { |
| response2[i] = i + response1.size(); |
| } |
| |
| FlashReadPacket response{}; |
| EXPECT_CALL(*mock_command, Resp).WillRepeatedly(Return(&response)); |
| EXPECT_CALL(*mock_command, Result).WillRepeatedly(Return(EC_RES_SUCCESS)); |
| |
| testing::InSequence s; |
| EXPECT_CALL(*mock_command, EcCommandRun) |
| .WillOnce([&mock_command, &response, &response1](int fd) { |
| EXPECT_EQ(mock_command->Req()->offset, 3); |
| EXPECT_EQ(mock_command->Req()->size, 544); |
| response = response1; |
| return true; |
| }); |
| EXPECT_CALL(*mock_command, EcCommandRun) |
| .WillOnce([&mock_command, &response, &response2](int fd) { |
| EXPECT_EQ(mock_command->Req()->offset, 547); |
| EXPECT_EQ(mock_command->Req()->size, 10); |
| response = response2; |
| return true; |
| }); |
| |
| EXPECT_TRUE(mock_command->Run(-1)); |
| |
| std::vector<uint8_t> expected(554); |
| for (int i = 0; i < expected.size(); ++i) { |
| expected[i] = i; |
| } |
| EXPECT_EQ(mock_command->GetData(), expected); |
| } |
| |
| } // namespace |
| } // namespace ec |