/*
 * SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION &
 * AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0
 *
 * 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 "base.h"
#include "device-configuration.h"
#include "diagnostics.h"
#include "pci-links.h"
#include "platform-environmental.h"

#include "utils.hpp"

#include <functional>

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

using ::testing::Test;

#define private public
#define protected public
#include "mockupResponder.hpp"
class MockupResponderTest : public Test
{
  private:
    template <typename ResponseStruct>
    void test(
        const nsm_msg* requestMsg, size_t requestMsgLen,
        std::function<std::optional<Response>(const nsm_msg*, size_t)> handler,
        uint8_t command, ResponseStruct& response)
    {
        // Good Test
        auto resp = handler(requestMsg, requestMsgLen);

        EXPECT_TRUE(resp.has_value());
        EXPECT_EQ(resp.value().size(),
                  sizeof(nsm_msg_hdr) + sizeof(ResponseStruct));

        auto msg = reinterpret_cast<nsm_msg*>(resp.value().data());
        EXPECT_GE(sizeof(ResponseStruct), sizeof(nsm_common_resp));
        auto common = reinterpret_cast<nsm_common_resp*>(msg->payload);
        EXPECT_EQ(command, common->command);
        EXPECT_EQ(sizeof(ResponseStruct) - sizeof(nsm_common_resp),
                  common->data_size);
        response = *reinterpret_cast<ResponseStruct*>(msg->payload);

        // Bad tests
        resp = handler(nullptr, requestMsgLen);
        EXPECT_FALSE(resp.has_value());
        resp = handler(requestMsg, requestMsgLen - 1);
        EXPECT_FALSE(resp.has_value());

        auto badRequest = Request((uint8_t*)requestMsg,
                                  (uint8_t*)requestMsg + requestMsgLen);
        auto badRequestMsg = reinterpret_cast<nsm_msg*>(badRequest.data());
        badRequestMsg->hdr.ocp_type = 0;
        resp = handler(badRequestMsg, requestMsgLen);
        EXPECT_FALSE(resp.has_value());
    }

    template <typename ResponseStruct>
    void
        test(const nsm_msg* requestMsg, size_t requestMsgLen,
             std::function<std::optional<Response>(const nsm_msg*, size_t, bool,
                                                   std::optional<Request>&)>
                 handler,
             uint8_t command, ResponseStruct& response)
    {
        std::optional<Request> longRunningEvent;
        // test as not long running
        test(requestMsg, requestMsgLen,
             [&handler, &longRunningEvent](const nsm_msg* request, size_t len) {
            return handler(request, len, false, longRunningEvent);
        }, command, response);

        // test as long running
        auto resp = handler(requestMsg, requestMsgLen, true, longRunningEvent);

        EXPECT_TRUE(resp.has_value());
        EXPECT_EQ(resp.value().size(),
                  sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
        auto respMsg = reinterpret_cast<nsm_msg*>(resp.value().data());
        auto commonResp = reinterpret_cast<nsm_common_resp*>(respMsg->payload);
        EXPECT_EQ(command, commonResp->command);
        EXPECT_EQ(NSM_ACCEPTED, commonResp->completion_code);
        EXPECT_EQ(0, commonResp->reserved);
        EXPECT_EQ(0, commonResp->data_size);

        EXPECT_TRUE(longRunningEvent.has_value());
        EXPECT_EQ(longRunningEvent.value().size(),
                  sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
                      sizeof(nsm_long_running_resp) + sizeof(ResponseStruct) -
                      sizeof(nsm_common_resp));
    }

  protected:
    MockupResponderTest() : event(sdeventplus::Event::get_default())

    {
        init(30, NSM_DEV_ID_GPU, 2);
    }

    uint8_t instanceId = 0;
    sdeventplus::Event event;
    boost::asio::io_context io;
    std::shared_ptr<sdbusplus::asio::connection> systemBus;
    std::shared_ptr<sdbusplus::asio::object_server> objServer;
    std::shared_ptr<MockupResponder::MockupResponder> mockupResponder;

    void init(eid_t eid, uint8_t deviceType, uint8_t instanceId)
    {
        this->instanceId = instanceId;
        systemBus = std::make_shared<sdbusplus::asio::connection>(io);
        objServer = std::make_shared<sdbusplus::asio::object_server>(systemBus);
        mockupResponder = std::make_shared<MockupResponder::MockupResponder>(
            true, event, *objServer, eid, deviceType, instanceId);
    }

    void testProperty(uint8_t propertyIdentifier,
                      const std::string& expectedValue)
    {
        // get property
        auto res = mockupResponder->getProperty(propertyIdentifier);
        EXPECT_NE(res.size(), 0);

        // verify property value
        std::string returnedValue((char*)res.data(), res.size());
        EXPECT_STREQ(returnedValue.c_str(), expectedValue.c_str());
    }
    void testProperty(uint8_t propertyIdentifier, uint32_t expectedValue)
    {
        // get property
        auto res = mockupResponder->getProperty(propertyIdentifier);
        EXPECT_EQ(res.size(), sizeof(uint32_t));

        // verify property value
        uint32_t returnedValue = htole32(*(uint32_t*)res.data());
        EXPECT_EQ(returnedValue, expectedValue);
    }

    using MockupResponderFunction = std::optional<Response> (
        MockupResponder::MockupResponder::*)(const nsm_msg*, size_t);

    template <typename RequestPayload, typename ResponseStruct,
              typename MockupFunction>
    void test(std::function<int(uint8_t, const RequestPayload*, nsm_msg*)>
                  encodeRequestFunction,
              RequestPayload& requestPayload, MockupFunction handlerFunction,
              uint8_t command, ResponseStruct& response)
    {
        Request request(sizeof(nsm_msg_hdr) + sizeof(nsm_common_req) +
                            sizeof(RequestPayload),
                        0);
        auto requestMsg = reinterpret_cast<nsm_msg*>(request.data());
        auto rc = encodeRequestFunction(
            instanceId, const_cast<const RequestPayload*>(&requestPayload),
            requestMsg);
        EXPECT_EQ(rc, NSM_SW_SUCCESS);
        auto handler = std::bind_front(handlerFunction, mockupResponder.get());
        test(requestMsg, request.size(), handler, command, response);
    }
    template <typename RequestPayload, typename MockupFunction>
    void test(std::function<int(uint8_t, RequestPayload, nsm_msg*)>
                  encodeRequestFunction,
              RequestPayload requestPayload, MockupFunction handlerFunction,
              uint8_t command)
    {
        Request request(sizeof(nsm_msg_hdr) + sizeof(nsm_common_req) +
                        sizeof(RequestPayload));
        auto requestMsg = reinterpret_cast<nsm_msg*>(request.data());
        auto rc = encodeRequestFunction(instanceId, requestPayload, requestMsg);
        EXPECT_EQ(rc, NSM_SW_SUCCESS);
        nsm_common_resp response;
        auto handler = std::bind_front(handlerFunction, mockupResponder.get());
        test(requestMsg, request.size(), handler, command, response);
        EXPECT_EQ(NSM_SUCCESS, response.completion_code);
    }
    template <typename ResponseStruct, typename MockupFunction>
    void test(std::function<int(uint8_t, nsm_msg*)> encodeRequestFunction,
              MockupFunction handlerFunction, uint8_t command,
              ResponseStruct& response)
    {
        Request request(sizeof(nsm_msg_hdr) + sizeof(nsm_common_req));
        auto requestMsg = reinterpret_cast<nsm_msg*>(request.data());
        auto rc = encodeRequestFunction(instanceId, requestMsg);
        EXPECT_EQ(rc, NSM_SW_SUCCESS);
        auto handler = std::bind_front(handlerFunction, mockupResponder.get());
        test(requestMsg, request.size(), handler, command, response);
    }
};

TEST_F(MockupResponderTest, goodTestGetPropertyTest)
{
    testProperty(BOARD_PART_NUMBER, "MCX750500B-0D00_DK");
    testProperty(SERIAL_NUMBER, "SN123456789");
    testProperty(MARKETING_NAME, "NV123");
    testProperty(PRODUCT_LENGTH, 850);
    testProperty(PRODUCT_WIDTH, 730);
    testProperty(PRODUCT_HEIGHT, 2600);
    testProperty(MINIMUM_DEVICE_POWER_LIMIT, 10000);
    testProperty(MAXIMUM_DEVICE_POWER_LIMIT, 100000);
}

TEST_F(MockupResponderTest, goodTestUuidPropertyTest)
{
    uuid_t expectedUuid("72000000-0000-0000-0000-000000000000");

    // get Uuid property
    auto res = mockupResponder->getProperty(DEVICE_GUID);
    EXPECT_EQ(res.size(), 16);
    // verify Uuid property value
    auto uuidProperty = utils::convertUUIDToString(res);
    EXPECT_STREQ(uuidProperty.substr(2).c_str(),
                 expectedUuid.substr(2).c_str());
}

TEST_F(MockupResponderTest, goodTestPowerSupplyStatusTest)
{
    const uint8_t expectedStatus = 0b00110011;
    std::vector<uint8_t> requestMsg(
        sizeof(nsm_msg_hdr) + sizeof(nsm_get_fpga_diagnostics_settings_req));

    auto request = reinterpret_cast<nsm_msg*>(requestMsg.data());
    fpga_diagnostics_settings_data_index data_index = GET_POWER_SUPPLY_STATUS;

    auto rc = encode_get_fpga_diagnostics_settings_req(0, data_index, request);
    EXPECT_EQ(rc, NSM_SW_SUCCESS);

    auto res = mockupResponder->getFpgaDiagnosticsSettingsHandler(
        request, requestMsg.size());

    EXPECT_TRUE(res.has_value());
    EXPECT_EQ(res.value().size(),
              sizeof(nsm_msg_hdr) + sizeof(nsm_get_power_supply_status_resp));

    auto response = reinterpret_cast<nsm_msg*>(res.value().data());
    auto resp = (nsm_get_power_supply_status_resp*)response->payload;

    EXPECT_EQ(NSM_GET_FPGA_DIAGNOSTICS_SETTINGS, resp->hdr.command);
    EXPECT_EQ(expectedStatus, resp->power_supply_status);
}

TEST_F(MockupResponderTest, goodTestGpuPresenceTest)
{
    uint32_t expectedPresence = 0b11111111;
    std::vector<uint8_t> requestMsg(
        sizeof(nsm_msg_hdr) + sizeof(nsm_get_fpga_diagnostics_settings_req));

    auto request = reinterpret_cast<nsm_msg*>(requestMsg.data());
    fpga_diagnostics_settings_data_index data_index = GET_GPU_PRESENCE;

    auto rc = encode_get_fpga_diagnostics_settings_req(0, data_index, request);
    EXPECT_EQ(rc, NSM_SW_SUCCESS);

    auto res = mockupResponder->getFpgaDiagnosticsSettingsHandler(
        request, requestMsg.size());

    EXPECT_TRUE(res.has_value());
    EXPECT_EQ(res.value().size(),
              sizeof(nsm_msg_hdr) + sizeof(nsm_get_gpu_presence_resp));

    auto response = reinterpret_cast<nsm_msg*>(res.value().data());
    auto resp = (nsm_get_gpu_presence_resp*)response->payload;

    EXPECT_EQ(NSM_GET_FPGA_DIAGNOSTICS_SETTINGS, resp->hdr.command);
    EXPECT_EQ(expectedPresence, resp->presence);
}

TEST_F(MockupResponderTest, goodTestGpuPresenceAndPowerStatusTest)
{
    uint32_t expectedPower = 0b11110111;
    std::vector<uint8_t> requestMsg(
        sizeof(nsm_msg_hdr) + sizeof(nsm_get_fpga_diagnostics_settings_req));

    auto request = reinterpret_cast<nsm_msg*>(requestMsg.data());
    fpga_diagnostics_settings_data_index data_index = GET_GPU_POWER_STATUS;

    auto rc = encode_get_fpga_diagnostics_settings_req(0, data_index, request);
    EXPECT_EQ(rc, NSM_SW_SUCCESS);

    auto res = mockupResponder->getFpgaDiagnosticsSettingsHandler(
        request, requestMsg.size());

    EXPECT_TRUE(res.has_value());
    EXPECT_EQ(res.value().size(),
              sizeof(nsm_msg_hdr) + sizeof(nsm_get_gpu_power_status_resp));

    auto response = reinterpret_cast<nsm_msg*>(res.value().data());
    auto resp = (nsm_get_gpu_power_status_resp*)response->payload;

    EXPECT_EQ(NSM_GET_FPGA_DIAGNOSTICS_SETTINGS, resp->hdr.command);
    EXPECT_EQ(expectedPower, resp->power_status);
}

TEST_F(MockupResponderTest, goodTestGetReconfigurationPermissionsV1Handler)
{
    Request request(sizeof(nsm_msg_hdr) +
                    sizeof(nsm_get_reconfiguration_permissions_v1_req));

    auto requestMsg = reinterpret_cast<nsm_msg*>(request.data());
    reconfiguration_permissions_v1_index setting_index = RP_IN_SYSTEM_TEST;

    auto rc = encode_get_reconfiguration_permissions_v1_req(0, setting_index,
                                                            requestMsg);
    EXPECT_EQ(rc, NSM_SW_SUCCESS);

    auto resp = mockupResponder->getReconfigurationPermissionsV1Handler(
        requestMsg, request.size());

    EXPECT_TRUE(resp.has_value());
    EXPECT_EQ(resp.value().size(),
              sizeof(nsm_msg_hdr) +
                  sizeof(nsm_get_reconfiguration_permissions_v1_resp));

    auto msg = reinterpret_cast<nsm_msg*>(resp.value().data());
    auto response =
        reinterpret_cast<nsm_get_reconfiguration_permissions_v1_resp*>(
            msg->payload);

    nsm_reconfiguration_permissions_v1 expected = {0, 0, 0, 0, 1, 0, 1};
    EXPECT_EQ(NSM_GET_RECONFIGURATION_PERMISSIONS_V1, response->hdr.command);
    EXPECT_EQ(expected.host_oneshot, response->data.host_oneshot);
    EXPECT_EQ(expected.host_persistent, response->data.host_persistent);
    EXPECT_EQ(expected.host_flr_persistent, response->data.host_flr_persistent);
}

TEST_F(MockupResponderTest, goodTestSetReconfigurationPermissionsV1Handler)
{
    Request request(sizeof(nsm_msg_hdr) +
                    sizeof(nsm_set_reconfiguration_permissions_v1_req));

    auto requestMsg = reinterpret_cast<nsm_msg*>(request.data());
    auto settingIndex = RP_IN_SYSTEM_TEST;
    auto configuration = RP_ONESHOOT_HOT_RESET;
    uint8_t permission = 0;

    auto rc = encode_set_reconfiguration_permissions_v1_req(
        0, settingIndex, configuration, permission, requestMsg);
    EXPECT_EQ(rc, NSM_SW_SUCCESS);

    auto resp = mockupResponder->setReconfigurationPermissionsV1Handler(
        requestMsg, request.size());

    EXPECT_TRUE(resp.has_value());
    EXPECT_EQ(resp.value().size(),
              sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));

    auto msg = reinterpret_cast<nsm_msg*>(resp.value().data());
    auto response = reinterpret_cast<nsm_common_resp*>(msg->payload);

    EXPECT_EQ(NSM_SET_RECONFIGURATION_PERMISSIONS_V1, response->command);
}

TEST_F(MockupResponderTest, testGetErrorInjectionModeV1Handler)
{
    nsm_get_error_injection_mode_v1_resp response;
    test(&encode_get_error_injection_mode_v1_req,
         &MockupResponder::MockupResponder::getErrorInjectionModeV1Handler,
         NSM_GET_ERROR_INJECTION_MODE_V1, response);
    EXPECT_EQ(mockupResponder->state.errorInjectionMode.mode,
              response.data.mode);
    EXPECT_EQ(mockupResponder->state.errorInjectionMode.flags.byte,
              response.data.flags.byte);
}

TEST_F(MockupResponderTest, testGetSupportedErrorInjectionTypesHandler)
{
    nsm_get_error_injection_types_mask_resp response;
    test(&encode_get_supported_error_injection_types_v1_req,
         &MockupResponder::MockupResponder::
             getSupportedErrorInjectionTypesV1Handler,
         NSM_GET_SUPPORTED_ERROR_INJECTION_TYPES_V1, response);
    for (const auto& [type, _] :
         mockupResponder->state.errorInjection[NSM_DEV_ID_GPU])
    {
        EXPECT_TRUE(response.data.mask[type / 8] & (1 << (type % 8)));
    }
}

TEST_F(MockupResponderTest, testSetCurrentErrorInjectionTypesHandler)
{
    nsm_error_injection_types_mask data = {0, 0, 0, 0, 0, 0, 0, 0};
    nsm_common_resp response;
    for (const auto& [type, _] :
         mockupResponder->state.errorInjection[NSM_DEV_ID_GPU])
    {
        data.mask[type / 8] |= (1 << (type % 8));
    }
    test<nsm_error_injection_types_mask>(
        &encode_set_current_error_injection_types_v1_req, data,
        &MockupResponder::MockupResponder::
            setCurrentErrorInjectionTypesV1Handler,
        NSM_SET_CURRENT_ERROR_INJECTION_TYPES_V1, response);
}
TEST_F(MockupResponderTest, testGetCurrentErrorInjectionTypesHandler)
{
    nsm_get_error_injection_types_mask_resp response;
    test(&encode_get_current_error_injection_types_v1_req,
         &MockupResponder::MockupResponder::
             getCurrentErrorInjectionTypesV1Handler,
         NSM_GET_CURRENT_ERROR_INJECTION_TYPES_V1, response);
    for (const auto& [type, enabled] :
         mockupResponder->state.errorInjection[NSM_DEV_ID_GPU])
    {
        EXPECT_EQ(enabled, response.data.mask[type / 8] & (1 << (type % 8)));
    }
}

TEST_F(MockupResponderTest, testMigModeHandler)
{
    nsm_get_MIG_mode_resp response;
    test(&encode_get_MIG_mode_req,
         &MockupResponder::MockupResponder::getMigModeHandler, NSM_GET_MIG_MODE,
         response);
    EXPECT_EQ(mockupResponder->state.migMode, response.flags.byte);
    uint8_t data = 1;
    test<uint8_t>(&encode_set_MIG_mode_req, data,
                  &MockupResponder::MockupResponder::setMigModeHandler,
                  NSM_SET_MIG_MODE);
    test(&encode_get_MIG_mode_req,
         &MockupResponder::MockupResponder::getMigModeHandler, NSM_GET_MIG_MODE,
         response);
    EXPECT_EQ(mockupResponder->state.migMode, response.flags.byte);
}

TEST_F(MockupResponderTest, testEccModeHandler)
{
    nsm_get_ECC_mode_resp response;
    test(&encode_get_ECC_mode_req,
         &MockupResponder::MockupResponder::getEccModeHandler, NSM_GET_ECC_MODE,
         response);
    EXPECT_EQ(mockupResponder->state.eccMode, response.flags.byte);
    uint8_t data = 1;
    test<uint8_t>(&encode_set_ECC_mode_req, data,
                  &MockupResponder::MockupResponder::setEccModeHandler,
                  NSM_SET_ECC_MODE);
    test(&encode_get_ECC_mode_req,
         &MockupResponder::MockupResponder::getEccModeHandler, NSM_GET_ECC_MODE,
         response);
    EXPECT_EQ(mockupResponder->state.eccMode, response.flags.byte);
}

TEST_F(MockupResponderTest, testGetMemoryCapacityUtilHandler)
{
    nsm_get_memory_capacity_util_resp response;
    test(&encode_get_memory_capacity_util_req,
         &MockupResponder::MockupResponder::getMemoryCapacityUtilHandler,
         NSM_GET_MEMORY_CAPACITY_UTILIZATION, response);
}

TEST_F(MockupResponderTest, testGetCurrentUtilizationHandler)
{
    nsm_get_current_utilization_resp response;
    test(&encode_get_current_utilization_req,
         &MockupResponder::MockupResponder::getCurrentUtilizationHandler,
         NSM_GET_CURRENT_UTILIZATION, response);
}

TEST_F(MockupResponderTest, testGetViolationDurationHandler)
{
    nsm_get_violation_duration_resp response;
    test(&encode_get_violation_duration_req,
         &MockupResponder::MockupResponder::getViolationDurationHandler,
         NSM_GET_VIOLATION_DURATION, response);
}

TEST_F(MockupResponderTest, testListAvailablePciePortsHandler)
{
    nsm_list_available_pcie_ports_resp response;
    test(&encode_list_available_pcie_ports_req,
         &MockupResponder::MockupResponder::getListAvailablePciePortsHandler,
         NSM_LIST_AVAILABLE_PCIE_PORTS, response);
}

struct QueryScalarGroupTelemetryV1GroupReqData
{
    uint8_t deviceId;
    uint8_t groupId;
} __attribute__((packed));

auto encodeQueryScalarGroupTelemetryV1Req()
{
    return
        [&](uint8_t instanceId,
            const QueryScalarGroupTelemetryV1GroupReqData* data, nsm_msg* msg) {
        return encode_query_scalar_group_telemetry_v1_req(
            instanceId, data->deviceId, data->groupId, msg);
    };
}

TEST_F(MockupResponderTest, testQueryScalarGroup10TelemetryHandler)
{
    QueryScalarGroupTelemetryV1GroupReqData data = {0, GROUP_ID_10};
    nsm_query_scalar_group_telemetry_v1_group_10_resp response;
    test<QueryScalarGroupTelemetryV1GroupReqData>(
        encodeQueryScalarGroupTelemetryV1Req(), data,
        &MockupResponder::MockupResponder::queryScalarGroupTelemetryHandler,
        NSM_QUERY_SCALAR_GROUP_TELEMETRY_V1, response);
}
TEST_F(MockupResponderTest, testMultiportQueryScalarGroup10TelemetryHandler)
{
    nsm_multiport_query_scalar_group_telemetry_v2_req_data data = {
        0, NSM_PORT_TYPE_UPSTREAM, 0, GROUP_ID_10};
    nsm_query_scalar_group_telemetry_v1_group_10_resp response;
    test<nsm_multiport_query_scalar_group_telemetry_v2_req_data>(
        &encode_multiport_query_scalar_group_telemetry_v2_req, data,
        &MockupResponder::MockupResponder::
            queryMultiportScalarGroupTelemetryHandler,
        NSM_MULTIPORT_QUERY_SCALAR_GROUP_TELEMETRY_V2, response);
}
