#include "ipmi.hpp"
#include "manager_mock.hpp"

#include <cstring>
#include <string>

#include <gtest/gtest.h>

namespace blobs
{

using ::testing::_;
using ::testing::Invoke;
using ::testing::Matcher;
using ::testing::NotNull;
using ::testing::Return;
using ::testing::StrEq;

// ipmid.hpp isn't installed where we can grab it and this value is per BMC
// SoC.
#define MAX_IPMI_BUFFER 64

TEST(BlobStatTest, InvalidRequestLengthReturnsFailure)
{
    // There is a minimum blobId length of one character, this test verifies
    // we check that.

    ManagerMock mgr;
    size_t dataLen;
    uint8_t request[MAX_IPMI_BUFFER] = {0};
    uint8_t reply[MAX_IPMI_BUFFER] = {0};
    auto req = reinterpret_cast<struct BmcBlobStatTx*>(request);
    std::string blobId = "abc";

    req->cmd = BlobOEMCommands::bmcBlobStat;
    req->crc = 0;
    // length() doesn't include the nul-terminator.
    std::memcpy(req->blobId, blobId.c_str(), blobId.length());

    dataLen = sizeof(struct BmcBlobStatTx) + blobId.length();

    EXPECT_EQ(IPMI_CC_REQ_DATA_LEN_INVALID,
              statBlob(&mgr, request, reply, &dataLen));
}

TEST(BlobStatTest, RequestRejectedReturnsFailure)
{
    // The blobId is rejected for any reason.

    ManagerMock mgr;
    size_t dataLen;
    uint8_t request[MAX_IPMI_BUFFER] = {0};
    uint8_t reply[MAX_IPMI_BUFFER] = {0};
    auto req = reinterpret_cast<struct BmcBlobStatTx*>(request);
    std::string blobId = "a";

    req->cmd = BlobOEMCommands::bmcBlobStat;
    req->crc = 0;
    // length() doesn't include the nul-terminator, request buff is initialized
    // to 0s
    std::memcpy(req->blobId, blobId.c_str(), blobId.length());

    dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1;

    EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)),
                          Matcher<struct BlobMeta*>(_)))
        .WillOnce(Return(false));

    EXPECT_EQ(IPMI_CC_UNSPECIFIED_ERROR,
              statBlob(&mgr, request, reply, &dataLen));
}

TEST(BlobStatTest, RequestSucceedsNoMetadata)
{
    // Stat request succeeeds but there were no metadata bytes.

    ManagerMock mgr;
    size_t dataLen;
    uint8_t request[MAX_IPMI_BUFFER] = {0};
    uint8_t reply[MAX_IPMI_BUFFER] = {0};
    auto req = reinterpret_cast<struct BmcBlobStatTx*>(request);
    std::string blobId = "a";

    req->cmd = BlobOEMCommands::bmcBlobStat;
    req->crc = 0;
    // length() doesn't include the nul-terminator, request buff is initialized
    // to 0s
    std::memcpy(req->blobId, blobId.c_str(), blobId.length());

    dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1;

    struct BmcBlobStatRx rep;
    rep.crc = 0x00;
    rep.blobState = 0x01;
    rep.size = 0x100;
    rep.metadataLen = 0x00;

    EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)),
                          Matcher<struct BlobMeta*>(NotNull())))
        .WillOnce(Invoke([&](const std::string& path, struct BlobMeta* meta) {
            meta->blobState = rep.blobState;
            meta->size = rep.size;
            return true;
        }));

    EXPECT_EQ(IPMI_CC_OK, statBlob(&mgr, request, reply, &dataLen));

    EXPECT_EQ(sizeof(rep), dataLen);
    EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep)));
}

TEST(BlobStatTest, RequestSucceedsWithMetadata)
{
    // Stat request succeeds and there were metadata bytes.

    ManagerMock mgr;
    size_t dataLen;
    uint8_t request[MAX_IPMI_BUFFER] = {0};
    uint8_t reply[MAX_IPMI_BUFFER] = {0};
    auto req = reinterpret_cast<struct BmcBlobStatTx*>(request);
    std::string blobId = "a";

    req->cmd = BlobOEMCommands::bmcBlobStat;
    req->crc = 0;
    // length() doesn't include the nul-terminator, request buff is initialized
    // to 0s
    std::memcpy(req->blobId, blobId.c_str(), blobId.length());

    dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1;

    struct BlobMeta lmeta;
    lmeta.blobState = 0x01;
    lmeta.size = 0x100;
    lmeta.metadata.push_back(0x01);
    lmeta.metadata.push_back(0x02);
    lmeta.metadata.push_back(0x03);
    lmeta.metadata.push_back(0x04);

    struct BmcBlobStatRx rep;
    rep.crc = 0x00;
    rep.blobState = lmeta.blobState;
    rep.size = lmeta.size;
    rep.metadataLen = lmeta.metadata.size();

    EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)),
                          Matcher<struct BlobMeta*>(NotNull())))
        .WillOnce(Invoke([&](const std::string& path, struct BlobMeta* meta) {
            (*meta) = lmeta;
            return true;
        }));

    EXPECT_EQ(IPMI_CC_OK, statBlob(&mgr, request, reply, &dataLen));

    EXPECT_EQ(sizeof(rep) + lmeta.metadata.size(), dataLen);
    EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep)));
    EXPECT_EQ(0, std::memcmp(reply + sizeof(rep), lmeta.metadata.data(),
                             lmeta.metadata.size()));
}
} // namespace blobs
