/**
 * Copyright © 2020 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_compare_bit_action.hpp"
#include "i2c_interface.hpp"
#include "id_map.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::A;
using ::testing::Return;
using ::testing::SetArgReferee;
using ::testing::Throw;

TEST(I2CCompareBitActionTests, Constructor)
{
    // Test where works
    try
    {
        I2CCompareBitAction action{0x7C, 2, 0};
        EXPECT_EQ(action.getRegister(), 0x7C);
        EXPECT_EQ(action.getPosition(), 2);
        EXPECT_EQ(action.getValue(), 0);
    }
    catch (...)
    {
        ADD_FAILURE() << "Should not have caught exception.";
    }

    // Test where fails: Invalid bit position > 7
    try
    {
        I2CCompareBitAction action{0x7C, 8, 0};
        ADD_FAILURE() << "Should not have reached this line.";
    }
    catch (const std::invalid_argument& e)
    {
        EXPECT_STREQ(e.what(), "Invalid bit position: 8");
    }
    catch (...)
    {
        ADD_FAILURE() << "Should not have caught exception.";
    }

    // Test where fails: Invalid bit value > 1
    try
    {
        I2CCompareBitAction action{0x7C, 2, 2};
        ADD_FAILURE() << "Should not have reached this line.";
    }
    catch (const std::invalid_argument& e)
    {
        EXPECT_STREQ(e.what(), "Invalid bit value: 2");
    }
    catch (...)
    {
        ADD_FAILURE() << "Should not have caught exception.";
    }
}

TEST(I2CCompareBitActionTests, Execute)
{
    // Test where works
    try
    {
        // Create mock I2CInterface: read() returns value 0x96 (1001 0110)
        std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
            std::make_unique<i2c::MockedI2CInterface>();
        EXPECT_CALL(*i2cInterface, isOpen).WillRepeatedly(Return(true));
        EXPECT_CALL(*i2cInterface, read(0x7C, A<uint8_t&>()))
            .WillRepeatedly(SetArgReferee<1>(0x96));

        // Create Device, IDMap, and ActionEnvironment
        Device device{"reg1", true, "/system/chassis/motherboard/reg1",
                      std::move(i2cInterface)};
        IDMap idMap{};
        idMap.addDevice(device);
        ActionEnvironment env{idMap, "reg1"};

        // Test where actual bit value is equal to expected bit value.
        // Test all bits in register value 0x96 == 1001 0110).
        {
            I2CCompareBitAction actions[] = {I2CCompareBitAction{0x7C, 7, 1},
                                             I2CCompareBitAction{0x7C, 6, 0},
                                             I2CCompareBitAction{0x7C, 5, 0},
                                             I2CCompareBitAction{0x7C, 4, 1},
                                             I2CCompareBitAction{0x7C, 3, 0},
                                             I2CCompareBitAction{0x7C, 2, 1},
                                             I2CCompareBitAction{0x7C, 1, 1},
                                             I2CCompareBitAction{0x7C, 0, 0}};
            for (I2CCompareBitAction& action : actions)
            {
                EXPECT_EQ(action.execute(env), true);
            }
        }

        // Test where actual bit value is not equal to expected bit value.
        // Test all bits in register value 0x96 == 1001 0110).
        {
            I2CCompareBitAction actions[] = {I2CCompareBitAction{0x7C, 7, 0},
                                             I2CCompareBitAction{0x7C, 6, 1},
                                             I2CCompareBitAction{0x7C, 5, 1},
                                             I2CCompareBitAction{0x7C, 4, 0},
                                             I2CCompareBitAction{0x7C, 3, 1},
                                             I2CCompareBitAction{0x7C, 2, 0},
                                             I2CCompareBitAction{0x7C, 1, 0},
                                             I2CCompareBitAction{0x7C, 0, 1}};
            for (I2CCompareBitAction& action : actions)
            {
                EXPECT_EQ(action.execute(env), false);
            }
        }
    }
    catch (...)
    {
        ADD_FAILURE() << "Should not have caught exception.";
    }

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

        I2CCompareBitAction action{0x7C, 5, 1};
        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 \"reg1\"");
    }
    catch (...)
    {
        ADD_FAILURE() << "Should not have caught exception.";
    }

    // Test where fails: Reading byte 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, A<uint8_t&>()))
            .Times(1)
            .WillOnce(Throw(
                i2c::I2CException{"Failed to read byte", "/dev/i2c-1", 0x70}));

        // Create Device, IDMap, and ActionEnvironment
        Device device{"reg1", true, "/system/chassis/motherboard/reg1",
                      std::move(i2cInterface)};
        IDMap idMap{};
        idMap.addDevice(device);
        ActionEnvironment env{idMap, "reg1"};

        I2CCompareBitAction action{0x7C, 5, 1};
        action.execute(env);
        ADD_FAILURE() << "Should not have reached this line.";
    }
    catch (const ActionError& e)
    {
        EXPECT_STREQ(e.what(), "ActionError: i2c_compare_bit: { register: "
                               "0x7C, position: 5, value: 1 }");
        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 byte: bus /dev/i2c-1, addr 0x70");
        }
        catch (...)
        {
            ADD_FAILURE() << "Should not have caught exception.";
        }
    }
    catch (...)
    {
        ADD_FAILURE() << "Should not have caught exception.";
    }
}

TEST(I2CCompareBitActionTests, GetRegister)
{
    I2CCompareBitAction action{0x7C, 5, 1};
    EXPECT_EQ(action.getRegister(), 0x7C);
}

TEST(I2CCompareBitActionTests, GetPosition)
{
    I2CCompareBitAction action{0x7C, 5, 1};
    EXPECT_EQ(action.getPosition(), 5);
}

TEST(I2CCompareBitActionTests, GetValue)
{
    I2CCompareBitAction action{0x7C, 5, 1};
    EXPECT_EQ(action.getValue(), 1);
}

TEST(I2CCompareBitActionTests, ToString)
{
    I2CCompareBitAction action{0x7C, 5, 1};
    EXPECT_EQ(action.toString(),
              "i2c_compare_bit: { register: 0x7C, position: 5, value: 1 }");
}
