/**
 * 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 "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 InvalidEnumString; exception_t is a pure virtual base class
            throw sdbusplus::exception::InvalidEnumString{};
        }
        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 InvalidEnumString; exception_t is pure virtual class
                throw sdbusplus::exception::InvalidEnumString{};
            }
            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);
    }
}
