#include "NVMeMiFake.hpp"
#include "NVMeSubsys.hpp"

#include <dlfcn.h>
#include <valgrind/valgrind.h>

#include <nlohmann/json.hpp>
#include <sdbusplus/asio/connection.hpp>

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

#define xstr(s) str(s) // NOLINT
#define str(s) #s      // NOLINT

std::unordered_map<std::string, void*> pluginLibMap = {};
class NVMeMiMock :
    public NVMeMiIntf,
    public std::enable_shared_from_this<NVMeMiMock>
{
  public:
    NVMeMiMock(boost::asio::io_context& io, std::chrono::milliseconds delay) :
        fake(std::make_shared<NVMeMiFake>(io, delay))
    {
        ON_CALL(*this, getNID).WillByDefault([]() { return 0; });
        ON_CALL(*this, getEID).WillByDefault([]() { return 0; });
        ON_CALL(*this, miSubsystemHealthStatusPoll)
            .WillByDefault(
                [this](
                    std::function<void(const std::error_code&,
                                       nvme_mi_nvm_ss_health_status*)>&& cb) {
            return fake->miSubsystemHealthStatusPoll(std::move(cb));
        });
        ON_CALL(*this, miScanCtrl)
            .WillByDefault(
                [this](
                    std::function<void(const std::error_code& ec,
                                       const std::vector<nvme_mi_ctrl_t>& list)>
                        cb) { return fake->miScanCtrl(std::move(cb)); });
        ON_CALL(*this, flushOperations)
            .WillByDefault([this](std::function<void()>&& cb) {
            return fake->flushOperations(std::move(cb));
        });
        ON_CALL(*this, adminIdentify)
            .WillByDefault(
                [this](
                    nvme_mi_ctrl_t ctrl, nvme_identify_cns cns, uint32_t nsid,
                    uint16_t cntid,
                    std::function<void(nvme_ex_ptr, std::span<uint8_t>)>&& cb) {
            return fake->adminIdentify(ctrl, cns, nsid, cntid, std::move(cb));
        });
        ON_CALL(*this, adminGetLogPage)
            .WillByDefault(
                [this](nvme_mi_ctrl_t ctrl, nvme_cmd_get_log_lid lid,
                       uint32_t nsid, uint8_t lsp, uint16_t lsi,
                       std::function<void(const std::error_code&,
                                          std::span<uint8_t>)>&& cb) {
            return fake->adminGetLogPage(ctrl, lid, nsid, lsp, lsi,
                                         std::move(cb));
        });
        ON_CALL(*this, adminFwCommit)
            .WillByDefault([this](nvme_mi_ctrl_t ctrl, nvme_fw_commit_ca action,
                                  uint8_t slot, bool bpid,
                                  std::function<void(const std::error_code&,
                                                     nvme_status_field)>&& cb) {
            return fake->adminFwCommit(ctrl, action, slot, bpid, std::move(cb));
        });
        ON_CALL(*this, adminXfer)
            .WillByDefault(
                [this](
                    nvme_mi_ctrl_t ctrl, const nvme_mi_admin_req_hdr& adminReq,
                    std::span<uint8_t> data, unsigned int timeoutMs,
                    std::function<void(const std::error_code& ec,
                                       const nvme_mi_admin_resp_hdr& adminResp,
                                       std::span<uint8_t> respData)>&& cb) {
            return fake->adminXfer(ctrl, adminReq, data, timeoutMs,
                                   std::move(cb));
        });
        ON_CALL(*this, adminSecuritySend).WillByDefault([]() { return; });
        ON_CALL(*this, adminSecurityReceive).WillByDefault([]() { return; });
        ON_CALL(*this, adminListNamespaces)
            .WillByDefault(
                [this](nvme_mi_ctrl_t ctrl,
                       std::function<void(nvme_ex_ptr ex,
                                          std::vector<uint32_t> ns)>&& cb) {
            // return empty NS list
            return fake->adminListNamespaces(ctrl, std::move(cb));
        });
    }

    MOCK_METHOD(void, start, (const std::shared_ptr<MctpEndpoint>&),
                (override));
    MOCK_METHOD(void, stop, (), (override));
    MOCK_METHOD(void, recover, (), (override));
    MOCK_METHOD(int, getNID, (), (const override));
    MOCK_METHOD(int, getEID, (), (const override));
    MOCK_METHOD(void, miSubsystemHealthStatusPoll,
                (std::function<void(const std::error_code&,
                                    nvme_mi_nvm_ss_health_status*)>&&),
                (override));
    MOCK_METHOD(void, miScanCtrl,
                (std::function<void(const std::error_code&,
                                    const std::vector<nvme_mi_ctrl_t>&)>),
                (override));
    MOCK_METHOD(bool, flushOperations, (std::function<void()>&&));
    MOCK_METHOD(void, adminIdentify,
                (nvme_mi_ctrl_t ctrl, nvme_identify_cns cns, uint32_t nsid,
                 uint16_t cntid,
                 std::function<void(nvme_ex_ptr, std::span<uint8_t>)>&& cb),
                (override));
    MOCK_METHOD(void, adminGetFeatures,
                (nvme_mi_ctrl_t ctrl, const GetFeaturesRequest& req,
                 std::function<void(nvme_ex_ptr, uint32_t response,
                                    std::span<uint8_t>)>&& cb),
                (override));
    MOCK_METHOD(void, adminSetFeatures,
                (nvme_mi_ctrl_t ctrl, const SetFeaturesRequest& req,
                 std::function<void(nvme_ex_ptr, uint32_t response)>&& cb),
                (override));
    MOCK_METHOD(
        void, adminGetLogPage,
        (nvme_mi_ctrl_t ctrl, nvme_cmd_get_log_lid lid, uint32_t nsid,
         uint8_t lsp, uint16_t lsi,
         std::function<void(const std::error_code&, std::span<uint8_t>)>&& cb),
        (override));
    MOCK_METHOD(
        void, adminFwCommit,
        (nvme_mi_ctrl_t ctrl, nvme_fw_commit_ca action, uint8_t slot, bool bpid,
         std::function<void(const std::error_code&, nvme_status_field)>&& cb),
        (override));
    MOCK_METHOD(void, adminXfer,
                (nvme_mi_ctrl_t ctrl, const nvme_mi_admin_req_hdr& adminReq,
                 std::span<uint8_t> data, unsigned int timeoutMs,
                 std::function<void(const std::error_code& ec,
                                    const nvme_mi_admin_resp_hdr& adminResp,
                                    std::span<uint8_t> respData)>&& cb),
                (override));
    MOCK_METHOD(
        void, adminLockdownInband,
        (nvme_mi_ctrl_t ctrl, uint8_t prohibit,
         const std::vector<uint8_t>& adminCmds,
         const std::vector<uint8_t>& features,
         const std::vector<uint8_t>& logPages,
         std::function<
             void(const std::error_code&, int nvmeStatus, uint32_t comptionDw0,
                  const std::string& failureScope, uint32_t failureId)>&& cb),
        (override));
    MOCK_METHOD(
        void, adminSecuritySend,
        (nvme_mi_ctrl_t ctrl, uint8_t proto, uint16_t protoSpecific,
         std::span<uint8_t> data,
         std::function<void(const std::error_code&, int nvmeStatus)>&& cb),
        (override));
    MOCK_METHOD(void, adminSecurityReceive,
                (nvme_mi_ctrl_t ctrl, uint8_t proto, uint16_t protoSpecific,
                 uint32_t transferLength,
                 std::function<void(const std::error_code&, int nvmeStatus,
                                    const std::span<uint8_t> data)>&& cb),
                (override));

    MOCK_METHOD(
        void, adminFwDownload,
        (nvme_mi_ctrl_t ctrl, std::string firmwarefile,
         std::function<void(const std::error_code&, nvme_status_field)>&& cb),
        (override));

    MOCK_METHOD(void, adminNonDataCmd,
                (nvme_mi_ctrl_t ctrl, uint8_t opcode, uint32_t cdw1,
                 uint32_t cdw2, uint32_t cdw3, uint32_t cdw10, uint32_t cdw11,
                 uint32_t cdw12, uint32_t cdw13, uint32_t cdw14, uint32_t cdw15,
                 std::function<void(const std::error_code&, int nvmeStatus,
                                    uint32_t comptionDw0)>&& cb),
                (override));
    MOCK_METHOD(void, createNamespace,
                (nvme_mi_ctrl_t ctrl, uint64_t size, size_t lbaFormat,
                 bool metadataAtEnd,
                 std::function<void(nvme_ex_ptr ex)>&& submittedCB,
                 std::function<void(nvme_ex_ptr ex, NVMeNSIdentify newid)>&&
                     finishedCB),
                (override));

    MOCK_METHOD(
        void, adminDeleteNamespace,
        (nvme_mi_ctrl_t ctrl, uint32_t nsid,
         std::function<void(const std::error_code&, int nvmeStatus)>&& cb),
        (override));

    MOCK_METHOD(
        void, adminAttachDetachNamespace,
        (nvme_mi_ctrl_t ctrl, uint16_t ctrlid, uint32_t nsid, bool attach,
         std::function<void(const std::error_code&, int nvmeStatus)>&& cb),
        (override));

    MOCK_METHOD(
        void, adminListNamespaces,
        (nvme_mi_ctrl_t ctrl,
         std::function<void(nvme_ex_ptr ex, std::vector<uint32_t> ns)>&& cb),
        (override));

    MOCK_METHOD(void, adminSanitize,
                (nvme_mi_ctrl_t ctrl, enum nvme_sanitize_sanact sanact,
                 uint8_t passes, uint32_t pattern, bool invertPattern,
                 std::function<void(nvme_ex_ptr ex)>&& cb),
                (override));

    std::shared_ptr<NVMeMiFake> fake;
};

