blob: 4c4410af97e6b9b8f220e59cebba0d82ed9438c8 [file]
// 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 <memory>
#include <utility>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <libec/flash_write_command.h>
namespace ec {
namespace {
using ::testing::Return;
constexpr int kValidMaxWriteSize = 128;
TEST(FlashWriteCommand, FlashWriteCommand) {
auto cmd = FlashWriteCommand::Create(std::vector<uint8_t>(100), 0,
kValidMaxWriteSize);
EXPECT_TRUE(cmd);
EXPECT_EQ(cmd->Version(), 0);
EXPECT_EQ(cmd->Command(), EC_CMD_FLASH_WRITE);
}
TEST(FlashWriteCommand, Params) {
EXPECT_EQ(sizeof(flash_write::Header), sizeof(ec_params_flash_write));
EXPECT_EQ(sizeof(flash_write::Params), kMaxPacketSize);
}
TEST(FlashWriteCommand, InvalidWriteSize) {
constexpr int kInvalidMaxWriteSize = 545;
EXPECT_FALSE(FlashWriteCommand::Create(std::vector<uint8_t>(100), 0,
kInvalidMaxWriteSize));
}
TEST(FlashWriteCommand, InvalidWriteSizeZero) {
constexpr int kInvalidMaxWriteSize = 0;
EXPECT_FALSE(FlashWriteCommand::Create(std::vector<uint8_t>(100), 0,
kInvalidMaxWriteSize));
}
TEST(FlashWriteCommand, MaxWriteSizeEqualsMaxPacketSize) {
constexpr int kValidWriteSize = 544;
EXPECT_TRUE(
FlashWriteCommand::Create(std::vector<uint8_t>(100), 0, kValidWriteSize));
}
TEST(FlashWriteCommand, ZeroFrameSize) {
const std::vector<uint8_t> kInvalidTemplateData(0);
EXPECT_FALSE(
FlashWriteCommand::Create(kInvalidTemplateData, 0, kValidMaxWriteSize));
}
TEST(FlashWriteCommand, OffsetBoundaryCondition) {
constexpr uint32_t kOffset = 4294967295; // 2^32 - 1
EXPECT_TRUE(FlashWriteCommand::Create(std::vector<uint8_t>(1), kOffset,
kValidMaxWriteSize));
EXPECT_FALSE(FlashWriteCommand::Create(std::vector<uint8_t>(2), kOffset,
kValidMaxWriteSize));
}
// Mock the underlying EcCommand to test.
class FlashWriteCommandTest : public testing::Test {
public:
class MockFlashWriteCommand : public FlashWriteCommand {
public:
MockFlashWriteCommand(std::vector<uint8_t> data,
uint32_t offset,
uint16_t max_write_size)
: FlashWriteCommand(std::move(data), offset, max_write_size) {}
MOCK_METHOD(bool, EcCommandRun, (int fd), (override));
MOCK_METHOD(uint32_t, Result, (), (const, override));
};
};
TEST_F(FlashWriteCommandTest, Success) {
constexpr int kMaxWriteSize = 544; // SPI max packet size is 544.
constexpr int kDataSize = 536; // Subtract
// sizeof(struct ec_params_flash_write) to
// get 536.
// Perform a write that has one full packet of data and one partial
// packet.
constexpr int kFlashWriteSize = kDataSize + 10;
std::vector<uint8_t> kFlashWriteData(kFlashWriteSize);
auto begin = kFlashWriteData.begin();
auto end = kFlashWriteData.begin() + kDataSize;
std::fill(begin, end, 'a');
begin += kDataSize;
end += 10;
std::fill(begin, end, 'b');
auto mock_flash_write_command =
FlashWriteCommand::Create<MockFlashWriteCommand>(kFlashWriteData, 5,
kMaxWriteSize);
testing::InSequence s;
EXPECT_CALL(*mock_flash_write_command, EcCommandRun)
.WillOnce([&mock_flash_write_command](int fd) {
EXPECT_EQ(mock_flash_write_command->Req()->req.offset, 5);
EXPECT_EQ(mock_flash_write_command->Req()->req.size, 536);
auto expected = std::array<uint8_t, 536>();
expected.fill('a');
EXPECT_EQ(mock_flash_write_command->Req()->data, expected);
return true;
});
EXPECT_CALL(*mock_flash_write_command, EcCommandRun)
.WillOnce([&mock_flash_write_command](int fd) {
EXPECT_EQ(mock_flash_write_command->Req()->req.offset, 541);
EXPECT_EQ(mock_flash_write_command->Req()->req.size, 10);
auto expected = std::array<uint8_t, 10>();
expected.fill('b');
// Only the first 10 values are valid.
EXPECT_TRUE(
std::equal(mock_flash_write_command->Req()->data.cbegin(),
mock_flash_write_command->Req()->data.cbegin() + 10,
expected.cbegin()));
return true;
});
EXPECT_TRUE(mock_flash_write_command->Run(-1));
}
} // namespace
} // namespace ec