/**
 * 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 "config_file_parser_error.hpp"
#include "error_logging.hpp"
#include "error_logging_utils.hpp"
#include "i2c_interface.hpp"
#include "journal.hpp"
#include "mock_error_logging.hpp"
#include "mock_journal.hpp"
#include "mock_services.hpp"
#include "pmbus_error.hpp"
#include "test_sdbus_error.hpp"
#include "write_verification_error.hpp"

#include <errno.h>

#include <sdbusplus/exception.hpp>

#include <exception>
#include <filesystem>
#include <stdexcept>
#include <string>

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

using namespace phosphor::power::regulators;

namespace fs = std::filesystem;

using ::testing::Ref;

TEST(ErrorLoggingUtilsTests, LogError_3Parameters)
{
    // Create exception with two nesting levels; top priority is inner
    // PMBusError
    std::exception_ptr eptr;
    try
    {
        try
        {
            throw PMBusError{"VOUT_MODE contains unsupported data format",
                             "reg1",
                             "/xyz/openbmc_project/inventory/system/chassis/"
                             "motherboard/reg1"};
        }
        catch (...)
        {
            std::throw_with_nested(
                std::runtime_error{"Unable to set output voltage"});
        }
    }
    catch (...)
    {
        eptr = std::current_exception();
    }

    // Create MockServices.  Expect logPMBusError() to be called.
    MockServices services{};
    MockErrorLogging& errorLogging = services.getMockErrorLogging();
    MockJournal& journal = services.getMockJournal();
    EXPECT_CALL(
        errorLogging,
        logPMBusError(
            Entry::Level::Error, Ref(journal),
            "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1"))
        .Times(1);

    // Log error based on the nested exception
    error_logging_utils::logError(eptr, Entry::Level::Error, services);
}

TEST(ErrorLoggingUtilsTests, LogError_4Parameters)
{
    // Test where exception pointer is null
    {
        std::exception_ptr eptr;

        // Create MockServices.  Don't expect any log*() methods to be called.
        MockServices services{};

        ErrorHistory history{};
        error_logging_utils::logError(eptr, Entry::Level::Error, services,
                                      history);
    }

    // Test where exception is not nested
    {
        std::exception_ptr eptr;
        try
        {
            throw i2c::I2CException{"Unable to open device reg1", "/dev/i2c-8",
                                    0x30, ENODEV};
        }
        catch (...)
        {
            eptr = std::current_exception();
        }

        // Create MockServices.  Expect logI2CError() to be called.
        MockServices services{};
        MockErrorLogging& errorLogging = services.getMockErrorLogging();
        MockJournal& journal = services.getMockJournal();
        EXPECT_CALL(errorLogging,
                    logI2CError(Entry::Level::Critical, Ref(journal),
                                "/dev/i2c-8", 0x30, ENODEV))
            .Times(1);

        // Log error based on the nested exception
        ErrorHistory history{};
        error_logging_utils::logError(eptr, Entry::Level::Critical, services,
                                      history);
    }

    // Test where exception is nested
    {
        std::exception_ptr eptr;
        try
        {
            try
            {
                throw std::invalid_argument{"JSON element is not an array"};
            }
            catch (...)
            {
                std::throw_with_nested(ConfigFileParserError{
                    fs::path{"/etc/phosphor-regulators/config.json"},
                    "Unable to parse JSON configuration file"});
            }
        }
        catch (...)
        {
            eptr = std::current_exception();
        }

        // Create MockServices.  Expect logConfigFileError() to be called.
        MockServices services{};
        MockErrorLogging& errorLogging = services.getMockErrorLogging();
        MockJournal& journal = services.getMockJournal();
        EXPECT_CALL(errorLogging,
                    logConfigFileError(Entry::Level::Warning, Ref(journal)))
            .Times(1);

        // Log error based on the nested exception
        ErrorHistory history{};
        error_logging_utils::logError(eptr, Entry::Level::Warning, services,
                                      history);
    }

    // Test where exception is a ConfigFileParserError
    {
        std::exception_ptr eptr;
        try
        {
            throw ConfigFileParserError{
                fs::path{"/etc/phosphor-regulators/config.json"},
                "Unable to parse JSON configuration file"};
        }
        catch (...)
        {
            eptr = std::current_exception();
        }

        // Create MockServices.  Expect logConfigFileError() to be called once.
        MockServices services{};
        MockErrorLogging& errorLogging = services.getMockErrorLogging();
        MockJournal& journal = services.getMockJournal();
        EXPECT_CALL(errorLogging,
                    logConfigFileError(Entry::Level::Error, Ref(journal)))
            .Times(1);

        // Log error based on the nested exception
        ErrorHistory history{};
        error_logging_utils::logError(eptr, Entry::Level::Error, services,
                                      history);

        // Try to log error again.  Should not happen due to ErrorHistory.
        error_logging_utils::logError(eptr, Entry::Level::Error, services,
                                      history);
    }

    // Test where exception is a PMBusError
    {
        std::exception_ptr eptr;
        try
        {
            throw PMBusError{"VOUT_MODE contains unsupported data format",
                             "reg1",
                             "/xyz/openbmc_project/inventory/system/chassis/"
                             "motherboard/reg1"};
        }
        catch (...)
        {
            eptr = std::current_exception();
        }

        // Create MockServices.  Expect logPMBusError() to be called once.
        MockServices services{};
        MockErrorLogging& errorLogging = services.getMockErrorLogging();
        MockJournal& journal = services.getMockJournal();
        EXPECT_CALL(errorLogging,
                    logPMBusError(Entry::Level::Error, Ref(journal),
                                  "/xyz/openbmc_project/inventory/system/"
                                  "chassis/motherboard/reg1"))
            .Times(1);

        // Log error based on the nested exception
        ErrorHistory history{};
        error_logging_utils::logError(eptr, Entry::Level::Error, services,
                                      history);

        // Try to log error again.  Should not happen due to ErrorHistory.
        error_logging_utils::logError(eptr, Entry::Level::Error, services,
                                      history);
    }

    // Test where exception is a WriteVerificationError
    {
        std::exception_ptr eptr;
        try
        {
            throw WriteVerificationError{
                "value_written: 0xDEAD, value_read: 0xBEEF", "reg1",
                "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
                "reg1"};
        }
        catch (...)
        {
            eptr = std::current_exception();
        }

        // Create MockServices.  Expect logWriteVerificationError() to be
        // called once.
        MockServices services{};
        MockErrorLogging& errorLogging = services.getMockErrorLogging();
        MockJournal& journal = services.getMockJournal();
        EXPECT_CALL(errorLogging, logWriteVerificationError(
                                      Entry::Level::Warning, Ref(journal),
                                      "/xyz/openbmc_project/inventory/system/"
                                      "chassis/motherboard/reg1"))
            .Times(1);

        // Log error based on the nested exception
        ErrorHistory history{};
        error_logging_utils::logError(eptr, Entry::Level::Warning, services,
                                      history);

        // Try to log error again.  Should not happen due to ErrorHistory.
        error_logging_utils::logError(eptr, Entry::Level::Warning, services,
                                      history);
    }

    // Test where exception is a I2CException
    {
        std::exception_ptr eptr;
        try
        {
            throw i2c::I2CException{"Unable to open device reg1", "/dev/i2c-8",
                                    0x30, ENODEV};
        }
        catch (...)
        {
            eptr = std::current_exception();
        }

        // Create MockServices.  Expect logI2CError() to be called once.
        MockServices services{};
        MockErrorLogging& errorLogging = services.getMockErrorLogging();
        MockJournal& journal = services.getMockJournal();
        EXPECT_CALL(errorLogging,
                    logI2CError(Entry::Level::Informational, Ref(journal),
                                "/dev/i2c-8", 0x30, ENODEV))
            .Times(1);

        // Log error based on the nested exception
        ErrorHistory history{};
        error_logging_utils::logError(eptr, Entry::Level::Informational,
                                      services, history);

        // Try to log error again.  Should not happen due to ErrorHistory.
        error_logging_utils::logError(eptr, Entry::Level::Informational,
                                      services, history);
    }

    // Test where exception is a sdbusplus::exception_t
    {
        std::exception_ptr eptr;
        try
        {
            // Throw TestSDBusError; exception_t is a pure virtual base class
            throw TestSDBusError{"DBusError: Invalid object path."};
        }
        catch (...)
        {
            eptr = std::current_exception();
        }

        // Create MockServices.  Expect logDBusError() to be called once.
        MockServices services{};
        MockErrorLogging& errorLogging = services.getMockErrorLogging();
        MockJournal& journal = services.getMockJournal();
        EXPECT_CALL(errorLogging,
                    logDBusError(Entry::Level::Debug, Ref(journal)))
            .Times(1);

        // Log error based on the nested exception
        ErrorHistory history{};
        error_logging_utils::logError(eptr, Entry::Level::Debug, services,
                                      history);

        // Try to log error again.  Should not happen due to ErrorHistory.
        error_logging_utils::logError(eptr, Entry::Level::Debug, services,
                                      history);
    }

    // Test where exception is a std::exception
    {
        std::exception_ptr eptr;
        try
        {
            throw std::runtime_error{
                "Unable to read configuration file: No such file or directory"};
        }
        catch (...)
        {
            eptr = std::current_exception();
        }

        // Create MockServices.  Expect logInternalError() to be called once.
        MockServices services{};
        MockErrorLogging& errorLogging = services.getMockErrorLogging();
        MockJournal& journal = services.getMockJournal();
        EXPECT_CALL(errorLogging,
                    logInternalError(Entry::Level::Error, Ref(journal)))
            .Times(1);

        // Log error based on the nested exception
        ErrorHistory history{};
        error_logging_utils::logError(eptr, Entry::Level::Error, services,
                                      history);

        // Try to log error again.  Should not happen due to ErrorHistory.
        error_logging_utils::logError(eptr, Entry::Level::Error, services,
                                      history);
    }

    // Test where exception is unknown type
    {
        std::exception_ptr eptr;
        try
        {
            throw 23;
        }
        catch (...)
        {
            eptr = std::current_exception();
        }

        // Create MockServices.  Expect logInternalError() to be called once.
        MockServices services{};
        MockErrorLogging& errorLogging = services.getMockErrorLogging();
        MockJournal& journal = services.getMockJournal();
        EXPECT_CALL(errorLogging,
                    logInternalError(Entry::Level::Warning, Ref(journal)))
            .Times(1);

        // Log error based on the nested exception
        ErrorHistory history{};
        error_logging_utils::logError(eptr, Entry::Level::Warning, services,
                                      history);

        // Try to log error again.  Should not happen due to ErrorHistory.
        error_logging_utils::logError(eptr, Entry::Level::Warning, services,
                                      history);
    }
}

TEST(ErrorLoggingUtilsTests, GetExceptionToLog)
{
    // Test where exception is not nested
    {
        std::exception_ptr eptr;
        try
        {
            throw i2c::I2CException{"Unable to open device reg1", "/dev/i2c-8",
                                    0x30, ENODEV};
        }
        catch (...)
        {
            eptr = std::current_exception();
        }

        std::exception_ptr exceptionToLog =
            error_logging_utils::internal::getExceptionToLog(eptr);
        EXPECT_EQ(eptr, exceptionToLog);
    }

    // Test where exception is nested: Highest priority is innermost exception
    {
        std::exception_ptr inner, outer;
        try
        {
            try
            {
                throw PMBusError{
                    "VOUT_MODE contains unsupported data format", "reg1",
                    "/xyz/openbmc_project/inventory/system/chassis/"
                    "motherboard/reg1"};
            }
            catch (...)
            {
                inner = std::current_exception();
                std::throw_with_nested(
                    std::runtime_error{"Unable to set output voltage"});
            }
        }
        catch (...)
        {
            outer = std::current_exception();
        }

        std::exception_ptr exceptionToLog =
            error_logging_utils::internal::getExceptionToLog(outer);
        EXPECT_EQ(inner, exceptionToLog);
    }

    // Test where exception is nested: Highest priority is middle exception
    {
        std::exception_ptr inner, middle, outer;
        try
        {
            try
            {
                try
                {
                    throw std::invalid_argument{"JSON element is not an array"};
                }
                catch (...)
                {
                    inner = std::current_exception();
                    std::throw_with_nested(ConfigFileParserError{
                        fs::path{"/etc/phosphor-regulators/config.json"},
                        "Unable to parse JSON configuration file"});
                }
            }
            catch (...)
            {
                middle = std::current_exception();
                std::throw_with_nested(
                    std::runtime_error{"Unable to load config file"});
            }
        }
        catch (...)
        {
            outer = std::current_exception();
        }

        std::exception_ptr exceptionToLog =
            error_logging_utils::internal::getExceptionToLog(outer);
        EXPECT_EQ(middle, exceptionToLog);
    }

    // Test where exception is nested: Highest priority is outermost exception
    {
        std::exception_ptr inner, outer;
        try
        {
            try
            {
                throw std::invalid_argument{"JSON element is not an array"};
            }
            catch (...)
            {
                inner = std::current_exception();
                std::throw_with_nested(ConfigFileParserError{
                    fs::path{"/etc/phosphor-regulators/config.json"},
                    "Unable to parse JSON configuration file"});
            }
        }
        catch (...)
        {
            outer = std::current_exception();
        }

        std::exception_ptr exceptionToLog =
            error_logging_utils::internal::getExceptionToLog(outer);
        EXPECT_EQ(outer, exceptionToLog);
    }

    // Test where exception is nested: Two exceptions have same priority.
    // Should return outermost exception with that priority.
    {
        std::exception_ptr inner, outer;
        try
        {
            try
            {
                throw std::invalid_argument{"JSON element is not an array"};
            }
            catch (...)
            {
                inner = std::current_exception();
                std::throw_with_nested(
                    std::runtime_error{"Unable to load config file"});
            }
        }
        catch (...)
        {
            outer = std::current_exception();
        }

        std::exception_ptr exceptionToLog =
            error_logging_utils::internal::getExceptionToLog(outer);
        EXPECT_EQ(outer, exceptionToLog);
    }

    // Test where exception is nested: Highest priority is ConfigFileParserError
    {
        std::exception_ptr inner, outer;
        try
        {
            try
            {
                throw ConfigFileParserError{
                    fs::path{"/etc/phosphor-regulators/config.json"},
                    "Unable to parse JSON configuration file"};
            }
            catch (...)
            {
                inner = std::current_exception();
                std::throw_with_nested(
                    std::runtime_error{"Unable to load config file"});
            }
        }
        catch (...)
        {
            outer = std::current_exception();
        }

        std::exception_ptr exceptionToLog =
            error_logging_utils::internal::getExceptionToLog(outer);
        EXPECT_EQ(inner, exceptionToLog);
    }

    // Test where exception is nested: Highest priority is PMBusError
    {
        std::exception_ptr inner, outer;
        try
        {
            try
            {
                throw std::invalid_argument{"Invalid VOUT_MODE value"};
            }
            catch (...)
            {
                inner = std::current_exception();
                std::throw_with_nested(PMBusError{
                    "VOUT_MODE contains unsupported data format", "reg1",
                    "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
                    "reg1"});
            }
        }
        catch (...)
        {
            outer = std::current_exception();
        }

        std::exception_ptr exceptionToLog =
            error_logging_utils::internal::getExceptionToLog(outer);
        EXPECT_EQ(outer, exceptionToLog);
    }

    // Test where exception is nested: Highest priority is
    // WriteVerificationError
    {
        std::exception_ptr inner, outer;
        try
        {
            try
            {
                throw WriteVerificationError{
                    "value_written: 0xDEAD, value_read: 0xBEEF", "reg1",
                    "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
                    "reg1"};
            }
            catch (...)
            {
                inner = std::current_exception();
                std::throw_with_nested(
                    std::runtime_error{"Unable set voltage"});
            }
        }
        catch (...)
        {
            outer = std::current_exception();
        }

        std::exception_ptr exceptionToLog =
            error_logging_utils::internal::getExceptionToLog(outer);
        EXPECT_EQ(inner, exceptionToLog);
    }

    // Test where exception is nested: Highest priority is I2CException
    {
        std::exception_ptr inner, outer;
        try
        {
            try
            {
                throw std::invalid_argument{"No such device"};
            }
            catch (...)
            {
                inner = std::current_exception();
                std::throw_with_nested(i2c::I2CException{
                    "Unable to open device reg1", "/dev/i2c-8", 0x30, ENODEV});
            }
        }
        catch (...)
        {
            outer = std::current_exception();
        }

        std::exception_ptr exceptionToLog =
            error_logging_utils::internal::getExceptionToLog(outer);
        EXPECT_EQ(outer, exceptionToLog);
    }

    // Test where exception is nested: Highest priority is
    // sdbusplus::exception_t
    {
        std::exception_ptr inner, outer;
        try
        {
            try
            {
                // Throw TestSDBusError; exception_t is pure virtual class
                throw TestSDBusError{"DBusError: Invalid object path."};
            }
            catch (...)
            {
                inner = std::current_exception();
                std::throw_with_nested(
                    std::runtime_error{"Unable to call D-Bus method"});
            }
        }
        catch (...)
        {
            outer = std::current_exception();
        }

        std::exception_ptr exceptionToLog =
            error_logging_utils::internal::getExceptionToLog(outer);
        EXPECT_EQ(inner, exceptionToLog);
    }

    // Test where exception is nested: Highest priority is std::exception
    {
        std::exception_ptr inner, outer;
        try
        {
            try
            {
                throw std::invalid_argument{"No such file or directory"};
            }
            catch (...)
            {
                inner = std::current_exception();
                std::throw_with_nested(
                    std::runtime_error{"Unable load config file"});
            }
        }
        catch (...)
        {
            outer = std::current_exception();
        }

        std::exception_ptr exceptionToLog =
            error_logging_utils::internal::getExceptionToLog(outer);
        EXPECT_EQ(outer, exceptionToLog);
    }

    // Test where exception is nested: Highest priority is unknown type
    {
        std::exception_ptr inner, outer;
        try
        {
            try
            {
                throw 23;
            }
            catch (...)
            {
                inner = std::current_exception();
                std::throw_with_nested(std::string{"Unable load config file"});
            }
        }
        catch (...)
        {
            outer = std::current_exception();
        }

        std::exception_ptr exceptionToLog =
            error_logging_utils::internal::getExceptionToLog(outer);
        EXPECT_EQ(outer, exceptionToLog);
    }
}