class NVMeTest : public ::testing::Test
{
  protected:
    NVMeTest() :
        systemBus(std::make_shared<sdbusplus::asio::connection>(io)),
        object_server(systemBus),
        nvme_intf(NVMeIntf::create<::testing::NiceMock<NVMeMiMock>>(
            io, subsysPollTime / 10)),
        mock(*std::dynamic_pointer_cast<NVMeMiMock>(
            std::get<std::shared_ptr<NVMeMiIntf>>(nvme_intf.getInferface()))),
        subsys(std::make_shared<NVMeSubsystem>(io, object_server, systemBus,
                                               subsysPath, "NVMe_1",
                                               SensorData{}, nvme_intf, false))
    {
        systemBus->request_name("xyz.openbmc_project.NVMeTest");
        subsys->unavailableMaxCount = 1;
        subsys->pollingInterval = subsysPollTime;

        ON_CALL(mock, adminGetFeatures)
            .WillByDefault([](nvme_mi_ctrl_t,
                              const NVMeMiIntf::GetFeaturesRequest&,
                              std::function<void(nvme_ex_ptr, uint32_t,
                                                 std::span<uint8_t>)>&& cb) {
            cb(nullptr, 0, {});
        });
    }

    static void SetUpTestSuite()
    {
        // Load plugin shared libraries
        try
        {
            for (const auto& entry :
                 std::filesystem::directory_iterator(xstr(BUILDDIR)))
            {
                void* lib = dlopen(entry.path().c_str(), RTLD_NOW);
                if (lib != nullptr)
                {
                    pluginLibMap.emplace(entry.path().filename().string(), lib);
                }
                else
                {
                    std::cerr << "could not load the plugin: " << dlerror()
                              << '\n';
                }
            }
        }
        catch (const std::filesystem::filesystem_error& e)
        {
            std::cerr << "failed to open plugin folder: " << e.what() << '\n';
        }
    }

