/**
 * 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_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 <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::Return;
using ::testing::Throw;

/**
 * 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(std::runtime_error{"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);

        // 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());
}
