/**
 * 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.hpp"
#include "chassis.hpp"
#include "compare_presence_action.hpp"
#include "device.hpp"
#include "i2c_interface.hpp"
#include "mock_action.hpp"
#include "mock_error_logging.hpp"
#include "mock_journal.hpp"
#include "mock_presence_service.hpp"
#include "mock_services.hpp"
#include "mocked_i2c_interface.hpp"
#include "presence_detection.hpp"
#include "rule.hpp"
#include "system.hpp"

#include <sdbusplus/exception.hpp>

#include <memory>
#include <stdexcept>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

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

using namespace phosphor::power::regulators;

using ::testing::Ref;
using ::testing::Return;
using ::testing::Throw;

/**
 * Concrete subclass of sdbusplus::exception_t abstract base class.
 */
class TestSDBusError : public sdbusplus::exception_t
{
  public:
    TestSDBusError(const std::string& error) : error{error}
    {
    }

    const char* what() const noexcept override
    {
        return error.c_str();
    }

    const char* name() const noexcept override
    {
        return "";
    }

    const char* description() const noexcept override
    {
        return "";
    }

  private:
    const std::string error{};
};

/**
 * Creates the parent objects that normally contain a PresenceDetection object.
 *
 * A PresenceDetection object is normally contained within a hierarchy of
 * System, Chassis, and Device objects.  These objects are required in order to
 * call the execute() method.
 *
 * Creates the System, Chassis, and Device objects.  The PresenceDetection
 * object is moved into the Device object.
 *
 * @param detection PresenceDetection object to move into object hierarchy
 * @return Pointers to the System, Chassis, and Device objects.  The Chassis and
 *         Device objects are contained within the System object and will be
 *         automatically destructed.
 */
std::tuple<std::unique_ptr<System>, Chassis*, Device*>
    createParentObjects(std::unique_ptr<PresenceDetection> detection)
{
    // Create mock I2CInterface
    std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
        std::make_unique<i2c::MockedI2CInterface>();

    // Create Device that contains PresenceDetection
    std::unique_ptr<Device> device = std::make_unique<Device>(
        "vdd_reg", true,
        "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
        std::move(i2cInterface), std::move(detection));
    Device* devicePtr = device.get();

    // Create Chassis that contains Device
    std::vector<std::unique_ptr<Device>> devices{};
    devices.emplace_back(std::move(device));
    std::unique_ptr<Chassis> chassis =
        std::make_unique<Chassis>(1, std::move(devices));
    Chassis* chassisPtr = chassis.get();

    // Create System that contains Chassis
    std::vector<std::unique_ptr<Rule>> rules{};
    std::vector<std::unique_ptr<Chassis>> chassisVec{};
    chassisVec.emplace_back(std::move(chassis));
    std::unique_ptr<System> system =
        std::make_unique<System>(std::move(rules), std::move(chassisVec));

    return std::make_tuple(std::move(system), chassisPtr, devicePtr);
}

TEST(PresenceDetectionTests, Constructor)
{
    std::vector<std::unique_ptr<Action>> actions{};
    actions.emplace_back(std::make_unique<MockAction>());

    PresenceDetection detection{std::move(actions)};
    EXPECT_EQ(detection.getActions().size(), 1);
    EXPECT_FALSE(detection.getCachedPresence().has_value());
}

TEST(PresenceDetectionTests, ClearCache)
{
    // Create MockAction that will return true once
    std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
    EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));

    // Create PresenceDetection
    std::vector<std::unique_ptr<Action>> actions{};
    actions.emplace_back(std::move(action));
    PresenceDetection* detection = new PresenceDetection(std::move(actions));

    // Create parent System, Chassis, and Device objects
    auto [system, chassis, device] =
        createParentObjects(std::unique_ptr<PresenceDetection>{detection});

    // Verify that initially no presence value is cached
    EXPECT_FALSE(detection->getCachedPresence().has_value());

    // Call execute() which should obtain and cache presence value
    MockServices services{};
    EXPECT_TRUE(detection->execute(services, *system, *chassis, *device));

    // Verify true presence value was cached
    EXPECT_TRUE(detection->getCachedPresence().has_value());
    EXPECT_TRUE(detection->getCachedPresence().value());

    // Clear cached presence value
    detection->clearCache();

    // Verify that no presence value is cached
    EXPECT_FALSE(detection->getCachedPresence().has_value());
}