    void SetUp() override
    {
        subsys->init();
        subsys->start();
    }

    void TearDown() override
    {
        if (subsys)
        {
            subsys->stop();
        }
        io.poll();
        io.restart();
    }

    static constexpr char subsysPath[] = // NOLINT
        "/xyz/openbmc_project/inventory/Test_Chassis/Test_NVMe";

    boost::asio::io_context io;
    std::shared_ptr<sdbusplus::asio::connection> systemBus;
    sdbusplus::asio::object_server object_server;

    NVMeIntf nvme_intf;
    NVMeMiMock& mock;
    std::shared_ptr<NVMeSubsystem> subsys;

    const static std::chrono::milliseconds subsysPollTime;
};

const std::chrono::milliseconds NVMeTest::subsysPollTime = []() {
    return (RUNNING_ON_VALGRIND != 0U) ? std::chrono::milliseconds(1000)
                                       : std::chrono::milliseconds(100);
}();

/**
 * @brief Test start and stop function of NVMeSubsystem
 *
 */
TEST_F(NVMeTest, TestSubsystemStartStop)
{
    using ::testing::AtLeast;
    boost::asio::steady_timer timer(io);

    EXPECT_CALL(mock, miSubsystemHealthStatusPoll).Times(AtLeast(1));
    EXPECT_CALL(mock, adminIdentify).Times(AtLeast(1));
    EXPECT_CALL(mock, miScanCtrl).Times(AtLeast(1));

    // wait for subsystem initialization
    timer.expires_after(subsysPollTime * 2);
    timer.async_wait([&](boost::system::error_code) {
        systemBus->async_method_call(
            [&, this](boost::system::error_code, const GetSubTreeType& result) {
            // Only PF and the enabled VF should be listed
            EXPECT_EQ(result.size(), 2);
            subsys->stop();

            // wait for storage controller destruction.
            timer.expires_after(subsysPollTime * 1);
            timer.async_wait([&](boost::system::error_code) {
                systemBus->async_method_call(
                    [&](boost::system::error_code,
                        const GetSubTreeType& result) {
                    // not storage controller should be listed.
                    nlohmann::json j(result);
                    EXPECT_EQ(result.size(), 0)
                        << "The following interfaces remain after STOP: \n"
                        << j.dump(2) << '\n';
                    // restart the subsystem
                    subsys->start();
                    timer.expires_after(subsysPollTime * 2);
                    timer.async_wait([&](boost::system::error_code) {
                        systemBus->async_method_call(
                            [&](boost::system::error_code,
                                const GetSubTreeType& result) {
                            EXPECT_EQ(result.size(), 2);

                            subsys->stop();
                            // subsys.reset();

                            // wait for storage controller destruction.
                            timer.expires_after(subsysPollTime * 1);
                            timer.async_wait([&](boost::system::error_code) {
                                systemBus->async_method_call(
                                    [&](boost::system::error_code,
                                        const GetSubTreeType& result) {
                                    // not storage controller should be listed.
                                    nlohmann::json j(result);
                                    EXPECT_EQ(result.size(), 0)
                                        << "The following interfaces remain after STOP: \n"
                                        << j.dump(2) << '\n';
                                    io.stop();
                                },
                                    "xyz.openbmc_project.ObjectMapper",
                                    "/xyz/openbmc_project/object_mapper",
                                    "xyz.openbmc_project.ObjectMapper",
                                    "GetSubTree", subsysPath, 0,
                                    std::vector<std::string>{
                                        "xyz.openbmc_project.Inventory."
                                        "Item.StorageController"});
                            });
                        },
                            "xyz.openbmc_project.ObjectMapper",
                            "/xyz/openbmc_project/object_mapper",
                            "xyz.openbmc_project.ObjectMapper", "GetSubTree",
                            subsysPath, 0,
                            std::vector<std::string>{
                                "xyz.openbmc_project.Inventory.Item.StorageController"});
                    });
                },
                    "xyz.openbmc_project.ObjectMapper",
                    "/xyz/openbmc_project/object_mapper",
                    "xyz.openbmc_project.ObjectMapper", "GetSubTree",
                    subsysPath, 0,
                    std::vector<std::string>{"xyz.openbmc_project.Inventory."
                                             "Item.StorageController"});
            });
        }, "xyz.openbmc_project.ObjectMapper",
            "/xyz/openbmc_project/object_mapper",
            "xyz.openbmc_project.ObjectMapper", "GetSubTree", subsysPath, 0,
            std::vector<std::string>{
                "xyz.openbmc_project.Inventory.Item.StorageController"});
    });
    io.run();
}

