// 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.

#include "google3/host_commands.h"

#include "ec_util.hpp"
#include "host_command_mock.hpp"
#include "payload_update.hpp"

#include <xyz/openbmc_project/Control/Hoth/error.hpp>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

using namespace std::literals;
using namespace sdbusplus::error::xyz::openbmc_project::control::hoth;

using ::testing::_;
using ::testing::Return;

namespace google
{
namespace hoth
{
namespace internal
{
namespace
{

auto const goodResponseStr = "\x03\xfd\x00\x00\x00\x00\x00\x00"s;

class EcUtilTest : public ::testing::Test
{
  protected:
    EcUtilTest() : ecUtil(&hostCmd)
    {}

    // Host Command interface handle
    internal::HostCommandMock hostCmd;

    // EcUtil interface handle
    internal::EcUtilImpl ecUtil;
};

MATCHER_P(dummyMatches, req, "")
{
  const auto *const arg_req = static_cast<const uint8_t *>(arg);
  return *arg_req == req;
}

class EcUtilStatisticTest : public EcUtilTest
{};

TEST_F(EcUtilStatisticTest, sendCommandReturnsBadResultFails)
{
    std::vector<uint8_t> rsp(goodResponseStr.begin(), goodResponseStr.end());
    // Change the RspHeader.result to something other than EC_RES_SUCCESS
    rsp[2] = internal::EC_RES_ERROR;

    EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
                                         EC_PRV_CMD_HOTH_GET_STATISTICS,
                                     ecUtil.kVersionZero, nullptr, 0))
        .WillOnce(Return(rsp));

    EXPECT_THROW(ecUtil.getHothStatistics(), ResponseFailure);
}

TEST_F(EcUtilStatisticTest, sendCommandReturnsGoodResponseSuccess)
{
    std::vector<uint8_t> rsp(goodResponseStr.begin(), goodResponseStr.end());
    for (uint16_t i = 0; i < 256; i++)
    {
      rsp.push_back(0);
    }

    EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
                                         EC_PRV_CMD_HOTH_GET_STATISTICS,
                                     ecUtil.kVersionZero, nullptr, 0))
        .WillOnce(Return(rsp));

    EXPECT_NO_THROW(ecUtil.getHothStatistics());
}

class EcUtilPersistentPanicTest : public EcUtilTest
{};

struct panic_host_command_response
{
    RspHeader hdr;
    uint8_t body[HOTH_PERSISTENT_PANIC_INFO_CHUNK_SIZE];
};

// Template of a persistent panic response, with the correct data_len, checksum
// and panic magic.
const panic_host_command_response kPanicResponseTemplate = {
    .hdr =
        {
            .struct_version = 3,
            .checksum = 0xb9,
            .result = 0,
            .data_len = HOTH_PERSISTENT_PANIC_INFO_CHUNK_SIZE,
            .reserved = 0,
        },
    .body =
        {
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0,    0,    0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0,    0,    0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0,    0,    0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0,    0,    0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0,    0,    0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0,    0,    0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0,    0,    0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x50, 0x6e, 0x63, 0x21,
        },
};

TEST_F(EcUtilPersistentPanicTest, incorrectResponseSizeThrows)
{
    std::vector<uint8_t> rsp_buf(sizeof(kPanicResponseTemplate), 0);
    auto* rsp = reinterpret_cast<panic_host_command_response*>(rsp_buf.data());
    *rsp = kPanicResponseTemplate;
    rsp->hdr.data_len -= 1;
    rsp->hdr.checksum += 1;
    rsp_buf.resize(sizeof(kPanicResponseTemplate) - 1);
    EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
                                         EC_PRV_CMD_HOTH_PERSISTENT_PANIC_INFO,
                                     ecUtil.kVersionZero, _,
                                     sizeof(ec_request_persistent_panic_info)))
        .Times(2)
        .WillRepeatedly(Return(rsp_buf));
    EXPECT_THROW(ecUtil.checkHothPersistentPanicInfo(), ResponseFailure);
    EXPECT_THROW(ecUtil.getHothPersistentPanicInfo(), ResponseFailure);
}

TEST_F(EcUtilPersistentPanicTest, incorrectPanicMagicReturnsNullopt)
{
    std::vector<uint8_t> rsp_buf(sizeof(kPanicResponseTemplate), 0);
    auto* rsp = reinterpret_cast<panic_host_command_response*>(rsp_buf.data());
    *rsp = kPanicResponseTemplate;
    rsp->body[143] -= 1;
    rsp->hdr.checksum += 1;
    EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
                                         EC_PRV_CMD_HOTH_PERSISTENT_PANIC_INFO,
                                     ecUtil.kVersionZero, _,
                                     sizeof(ec_request_persistent_panic_info)))
        .Times(2)
        .WillRepeatedly(Return(rsp_buf));
    EXPECT_FALSE(ecUtil.checkHothPersistentPanicInfo());
    EXPECT_FALSE(ecUtil.getHothPersistentPanicInfo());
}

TEST_F(EcUtilPersistentPanicTest, correctHostCommandReturnsFullPanicRecord)
{
    std::vector<uint8_t> rsp_bufs[12];
    for (int i = 0; i < 12; ++i)
    {
        rsp_bufs[i].resize(sizeof(panic_host_command_response));
        auto* rsp =
            reinterpret_cast<panic_host_command_response*>(rsp_bufs[i].data());
        *rsp = kPanicResponseTemplate;
        // Tweak the response a little bit to make each chunk slightly
        // different.
        rsp->body[0] += i;
        rsp->body[HOTH_PERSISTENT_PANIC_INFO_CHUNK_SIZE - 1] -= i;
    }
    EXPECT_CALL(hostCmd, sendCommand(EC_CMD_BOARD_SPECIFIC_BASE +
                                         EC_PRV_CMD_HOTH_PERSISTENT_PANIC_INFO,
                                     ecUtil.kVersionZero, _,
                                     sizeof(ec_request_persistent_panic_info)))
        .Times(13)
        .WillOnce(Return(rsp_bufs[0]))
        .WillOnce(Return(rsp_bufs[0]))
        .WillOnce(Return(rsp_bufs[1]))
        .WillOnce(Return(rsp_bufs[2]))
        .WillOnce(Return(rsp_bufs[3]))
        .WillOnce(Return(rsp_bufs[4]))
        .WillOnce(Return(rsp_bufs[5]))
        .WillOnce(Return(rsp_bufs[6]))
        .WillOnce(Return(rsp_bufs[7]))
        .WillOnce(Return(rsp_bufs[8]))
        .WillOnce(Return(rsp_bufs[9]))
        .WillOnce(Return(rsp_bufs[10]))
        .WillOnce(Return(rsp_bufs[11]));

    EXPECT_TRUE(ecUtil.checkHothPersistentPanicInfo());

    auto panic = ecUtil.getHothPersistentPanicInfo();
    std::span<uint8_t> panic_buf(reinterpret_cast<uint8_t*>(&panic.value()),
                                 sizeof(panic.value()));
    for (uint8_t i = 0; i < 12; ++i)
    {
        size_t chunk_start =
            static_cast<uint32_t>(i) * HOTH_PERSISTENT_PANIC_INFO_CHUNK_SIZE;
        EXPECT_EQ(panic_buf[chunk_start], i);
        EXPECT_EQ(
            panic_buf[chunk_start + HOTH_PERSISTENT_PANIC_INFO_CHUNK_SIZE - 1],
            static_cast<uint8_t>(-i));
    }
}

} // namespace
} // namespace internal
} // namespace hoth
} // namespace google
