// Copyright 2020 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 <limits>
#include <memory>
#include <vector>

#include <base/test/task_environment.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "biod/fp_frame_command.h"

namespace biod {
namespace {

using ::testing::Return;

constexpr int kValidMaxReadSize = 128;
constexpr int kValidFrameSize = 4096;
constexpr int kValidIndex = 0;

TEST(FpFrameCommand, FpFrameCommand) {
  auto cmd =
      FpFrameCommand::Create(kValidIndex, kValidFrameSize, kValidMaxReadSize);
  EXPECT_TRUE(cmd);
  EXPECT_EQ(cmd->Version(), 0);
  EXPECT_EQ(cmd->Command(), EC_CMD_FP_FRAME);
}

TEST(FpFrameCommand, InvalidReadSize) {
  constexpr int kInvalidMaxReadSize = kMaxPacketSize + 1;
  EXPECT_FALSE(FpFrameCommand::Create(kValidIndex, kValidFrameSize,
                                      kInvalidMaxReadSize));
}

TEST(FpFrameCommand, InvalidReadSizeZero) {
  constexpr int kInvalidMaxReadSize = 0;
  EXPECT_FALSE(FpFrameCommand::Create(kValidIndex, kValidFrameSize,
                                      kInvalidMaxReadSize));
}

TEST(FpFrameCommand, MaxReadSizeEqualsMaxPacketSize) {
  constexpr int kValidReadSize = kMaxPacketSize;
  EXPECT_TRUE(
      FpFrameCommand::Create(kValidIndex, kValidFrameSize, kValidReadSize));
}

TEST(FpFrameCommand, ZeroFrameSize) {
  constexpr int kInvalidFrameSize = 0;
  EXPECT_FALSE(FpFrameCommand::Create(kValidIndex, kInvalidFrameSize,
                                      kValidMaxReadSize));
}

// Mock the underlying EcCommand to test
class FpFrameCommandTest : public testing::Test {
 public:
  class MockFpFrameCommand : public FpFrameCommand {
   public:
    MockFpFrameCommand(int index, uint32_t frame_size, ssize_t max_read_size)
        : FpFrameCommand(index, frame_size, max_read_size) {
      // Unless overridden, return packets full of zeroes.
      static FpFramePacket packet = {0};
      ON_CALL(*this, Resp).WillByDefault(Return(&packet));
    }
    MOCK_METHOD(bool, EcCommandRun, (int fd), (override));
    MOCK_METHOD(FpFramePacket*, Resp, (), (override));
    MOCK_METHOD(uint32_t, Result, (), (const, override));
  };