/**
 * @brief Test NVMeMi return DriveFunctional(NSHDS.NSS.DF) = 0
 *
 */
TEST_F(NVMeTest, TestDriveFunctional)
{
    using ::testing::AtLeast;
    boost::asio::steady_timer timer(io);

    EXPECT_CALL(mock, miSubsystemHealthStatusPoll).Times(AtLeast(1));
    EXPECT_CALL(mock, adminIdentify).Times(AtLeast(1));
    EXPECT_CALL(mock, miScanCtrl).Times(AtLeast(1));

    // wait for subsystem initialization
    timer.expires_after(subsysPollTime * 2);
    timer.async_wait([&](boost::system::error_code) {
        systemBus->async_method_call(
            [&](boost::system::error_code, const GetSubTreeType& result) {
            // Only PF and the enabled VF should be listed
            EXPECT_EQ(result.size(), 2);

            // mimik communication error of NVMeMI request
            ON_CALL(mock, miSubsystemHealthStatusPoll)
                .WillByDefault(
                    [&](std::function<void(const std::error_code&,
                                           nvme_mi_nvm_ss_health_status*)>&&
                            cb) {
                std::cerr << "mock device not functional health poll" << '\n';
                // return status.nss.df = 0
                return boost::asio::post(io, [cb = std::move(cb)]() {
                    nvme_mi_nvm_ss_health_status status{};
                    status.nss = 0;
                    cb({}, &status);
                });
            });

            // wait for storage controller destruction.
            timer.expires_after(subsysPollTime * 2);
            timer.async_wait([&](boost::system::error_code) {
                systemBus->async_method_call(
                    [&](boost::system::error_code,
                        const GetSubTreeType& result) {
                    // no storage controller should be listed.
                    nlohmann::json j(result);
                    EXPECT_EQ(result.size(), 0)
                        << "The following interfaces remain after unfunctional: \n"
                        << j.dump(2) << '\n';

                    // restart sending DF = 1
                    ON_CALL(mock, miSubsystemHealthStatusPoll)
                        .WillByDefault(
                            [&](std::function<void(
                                    const std::error_code&,
                                    nvme_mi_nvm_ss_health_status*)>&& cb) {
                        return mock.fake->miSubsystemHealthStatusPoll(
                            std::move(cb));
                    });
                    timer.expires_after(subsysPollTime * 2);
                    timer.async_wait([&](boost::system::error_code) {
                        systemBus->async_method_call(
                            [&](boost::system::error_code,
                                const GetSubTreeType& result) {
                            // storage controller should be restored.
                            EXPECT_EQ(result.size(), 2);

                            subsys->stop();
                            // subsys.reset();

                            // wait for storage controller destruction.
                            timer.expires_after(subsysPollTime * 1);
                            timer.async_wait([&](boost::system::error_code) {
                                systemBus->async_method_call(
                                    [&](boost::system::error_code,
                                        const GetSubTreeType& result) {
                                    // not storage controller should be listed.
                                    nlohmann::json j(result);
                                    EXPECT_EQ(result.size(), 0)
                                        << "The following interfaces remain after STOP: \n"
                                        << j.dump(2) << '\n';
                                    io.stop();
                                },
                                    "xyz.openbmc_project.ObjectMapper",
                                    "/xyz/openbmc_project/object_mapper",
                                    "xyz.openbmc_project.ObjectMapper",
                                    "GetSubTree", subsysPath, 0,
                                    std::vector<std::string>{
                                        "xyz.openbmc_project.Inventory."
                                        "Item.StorageController"});
                            });
                        },
                            "xyz.openbmc_project.ObjectMapper",
                            "/xyz/openbmc_project/object_mapper",
                            "xyz.openbmc_project.ObjectMapper", "GetSubTree",
                            subsysPath, 0,
                            std::vector<std::string>{
                                "xyz.openbmc_project.Inventory."
                                "Item.StorageController"});
                    });
                },
                    "xyz.openbmc_project.ObjectMapper",
                    "/xyz/openbmc_project/object_mapper",
                    "xyz.openbmc_project.ObjectMapper", "GetSubTree",
                    subsysPath, 0,
                    std::vector<std::string>{"xyz.openbmc_project.Inventory."
                                             "Item.StorageController"});
            });
        }, "xyz.openbmc_project.ObjectMapper",
            "/xyz/openbmc_project/object_mapper",
            "xyz.openbmc_project.ObjectMapper", "GetSubTree", subsysPath, 0,
            std::vector<std::string>{
                "xyz.openbmc_project.Inventory.Item.StorageController"});
    });
    io.run();
}