TEST(PresenceDetectionTests, Execute)
{
    // Create ComparePresenceAction
    std::unique_ptr<ComparePresenceAction> action =
        std::make_unique<ComparePresenceAction>(
            "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2",
            true);

    // Create PresenceDetection
    std::vector<std::unique_ptr<Action>> actions{};
    actions.emplace_back(std::move(action));
    PresenceDetection* detection = new PresenceDetection(std::move(actions));

    // Create parent System, Chassis, and Device objects
    auto [system, chassis, device] =
        createParentObjects(std::unique_ptr<PresenceDetection>{detection});

    // Test where works: Present: Value is not cached
    {
        EXPECT_FALSE(detection->getCachedPresence().has_value());

        // Create MockServices.  MockPresenceService::isPresent() should return
        // true.
        MockServices services{};
        MockPresenceService& presenceService =
            services.getMockPresenceService();
        EXPECT_CALL(presenceService,
                    isPresent("/xyz/openbmc_project/inventory/system/chassis/"
                              "motherboard/cpu2"))
            .Times(1)
            .WillOnce(Return(true));

        // Execute PresenceDetection
        EXPECT_TRUE(detection->execute(services, *system, *chassis, *device));

        EXPECT_TRUE(detection->getCachedPresence().has_value());
        EXPECT_TRUE(detection->getCachedPresence().value());
    }

    // Test where works: Present: Value is cached
    {
        EXPECT_TRUE(detection->getCachedPresence().has_value());

        // Create MockServices.  MockPresenceService::isPresent() should not be
        // called.
        MockServices services{};
        MockPresenceService& presenceService =
            services.getMockPresenceService();
        EXPECT_CALL(presenceService, isPresent).Times(0);

        // Execute PresenceDetection
        EXPECT_TRUE(detection->execute(services, *system, *chassis, *device));
    }

    // Test where works: Not present: Value is not cached
    {
        // Clear cached presence value
        detection->clearCache();
        EXPECT_FALSE(detection->getCachedPresence().has_value());

        // Create MockServices.  MockPresenceService::isPresent() should return
        // false.
        MockServices services{};
        MockPresenceService& presenceService =
            services.getMockPresenceService();
        EXPECT_CALL(presenceService,
                    isPresent("/xyz/openbmc_project/inventory/system/chassis/"
                              "motherboard/cpu2"))
            .Times(1)
            .WillOnce(Return(false));

        // Execute PresenceDetection
        EXPECT_FALSE(detection->execute(services, *system, *chassis, *device));

        EXPECT_TRUE(detection->getCachedPresence().has_value());
        EXPECT_FALSE(detection->getCachedPresence().value());
    }

    // Test where works: Not present: Value is cached
    {
        EXPECT_TRUE(detection->getCachedPresence().has_value());

        // Create MockServices.  MockPresenceService::isPresent() should not be
        // called.
        MockServices services{};
        MockPresenceService& presenceService =
            services.getMockPresenceService();
        EXPECT_CALL(presenceService, isPresent).Times(0);

        // Execute PresenceDetection
        EXPECT_FALSE(detection->execute(services, *system, *chassis, *device));
    }

    // Test where fails
    {
        // Clear cached presence value
        detection->clearCache();
        EXPECT_FALSE(detection->getCachedPresence().has_value());

        // Create MockServices.  MockPresenceService::isPresent() should throw
        // an exception.
        MockServices services{};
        MockPresenceService& presenceService =
            services.getMockPresenceService();
        EXPECT_CALL(presenceService,
                    isPresent("/xyz/openbmc_project/inventory/system/chassis/"
                              "motherboard/cpu2"))
            .Times(1)
            .WillOnce(Throw(TestSDBusError{"DBusError: Invalid object path."}));

        // Define expected journal messages that should be passed to MockJournal
        MockJournal& journal = services.getMockJournal();
        std::vector<std::string> exceptionMessages{
            "DBusError: Invalid object path.",
            "ActionError: compare_presence: { fru: "
            "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2, "
            "value: true }"};
        EXPECT_CALL(journal, logError(exceptionMessages)).Times(1);
        EXPECT_CALL(journal,
                    logError("Unable to determine presence of vdd_reg"))
            .Times(1);

        // Expect logDBusError() to be called
        MockErrorLogging& errorLogging = services.getMockErrorLogging();
        EXPECT_CALL(errorLogging,
                    logDBusError(Entry::Level::Warning, Ref(journal)))
            .Times(1);

        // Execute PresenceDetection.  Should return true when an error occurs.
        EXPECT_TRUE(detection->execute(services, *system, *chassis, *device));

        EXPECT_TRUE(detection->getCachedPresence().has_value());
        EXPECT_TRUE(detection->getCachedPresence().value());
    }
}

TEST(PresenceDetectionTests, GetActions)
{
    std::vector<std::unique_ptr<Action>> actions{};

    MockAction* action1 = new MockAction{};
    actions.emplace_back(std::unique_ptr<MockAction>{action1});

    MockAction* action2 = new MockAction{};
    actions.emplace_back(std::unique_ptr<MockAction>{action2});

    PresenceDetection detection{std::move(actions)};
    EXPECT_EQ(detection.getActions().size(), 2);
    EXPECT_EQ(detection.getActions()[0].get(), action1);
    EXPECT_EQ(detection.getActions()[1].get(), action2);
}

TEST(PresenceDetectionTests, GetCachedPresence)
{
    // Create MockAction that will return false once
    std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
    EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));

    // Create PresenceDetection
    std::vector<std::unique_ptr<Action>> actions{};
    actions.emplace_back(std::move(action));
    PresenceDetection* detection = new PresenceDetection(std::move(actions));

    // Create parent System, Chassis, and Device objects
    auto [system, chassis, device] =
        createParentObjects(std::unique_ptr<PresenceDetection>{detection});

    // Verify that initially no presence value is cached
    EXPECT_FALSE(detection->getCachedPresence().has_value());

    // Call execute() which should obtain and cache presence value
    MockServices services{};
    EXPECT_FALSE(detection->execute(services, *system, *chassis, *device));

    // Verify false presence value was cached
    EXPECT_TRUE(detection->getCachedPresence().has_value());
    EXPECT_FALSE(detection->getCachedPresence().value());

    // Clear cached presence value
    detection->clearCache();

    // Verify that no presence value is cached
    EXPECT_FALSE(detection->getCachedPresence().has_value());
}
