/**
 * Copyright © 2021 IBM Corporation
 *
 * 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 "action_environment.hpp"
#include "action_error.hpp"
#include "device.hpp"
#include "i2c_capture_bytes_action.hpp"
#include "i2c_interface.hpp"
#include "id_map.hpp"
#include "mock_services.hpp"
#include "mocked_i2c_interface.hpp"

#include <cstdint>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>

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

using namespace phosphor::power::regulators;

using ::testing::NotNull;
using ::testing::Return;
using ::testing::SetArrayArgument;
using ::testing::Throw;
using ::testing::TypedEq;

TEST(I2CCaptureBytesActionTests, Constructor)
{
    // Test where works
    try
    {
        I2CCaptureBytesAction action{0x2A, 2};
        EXPECT_EQ(action.getRegister(), 0x2A);
        EXPECT_EQ(action.getCount(), 2);
    }
    catch (...)
    {
        ADD_FAILURE() << "Should not have caught exception.";
    }

    // Test where fails: Count < 1
    try
    {
        I2CCaptureBytesAction action{0x2A, 0};
        ADD_FAILURE() << "Should not have reached this line.";
    }
    catch (const std::invalid_argument& e)
    {
        EXPECT_STREQ(e.what(), "Invalid byte count: Less than 1");
    }
    catch (...)
    {
        ADD_FAILURE() << "Should not have caught exception.";
    }
}

TEST(I2CCaptureBytesActionTests, Execute)
{
    // Test where works: One byte captured
    try
    {
        // Create mock I2CInterface: read() returns value 0xD7
        std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
            std::make_unique<i2c::MockedI2CInterface>();
        uint8_t values[] = {0xD7};
        EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
        EXPECT_CALL(*i2cInterface, read(0xA0, TypedEq<uint8_t&>(1), NotNull(),
                                        i2c::I2CInterface::Mode::I2C))
            .Times(1)
            .WillOnce(SetArrayArgument<2>(values, values + 1));

        // Create Device, IDMap, MockServices, and ActionEnvironment
        Device device{
            "vdd1", true,
            "/xyz/openbmc_project/inventory/system/chassis/motherboard/vdd1",
            std::move(i2cInterface)};
        IDMap idMap{};
        idMap.addDevice(device);
        MockServices services{};
        ActionEnvironment env{idMap, "vdd1", services};

        I2CCaptureBytesAction action{0xA0, 1};
        EXPECT_EQ(action.execute(env), true);
        EXPECT_EQ(env.getAdditionalErrorData().size(), 1);
        EXPECT_EQ(env.getAdditionalErrorData().at("vdd1_register_0xA0"),
                  "[ 0xD7 ]");
    }
    catch (...)
    {
        ADD_FAILURE() << "Should not have caught exception.";
    }

    // Test where works: Multiple bytes captured
    try
    {
        // Create mock I2CInterface: read() returns values 0x56, 0x14, 0xDA
        std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
            std::make_unique<i2c::MockedI2CInterface>();
        uint8_t values[] = {0x56, 0x14, 0xDA};
        EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
        EXPECT_CALL(*i2cInterface, read(0x7C, TypedEq<uint8_t&>(3), NotNull(),
                                        i2c::I2CInterface::Mode::I2C))
            .Times(1)
            .WillOnce(SetArrayArgument<2>(values, values + 3));

        // Create Device, IDMap, MockServices, and ActionEnvironment
        Device device{
            "vdd1", true,
            "/xyz/openbmc_project/inventory/system/chassis/motherboard/vdd1",
            std::move(i2cInterface)};
        IDMap idMap{};
        idMap.addDevice(device);
        MockServices services{};
        ActionEnvironment env{idMap, "vdd1", services};

        I2CCaptureBytesAction action{0x7C, 3};
        EXPECT_EQ(action.execute(env), true);
        EXPECT_EQ(env.getAdditionalErrorData().size(), 1);
        EXPECT_EQ(env.getAdditionalErrorData().at("vdd1_register_0x7C"),
                  "[ 0x56, 0x14, 0xDA ]");
    }
    catch (...)
    {
        ADD_FAILURE() << "Should not have caught exception.";
    }

    // Test where fails: Getting I2CInterface fails
    try
    {
        // Create IDMap, MockServices, and ActionEnvironment
        IDMap idMap{};
        MockServices services{};
        ActionEnvironment env{idMap, "vdd1", services};

        I2CCaptureBytesAction action{0x7C, 2};
        action.execute(env);
        ADD_FAILURE() << "Should not have reached this line.";
    }
    catch (const std::invalid_argument& e)
    {
        EXPECT_STREQ(e.what(), "Unable to find device with ID \"vdd1\"");
    }
    catch (...)
    {
        ADD_FAILURE() << "Should not have caught exception.";
    }

    // Test where fails: Reading bytes fails
    try
    {
        // Create mock I2CInterface: read() throws an I2CException
        std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
            std::make_unique<i2c::MockedI2CInterface>();
        EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
        EXPECT_CALL(*i2cInterface, read(0x7C, TypedEq<uint8_t&>(2), NotNull(),
                                        i2c::I2CInterface::Mode::I2C))
            .Times(1)
            .WillOnce(Throw(i2c::I2CException{"Failed to read i2c block data",
                                              "/dev/i2c-1", 0x70}));

        // Create Device, IDMap, MockServices, and ActionEnvironment
        Device device{
            "vdd1", true,
            "/xyz/openbmc_project/inventory/system/chassis/motherboard/vdd1",
            std::move(i2cInterface)};
        IDMap idMap{};
        idMap.addDevice(device);
        MockServices services{};
        ActionEnvironment env{idMap, "vdd1", services};

        I2CCaptureBytesAction action{0x7C, 2};
        action.execute(env);
        ADD_FAILURE() << "Should not have reached this line.";
    }
    catch (const ActionError& e)
    {
        EXPECT_STREQ(
            e.what(),
            "ActionError: i2c_capture_bytes: { register: 0x7C, count: 2 }");
        try
        {
            // Re-throw inner I2CException
            std::rethrow_if_nested(e);
            ADD_FAILURE() << "Should not have reached this line.";
        }
        catch (const i2c::I2CException& ie)
        {
            EXPECT_STREQ(ie.what(),
                         "I2CException: Failed to read i2c block data: bus "
                         "/dev/i2c-1, addr 0x70");
        }
        catch (...)
        {
            ADD_FAILURE() << "Should not have caught exception.";
        }
    }
    catch (...)
    {
        ADD_FAILURE() << "Should not have caught exception.";
    }
}

TEST(I2CCaptureBytesActionTests, GetCount)
{
    I2CCaptureBytesAction action{0xA0, 3};
    EXPECT_EQ(action.getCount(), 3);
}

TEST(I2CCaptureBytesActionTests, GetRegister)
{
    I2CCaptureBytesAction action{0xA0, 3};
    EXPECT_EQ(action.getRegister(), 0xA0);
}

TEST(I2CCaptureBytesActionTests, ToString)
{
    I2CCaptureBytesAction action{0xA0, 3};
    EXPECT_EQ(action.toString(),
              "i2c_capture_bytes: { register: 0xA0, count: 3 }");
}