 protected:
  base::test::TaskEnvironment task_environment_{
      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
};

TEST_F(FpFrameCommandTest, SmallTemplateSuccess) {
  FpFramePacket packet = {1, 2, 3, 4, 5};
  EXPECT_EQ(packet.size(), 544);
  // Ec command payload is empty until EcCommandRun is called.
  FpFramePacket payload = {0};

  constexpr int kMaxReadSize = 536;  // SPI max packet size is 544. Subtract
                                     // the sizeof(struct ec_host_response)
                                     // to get 536.
  static_assert(kMaxReadSize <= packet.size(),
                "Read size must be less than or equal to packet size");

  // Create a frame that has two full packets worth of data and one partial
  // packet.
  constexpr int kFrameSize = kMaxReadSize + kMaxReadSize + 10;
  auto mock_fp_frame_command =
      FpFrameCommand::Create<MockFpFrameCommand>(0, kFrameSize, kMaxReadSize);

  EXPECT_CALL(*mock_fp_frame_command, Resp).WillRepeatedly(Return(&payload));

  EXPECT_CALL(*mock_fp_frame_command, EcCommandRun)
      .WillRepeatedly(
          // Command is run, so start returning actual packet.
          [&payload, &packet](int fd) {
            payload = packet;
            return true;
          });
  EXPECT_TRUE(mock_fp_frame_command->Run(-1));
  const auto& frame = mock_fp_frame_command->frame();

  // First chunk
  std::vector<uint8_t> packet_vec(packet.begin(),
                                  packet.begin() + kMaxReadSize);
  auto frame_begin = frame->begin();
  auto frame_end = frame->begin() + packet_vec.size();
  std::vector<uint8_t> frame_chunk_1(frame_begin, frame_end);
  EXPECT_EQ(packet_vec, frame_chunk_1);

  // Second chunk
  frame_begin += packet_vec.size();
  frame_end += packet_vec.size();
  std::vector<uint8_t> frame_chunk_2(frame_begin, frame_end);
  EXPECT_EQ(packet_vec, frame_chunk_2);

  // Last chunk (short)
  frame_begin += packet_vec.size();
  frame_end += 10;
  packet_vec.resize(10);
  std::vector<uint8_t> frame_chunk_3(frame_begin, frame_end);
  EXPECT_EQ(packet_vec, frame_chunk_3);
}

TEST_F(FpFrameCommandTest, LargeTemplateSuccess) {
  FpFramePacket packet = {1, 2, 3, 4, 5};
  EXPECT_EQ(packet.size(), 544);
  // Ec command payload is empty until EcCommandRun is called.
  FpFramePacket payload = {0};

  constexpr int kMaxReadSize = 536;  // SPI max packet size is 544. Subtract
                                     // the sizeof(struct ec_host_response)
                                     // to get 536.
  static_assert(kMaxReadSize <= packet.size(),
                "Read size must be less than or equal to packet size");

  // Create a frame that is larger than the max uint16_t value.
  constexpr int kFrameSize = std::numeric_limits<uint16_t>::max() + 10;
  auto mock_fp_frame_command =
      FpFrameCommand::Create<MockFpFrameCommand>(0, kFrameSize, kMaxReadSize);

  EXPECT_CALL(*mock_fp_frame_command, Resp).WillRepeatedly(Return(&payload));

  EXPECT_CALL(*mock_fp_frame_command, EcCommandRun)
      .WillRepeatedly(
          // Command is run, so start returning actual packet.
          [&payload, &packet](int fd) {
            payload = packet;
            return true;
          });
  EXPECT_TRUE(mock_fp_frame_command->Run(-1));
  const auto& frame = mock_fp_frame_command->frame();

  std::vector<uint8_t> packet_vec(packet.begin(),
                                  packet.begin() + kMaxReadSize);
  auto frame_begin = frame->begin();
  auto frame_end = frame->begin() + packet_vec.size();
  while (frame_end + packet_vec.size() < frame->end()) {
    std::vector<uint8_t> chunk(frame_begin, frame_end);
    EXPECT_EQ(packet_vec, chunk);
    frame_begin += packet_vec.size();
    frame_end += packet_vec.size();
  }

  // Last chunk (short).
  frame_begin += packet_vec.size();
  frame_end += kFrameSize % kMaxReadSize;
  EXPECT_EQ(frame_end, frame->end());
  packet_vec.resize(kFrameSize % kMaxReadSize);
  std::vector<uint8_t> chunk(frame_begin, frame_end);
  EXPECT_EQ(packet_vec, chunk);
}

TEST_F(FpFrameCommandTest, RetriesWhenBusy) {
  auto mock_fp_frame_command =
      FpFrameCommand::Create<MockFpFrameCommand>(0, 4096, 128);
  EXPECT_TRUE(mock_fp_frame_command);
  EXPECT_CALL(*mock_fp_frame_command, Result).WillOnce(Return(EC_RES_BUSY));
  EXPECT_CALL(*mock_fp_frame_command, EcCommandRun)
      .WillOnce(Return(false))
      .WillRepeatedly(Return(true));

  EXPECT_TRUE(mock_fp_frame_command->Run(-1));
}

TEST_F(FpFrameCommandTest, FailsIfBusyAfterFirstRequest) {
  auto mock_fp_frame_command =
      FpFrameCommand::Create<MockFpFrameCommand>(0, 4096, 128);
  EXPECT_TRUE(mock_fp_frame_command);
  EXPECT_CALL(*mock_fp_frame_command, Result).WillOnce(Return(EC_RES_BUSY));
  EXPECT_CALL(*mock_fp_frame_command, EcCommandRun)
      .WillOnce(Return(false))   // Failure on first request; triggers retry.
      .WillOnce(Return(true))    // Retry succeeds.
      .WillOnce(Return(false));  // Next request fails. Since it wasn't first
                                 // request, no more retries.

  EXPECT_FALSE(mock_fp_frame_command->Run(-1));
}

TEST_F(FpFrameCommandTest, StopsBusyRetriesAfterMaxAttempts) {
  auto mock_fp_frame_command =
      FpFrameCommand::Create<MockFpFrameCommand>(0, 4096, 128);
  EXPECT_TRUE(mock_fp_frame_command);
  EXPECT_CALL(*mock_fp_frame_command, EcCommandRun)
      .Times(51)
      .WillRepeatedly(Return(false));
  EXPECT_CALL(*mock_fp_frame_command, Result)
      .Times(51)
      .WillRepeatedly(Return(EC_RES_BUSY));
  EXPECT_FALSE(mock_fp_frame_command->Run(-1));
}

}  // namespace
}  // namespace biod