/**
 * @brief Test NVMeMi returns Drive is absent (ec = no_such_device)
 *
 */
TEST_F(NVMeTest, TestDriveAbsent)
{
    using ::testing::AtLeast;
    boost::asio::steady_timer timer(io);

    EXPECT_CALL(mock, miSubsystemHealthStatusPoll).Times(AtLeast(1));
    EXPECT_CALL(mock, adminIdentify).Times(AtLeast(1));
    EXPECT_CALL(mock, miScanCtrl).Times(AtLeast(1));

    // wait for subsystem initialization
    timer.expires_after(subsysPollTime * 2);
    timer.async_wait([&](boost::system::error_code) {
        systemBus->async_method_call(
            [&](boost::system::error_code, const GetSubTreeType& result) {
            // Only PF and the enabled VF should be listed
            EXPECT_EQ(result.size(), 2);

            // mimik communication error of NVMeMI request
            ON_CALL(mock, miSubsystemHealthStatusPoll)
                .WillByDefault(
                    [&](std::function<void(const std::error_code&,
                                           nvme_mi_nvm_ss_health_status*)>&&
                            cb) {
                std::cerr << "mock device absent health poll" << '\n';
                // return no_such_device
                return boost::asio::post(io, [cb = std::move(cb)]() {
                    cb(std::make_error_code(std::errc::no_such_device),
                       nullptr);
                });
            });

            // wait for storage controller destruction.
            timer.expires_after(subsysPollTime * 2);
            timer.async_wait([&](boost::system::error_code) {
                systemBus->async_method_call(
                    [&](boost::system::error_code,
                        const GetSubTreeType& result) {
                    // no storage controller should be listed.
                    nlohmann::json j(result);
                    EXPECT_EQ(result.size(), 0)
                        << "The following interfaces remain after absent: \n"
                        << j.dump(2) << '\n';

                    // restart sending normal polling result
                    ON_CALL(mock, miSubsystemHealthStatusPoll)
                        .WillByDefault(
                            [&](std::function<void(
                                    const std::error_code&,
                                    nvme_mi_nvm_ss_health_status*)>&& cb) {
                        return mock.fake->miSubsystemHealthStatusPoll(
                            std::move(cb));
                    });
                    timer.expires_after(subsysPollTime * 2);
                    timer.async_wait([&](boost::system::error_code) {
                        systemBus->async_method_call(
                            [&](boost::system::error_code,
                                const GetSubTreeType& result) {
                            // storage controller should be restored.
                            EXPECT_EQ(result.size(), 2);

                            subsys->stop();

                            // wait for storage controller destruction.
                            timer.expires_after(subsysPollTime * 1);
                            timer.async_wait([&](boost::system::error_code) {
                                systemBus->async_method_call(
                                    [&](boost::system::error_code,
                                        const GetSubTreeType& result) {
                                    // not storage controller should be listed.
                                    nlohmann::json j(result);
                                    EXPECT_EQ(result.size(), 0)
                                        << "The following interfaces remain after STOP: \n"
                                        << j.dump(2) << '\n';
                                    io.stop();
                                },
                                    "xyz.openbmc_project.ObjectMapper",
                                    "/xyz/openbmc_project/object_mapper",
                                    "xyz.openbmc_project.ObjectMapper",
                                    "GetSubTree", subsysPath, 0,
                                    std::vector<std::string>{
                                        "xyz.openbmc_project.Inventory."
                                        "Item.StorageController"});
                            });
                        },
                            "xyz.openbmc_project.ObjectMapper",
                            "/xyz/openbmc_project/object_mapper",
                            "xyz.openbmc_project.ObjectMapper", "GetSubTree",
                            subsysPath, 0,
                            std::vector<std::string>{
                                "xyz.openbmc_project.Inventory."
                                "Item.StorageController"});
                    });
                },
                    "xyz.openbmc_project.ObjectMapper",
                    "/xyz/openbmc_project/object_mapper",
                    "xyz.openbmc_project.ObjectMapper", "GetSubTree",
                    subsysPath, 0,
                    std::vector<std::string>{"xyz.openbmc_project.Inventory."
                                             "Item.StorageController"});
            });
        }, "xyz.openbmc_project.ObjectMapper",
            "/xyz/openbmc_project/object_mapper",
            "xyz.openbmc_project.ObjectMapper", "GetSubTree", subsysPath, 0,
            std::vector<std::string>{
                "xyz.openbmc_project.Inventory.Item.StorageController"});
    });
    io.run();
}

/**
 * @brief Inject error during subsystem initialization process. The subsystem is
 * expected to recover after the error
 */
TEST_F(NVMeTest, InitErrorInjection)
{
    using ::testing::_;
    using ::testing::AnyNumber;
    using ::testing::AtLeast;
    using ::testing::Eq;
    boost::asio::steady_timer timer(io);

    EXPECT_CALL(mock, miSubsystemHealthStatusPoll).Times(AtLeast(1));
    EXPECT_CALL(mock, miScanCtrl)
        .WillOnce(
            [](const std::function<void(const std::error_code&,
                                        const std::vector<nvme_mi_ctrl_t>&)>&
                   cb) {
        cb(std::make_error_code(std::errc::no_such_device), {});
    }).WillRepeatedly([&](auto&& cb) {
        return mock.fake->miScanCtrl(std::forward<decltype(cb)>(cb));
    });

    EXPECT_CALL(mock, adminIdentify).Times(::testing::AnyNumber());

    // Failed on the first query on id_sec_cntrl_list
    EXPECT_CALL(
        mock,
        adminIdentify(
            _, Eq(nvme_identify_cns::NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST), _,
            _, _))
        .WillOnce([]<class... Args>(Args... args) -> void {
        auto&& cb = std::get<sizeof...(Args) - 1>(std::tie(args...));
        return cb(
            makeLibNVMeError(0, NVME_MI_RESP_INVALID_PARAM, "adminIdentify"),
            {});
    }).WillRepeatedly([&]<class... Args>(Args&&... args) {
        return mock.fake->adminIdentify(std::forward<Args>(args)...);
    });

    // failed on first id_allocated_ns
    EXPECT_CALL(
        mock,
        adminIdentify(_, Eq(nvme_identify_cns::NVME_IDENTIFY_CNS_ALLOCATED_NS),
                      _, _, _))
        .Times(AnyNumber()) // allow to run at 0 times based on given NS number
        .WillOnce([]<class... Args>(Args... args) -> void {
        auto&& cb = std::get<sizeof...(Args) - 1>(std::tie(args...));
        return cb(
            makeLibNVMeError(0, NVME_MI_RESP_INVALID_PARAM, "adminIdentify"),
            {});
    }).WillRepeatedly([&]<class... Args>(Args&&... args) {
        return mock.fake->adminIdentify(std::forward<Args>(args)...);
    });

    // failed on first id_ns_cntrl
    EXPECT_CALL(
        mock,
        adminIdentify(_, Eq(nvme_identify_cns::NVME_IDENTIFY_CNS_NS_CTRL_LIST),
                      _, _, _))
        .Times(AnyNumber()) // allow to run at 0 times based on given NS number
        .WillOnce([]<class... Args>(Args... args) -> void {
        auto&& cb = std::get<sizeof...(Args) - 1>(std::tie(args...));
        return cb(
            makeLibNVMeError(0, NVME_MI_RESP_INVALID_PARAM, "adminIdentify"),
            {});
    }).WillRepeatedly([&]<class... Args>(Args&&... args) {
        return mock.fake->adminIdentify(std::forward<Args>(args)...);
    });

    // failed on first id_cntrl
    EXPECT_CALL(mock,
                adminIdentify(_, Eq(nvme_identify_cns::NVME_IDENTIFY_CNS_CTRL),
                              _, _, _))
        .WillOnce([]<class... Args>(Args... args) -> void {
        auto&& cb = std::get<sizeof...(Args) - 1>(std::tie(args...));
        return cb(
            makeLibNVMeError(0, NVME_MI_RESP_INVALID_PARAM, "adminIdentify"),
            {});
    }).WillRepeatedly([&]<class... Args>(Args&&... args) {
        return mock.fake->adminIdentify(std::forward<Args>(args)...);
    });

    // failed on first id_ns
    EXPECT_CALL(
        mock,
        adminIdentify(_, Eq(nvme_identify_cns::NVME_IDENTIFY_CNS_NS), _, _, _))
        .Times(AnyNumber()) // allow to run at 0 times based on given NS number
        .WillOnce([]<class... Args>(Args... args) -> void {
        auto&& cb = std::get<sizeof...(Args) - 1>(std::tie(args...));
        return cb(
            makeLibNVMeError(0, NVME_MI_RESP_INVALID_PARAM, "adminIdentify"),
            {});
    }).WillRepeatedly([&]<class... Args>(Args&&... args) {
        return mock.fake->adminIdentify(std::forward<Args>(args)...);
    });

    // Failed on list namespace
    EXPECT_CALL(mock, adminListNamespaces)
        .WillOnce([]<class... Args>(Args... args) -> void {
        auto&& cb = std::get<sizeof...(Args) - 1>(std::tie(args...));
        return cb(
            makeLibNVMeError(0, NVME_MI_RESP_INVALID_PARAM, "adminIdentify"),
            {});
    }).WillRepeatedly([&]<class... Args>(Args&&... args) {
        return mock.fake->adminListNamespaces(std::forward<Args>(args)...);
    });

    // wait for subsystem initialization, each failure will introduce 1 second
    // delay for retry
    timer.expires_after(subsysPollTime * (2 + 10 + 4));
    timer.async_wait([&](boost::system::error_code) {
        systemBus->async_method_call(
            [&, this](boost::system::error_code, const GetSubTreeType& result) {
            // Only PF and the enabled VF should be listed
            EXPECT_EQ(result.size(), 2);
            subsys->stop();

            // wait for storage controller destruction.
            timer.expires_after(subsysPollTime * 1);
            timer.async_wait([&](boost::system::error_code) {
                systemBus->async_method_call(
                    [&](boost::system::error_code,
                        const GetSubTreeType& result) {
                    // not storage controller should be listed.
                    nlohmann::json j(result);
                    EXPECT_EQ(result.size(), 0)
                        << "The following interfaces remain after STOP: \n"
                        << j.dump(2) << '\n';
                    io.stop();
                },
                    "xyz.openbmc_project.ObjectMapper",
                    "/xyz/openbmc_project/object_mapper",
                    "xyz.openbmc_project.ObjectMapper", "GetSubTree",
                    subsysPath, 0,
                    std::vector<std::string>{"xyz.openbmc_project.Inventory."
                                             "Item.StorageController"});
            });
        }, "xyz.openbmc_project.ObjectMapper",
            "/xyz/openbmc_project/object_mapper",
            "xyz.openbmc_project.ObjectMapper", "GetSubTree", subsysPath, 0,
            std::vector<std::string>{
                "xyz.openbmc_project.Inventory.Item.StorageController"});
    });
    io.run();
}
int main(int argc, char** argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
