/*
 * Copyright (c) 2023 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <devmon-common/arch_mode_manager.h>
#include <gtest/gtest.h>
#include <test_utilities/test_base.h>

#include "device/driver.h"
#include "device/test_driver.h"
#include "devmon.h"
#include "discovery/app_schema.h"
#include "discovery/csr_utils.h"
#include "discovery/object_group.h"
#include "discovery/root_object.h"
#include "test_paths.h"
#include "topology/root_topo_object.h"
#include <chrono>
#include <mc/app/service_registry.h>
#include <memory>
#include <optional>
#include <thread>
#include <unordered_map>

namespace {

driver_handle_t accessor_ctor_stub(void*, const char*)
{
    return nullptr;
}

status_t accessor_init_stub(driver_handle_t, void*, void*)
{
    return STATUS_OK;
}

status_t accessor_start_stub(driver_handle_t)
{
    return STATUS_OK;
}

status_t accessor_stop_stub(driver_handle_t)
{
    return STATUS_OK;
}

const char* accessor_dump_stub(driver_handle_t)
{
    static constexpr char k_accessor_dump[] =
        "Chip,Accessor/Scanner,Period,Aggregate_status,Status,Scan_status,Success_count,"
        "Failure_count,Value,Emit_signal_count,Error\n";
    return k_accessor_dump;
}

void register_accessor_driver_stub()
{
    static bool registered = false;
    if (registered) {
        return;
    }

    device_driver_t accessor_driver{"Accessor", accessor_ctor_stub, accessor_init_stub, accessor_start_stub,
                                    accessor_stop_stub};
    accessor_driver.dump = accessor_dump_stub;

    devmon::device_drivers drivers;
    drivers.emplace_back(std::make_shared<device_driver_t>(accessor_driver));
    devmon::device_driver_factory::get_instance().set_device_driver("Accessor", &drivers);

    registered = true;
}

// Scanner stub 函数
driver_handle_t scanner_ctor_stub(void*, const char*)
{
    return nullptr;
}

status_t scanner_init_stub(driver_handle_t, void*, void*)
{
    return STATUS_OK;
}

status_t scanner_start_stub(driver_handle_t)
{
    return STATUS_OK;
}

status_t scanner_stop_stub(driver_handle_t)
{
    return STATUS_OK;
}

// Accessor stub 函数(无 dump 方法)
driver_handle_t accessor_ctor_stub_no_dump(void*, const char*)
{
    return nullptr;
}

status_t accessor_init_stub_no_dump(driver_handle_t, void*, void*)
{
    return STATUS_OK;
}

status_t accessor_start_stub_no_dump(driver_handle_t)
{
    return STATUS_OK;
}

status_t accessor_stop_stub_no_dump(driver_handle_t)
{
    return STATUS_OK;
}

} // namespace

using namespace devmon;

class DevmonAppTest : public mc::test::TestWithDbusDaemon {
public:
protected:
    static devmon::devmon_service& test_service()
    {
        return *m_test_service;
    }

    static void SetUpTestSuite()
    {
        TestWithDbusDaemon::SetUpTestSuite();
        // 设置三层架构模式,禁用 devmon_service 内的 discovery(由 discovery_service 负责)
        devmon::arch_mode_manager::get_instance().set_arch_mode(true);
        m_test_service = mc::make_shared<devmon::devmon_service>("bmc.kepler.devmon");
        m_test_service->init({{"driver_path", "./subprojects/component_drivers/opt/bmc/drivers"}});
        m_test_service->start();
        create_driver();
        cleanup_service_state();
    }

    static void TearDownTestSuite()
    {
        devmon::device_driver_factory::get_instance().remove_device_driver("hisi_182x");
        m_test_service->stop();
        m_test_service.reset();
        devmon::arch_mode_manager::get_instance().reset();
        TestWithDbusDaemon::TearDownTestSuite();
    }

    void SetUp() override
    {
        TestWithDbusDaemon::SetUp();
        cleanup_service_state();
    }

    void TearDown() override
    {
        // 清理测试创建的对象
        cleanup_service_state();
        TestWithDbusDaemon::TearDown();
    }

private:
    // 清理设备对象(/bmc/dev/Systems/ 下的对象)
    static void cleanup_device_objects()
    {
        auto&                    object_table = test_service().get_object_table();
        std::vector<std::string> device_paths;
        object_table.query_object(mc::db::query_builder(), [&device_paths](mc::db::object_base& obj) {
            try {
                auto&      abstract_obj = static_cast<mc::engine::abstract_object&>(obj);
                const auto object_path  = std::string(abstract_obj.get_object_path());
                if (object_path.find("/bmc/dev/Systems/") == 0) {
                    device_paths.push_back(object_path);
                }
            } catch (...) {
                // 忽略单个对象的处理错误
            }
            return true;
        });
        if (device_paths.empty()) {
            return;
        }
        std::sort(device_paths.begin(), device_paths.end(), [](const std::string& a, const std::string& b) {
            return a.length() > b.length(); // 按路径长度降序排列
        });
        for (const auto& path : device_paths) {
            try {
                if (!path.empty()) {
                    // 在注销前检查对象是否仍然存在,避免注销不存在的路径导致段错误
                    bool object_exists = false;
                    object_table.query_object(
                        mc::db::query_builder(), [&object_exists, &path](mc::db::object_base& obj) {
                            try {
                                auto&      abstract_obj = static_cast<mc::engine::abstract_object&>(obj);
                                const auto object_path  = std::string(abstract_obj.get_object_path());
                                if (object_path == path) {
                                    object_exists = true;
                                    return false; // 找到后停止查询
                                }
                            } catch (...) {
                                // 忽略单个对象的处理错误
                            }
                            return true;
                        });
                    if (object_exists) {
                        test_service().unregister_object(path);
                    }
                }
            } catch (...) {
                // 忽略注销错误,某些对象可能已经被删除
            }
        }
    }

    // 清理 device_topo 中的设备对象映射
    static void cleanup_device_topo()
    {
        try {
            auto&                    topo         = device_topo::get_instance();
            auto&                    object_table = test_service().get_object_table();
            std::vector<std::string> positions;

            // 从对象组中获取 position(对象组的对象名就是 position)
            object_table.query_object(mc::db::query_builder(), [&positions](mc::db::object_base& obj) {
                try {
                    auto&      abstract_obj = static_cast<mc::engine::abstract_object&>(obj);
                    const auto object_path  = std::string(abstract_obj.get_object_path());
                    // 对象组路径格式:/bmc/dev/ObjectGroup/{position}
                    if (object_path.find("/bmc/dev/ObjectGroup/") == 0 && object_path != "/bmc/dev/ObjectGroup") {
                        auto object_name = abstract_obj.get_object_name();
                        if (!object_name.empty()) {
                            positions.push_back(std::string(object_name));
                        }
                    }
                } catch (...) {
                    // 忽略单个对象的处理错误
                }
                return true;
            });

            // 尝试清理每个 position 的设备对象
            for (const auto& position : positions) {
                try {
                    topo.remove_device_object(position);
                } catch (...) {
                    // 忽略清理失败的情况
                }
            }
        } catch (...) {
            // 如果 device_topo 未初始化或操作失败,忽略错误
        }
    }

    // 清理对象组对象
    static void cleanup_object_groups()
    {
        auto& object_table = test_service().get_object_table();
        for (int retry = 0; retry < 3; ++retry) {
            std::vector<std::string> paths_to_remove;
            object_table.query_object(mc::db::query_builder(), [&paths_to_remove](mc::db::object_base& obj) {
                try {
                    auto& abstract_obj = static_cast<mc::engine::abstract_object&>(obj);
                    auto  object_path  = std::string(abstract_obj.get_object_path());
                    // 清理 /bmc/dev/ObjectGroup/ 下的对象,但保留 ObjectGroupRoot
                    if (object_path.find("/bmc/dev/ObjectGroup/") == 0 && object_path != "/bmc/dev/ObjectGroup") {
                        paths_to_remove.push_back(object_path);
                    }
                } catch (...) {
                    // 忽略单个对象的处理错误
                }
                return true;
            });

            if (paths_to_remove.empty()) {
                break;
            }

            std::sort(paths_to_remove.begin(), paths_to_remove.end(), [](const std::string& a, const std::string& b) {
                return a.length() > b.length(); // 按路径长度降序排列
            });

            for (const auto& path : paths_to_remove) {
                try {
                    if (!path.empty()) {
                        // 在注销前检查对象是否仍然存在,避免注销不存在的路径导致段错误
                        bool object_exists = false;
                        object_table.query_object(
                            mc::db::query_builder(), [&object_exists, &path](mc::db::object_base& obj) {
                                try {
                                    auto&      abstract_obj = static_cast<mc::engine::abstract_object&>(obj);
                                    const auto object_path  = std::string(abstract_obj.get_object_path());
                                    if (object_path == path) {
                                        object_exists = true;
                                        return false; // 找到后停止查询
                                    }
                                } catch (...) {
                                    // 忽略单个对象的处理错误
                                }
                                return true;
                            });
                        if (object_exists) {
                            test_service().unregister_object(path);
                        }
                    }
                } catch (...) {
                    // 忽略注销错误,某些对象可能已经被删除
                }
            }
        }
    }

    static void cleanup_service_state()
    {
        try {
            // 清理设备对象(/bmc/dev/Systems/ 下的对象)
            cleanup_device_objects();

            // 清理 device_topo 中的设备对象映射(通过对象组获取所有 position)
            cleanup_device_topo();

            // 清理对象组对象(/bmc/dev/ObjectGroup/ 下的对象)
            cleanup_object_groups();

            // 重置对象组数据,避免测试用例间相互影响
            object_group_data::reset_for_test();

            // 清空func_collection缓存,避免测试用例间相互影响
        } catch (...) {
            // 如果清理过程中出现任何错误,忽略它,避免影响测试
        }
    }

protected:
    static mc::shared_ptr<devmon::devmon_service> m_test_service;
    static devmon::device_drivers                 m_test_device_driver;

    static void create_driver()
    {
        using namespace devmon::test;
        auto test_drv = std::make_unique<test_driver>();
        // 提供与CSR匹配的设备名,底层对象使用 test_device 实现
        std::string card = "PCIeNicCard";
        std::string port = "NicPort";
        std::string om   = "OpticalTransceiver";
        m_test_device_driver.emplace_back(test_drv->create(card));
        m_test_device_driver.emplace_back(test_drv->create(port));
        m_test_device_driver.emplace_back(test_drv->create(om));
        devmon::device_driver_factory::get_instance().set_device_driver("hisi_182x", &m_test_device_driver);
        // 保存 test_drv 生命周期到静态容器避免提前析构
        (void)test_drv.release();
    }
};

// 在类外部定义和初始化静态成员
mc::shared_ptr<devmon::devmon_service> DevmonAppTest::m_test_service;
devmon::device_drivers                 DevmonAppTest::m_test_device_driver;

// 测试 init 方法成功路径(带 app_paths)
TEST_F(DevmonAppTest, init_with_app_paths)
{
    devmon::devmon_service test_service{"bmc.kepler.test_devmon_init"};

    std::unordered_map<std::string, std::string> app_paths = {{"test_app", devmon::test::get_test_apps_path()}};

    mc::dict args = {{"driver_path", "./subprojects/component_drivers/opt/bmc/drivers"}, {"app_paths", app_paths}};

    bool result = test_service.init(args);
    EXPECT_TRUE(result);

    // 清理
    test_service.stop();
}

// 测试 cleanup 方法
TEST_F(DevmonAppTest, cleanup)
{
    devmon::devmon_service test_service{"bmc.kepler.test_devmon_cleanup"};

    // cleanup 方法应该不会抛出异常
    EXPECT_NO_THROW(test_service.cleanup());
}

// 测试 cleanup 在服务启动后调用
TEST_F(DevmonAppTest, cleanup_after_start)
{
    // 注意:不能创建新的 devmon_service 并调用 start(),因为根对象 "Devmon" 已经在
    // SetUpTestSuite 中创建,会导致对象名冲突。这里只测试 cleanup 方法本身。
    // cleanup 方法应该不会抛出异常,即使服务已启动
    EXPECT_NO_THROW(test_service().cleanup());
}

// 测试 cleanup 多次调用
TEST_F(DevmonAppTest, cleanup_multiple_calls)
{
    devmon::devmon_service test_service{"bmc.kepler.test_devmon_cleanup_multiple"};

    // cleanup 方法应该可以多次调用而不抛出异常
    EXPECT_NO_THROW(test_service.cleanup());
    EXPECT_NO_THROW(test_service.cleanup());
    EXPECT_NO_THROW(test_service.cleanup());
}

// 测试 mcapp 能通过 config_type 识别 devmon 配置属性
TEST_F(DevmonAppTest, mcapp_service_config_descriptor)
{
    mc::app::service_registry registry;
    registry.register_service<devmon::devmon_service>("devmon_service");

    auto* descriptor = registry.find("devmon_service");
    ASSERT_NE(descriptor, nullptr);
    EXPECT_TRUE(descriptor->config.schema.contains("driver_path"));
    EXPECT_TRUE(descriptor->config.schema.contains("app_paths"));
}

TEST_F(DevmonAppTest, root_objects_exist_after_start)
{
    // 确认服务启动后根对象已注册
    auto& object_table   = test_service().get_object_table();
    auto  devmon_obj     = object_table.find_object(mc::engine::by_object_name::field == "Devmon");
    auto  topo_obj       = object_table.find_object(mc::engine::by_object_name::field == "DevTopology");
    auto  obj_group_root = object_table.find_object(mc::engine::by_object_name::field == "ObjectGroupRoot");

    ASSERT_TRUE(devmon_obj);
    ASSERT_TRUE(topo_obj);
    ASSERT_TRUE(obj_group_root);

    auto* devmon_abstract = static_cast<mc::engine::abstract_object*>(devmon_obj.get());
    auto* topo_abstract   = static_cast<mc::engine::abstract_object*>(topo_obj.get());
    auto* group_abstract  = static_cast<mc::engine::abstract_object*>(obj_group_root.get());

    EXPECT_EQ(std::string_view("/bmc/dev"), devmon_abstract->get_object_path());
    EXPECT_EQ(std::string_view("/bmc/dev/topology"), topo_abstract->get_object_path());
    EXPECT_EQ(std::string_view("/bmc/dev/ObjectGroup"), group_abstract->get_object_path());
}

TEST_F(DevmonAppTest, init_populates_app_schema)
{
    devmon::devmon_service test_service_instance{"bmc.kepler.test_devmon_schema"};

    std::unordered_map<std::string, std::string> app_paths = {{"test_devices", devmon::test::get_test_apps_path()}};

    mc::dict args = {{"driver_path", "./subprojects/component_drivers/opt/bmc/drivers"}, {"app_paths", app_paths}};

    // 初始化服务时应该加载 schema 信息
    ASSERT_TRUE(test_service_instance.init(args));

    mc::dict ctx        = {{"SystemId", "1"}, {"Id", "DeviceA"}};
    auto     class_info = app_schema::get_instance().get_class_info("TestCard", ctx);

    EXPECT_EQ(class_info.app, "test_devices");
    EXPECT_EQ(class_info.path, "/bmc/dev/Systems/1/TestCard/DeviceA");

    // 清空 schema 状态,避免影响其他用例
    std::unordered_map<std::string, std::string> empty_paths;
    app_schema::get_instance().init(empty_paths);

    // stop 不应抛出异常
    EXPECT_NO_THROW(test_service_instance.stop());
}

TEST_F(DevmonAppTest, root_object_duplicate_creation_throws)
{
    // 再次创建根对象应因路径冲突抛出异常
    EXPECT_THROW(root_object::create_root_object(&test_service()), std::exception);
}

TEST_F(DevmonAppTest, object_group_root_duplicate_creation_throws)
{
    // 再次创建对象组根节点应因路径冲突抛出异常
    EXPECT_THROW(object_group_root::create_object(&test_service()), std::exception);
}

TEST_F(DevmonAppTest, stop_without_topology_instance_returns_true)
{
    devmon::devmon_service service{"bmc.kepler.test_devmon_stop_only"};
    mc::dict               args = {{"driver_path", "./subprojects/component_drivers/opt/bmc/drivers"}};

    ASSERT_TRUE(service.init(args));

    // 未调用 start,topology_discovery 实例不会被创建,stop 应该仍然返回 true
    EXPECT_TRUE(service.stop());
}

// 测试 stop 中 topology_discovery::cleanup 异常处理
// 注意:由于 topology_discovery 是单例,且根对象 "Devmon" 已在 SetUpTestSuite 中创建,
// 无法创建新的 devmon_service 实例来测试异常处理,因为会导致对象表冲突。
TEST_F(DevmonAppTest, stop_handles_topology_cleanup_exception)
{
    devmon::devmon_service service{"bmc.kepler.test_devmon_stop_cleanup"};
    ASSERT_TRUE(service.init({{"driver_path", "./subprojects/component_drivers/opt/bmc/drivers"}}));

    // 不在用例中 stop/restart 共享服务,避免污染 mcapp 与 TestWithDbusDaemon 的 suite 生命周期。
    EXPECT_NO_THROW(EXPECT_TRUE(service.stop()));
}

TEST_F(DevmonAppTest, dump_scanners_info)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    EXPECT_NO_THROW(test_service().dump_scanners_info(test_dir));

    std::string expected_file = test_dir + "/snapshot.csv";
    if (mc::filesystem::exists(expected_file)) {
        auto content_opt = mc::filesystem::read_file(expected_file);
        ASSERT_TRUE(content_opt.has_value());
        std::string content = content_opt.value();
        EXPECT_FALSE(content.empty());
    }
    mc::filesystem::remove_all(test_dir);
}

TEST_F(DevmonAppTest, dump_drivers_load_info)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    EXPECT_NO_THROW(test_service().dump_drivers_load_info(test_dir));

    std::string expected_file = test_dir + "/drivers_load_info.csv";
    EXPECT_TRUE(mc::filesystem::exists(expected_file));

    auto content_opt = mc::filesystem::read_file(expected_file);
    ASSERT_TRUE(content_opt.has_value());
    std::string content = content_opt.value();
    EXPECT_FALSE(content.empty());
    EXPECT_NE(content.find("DriverName,Load_status"), std::string::npos);

    mc::filesystem::remove_all(test_dir);
}

TEST_F(DevmonAppTest, dump_chips_access_info)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));

    std::string expected_file = test_dir + "/chips_access_statistic.csv";
    EXPECT_TRUE(mc::filesystem::exists(expected_file));

    auto content_opt = mc::filesystem::read_file(expected_file);
    ASSERT_TRUE(content_opt.has_value());
    std::string content = content_opt.value();
    EXPECT_FALSE(content.empty());
    EXPECT_NE(content.find("Bus,Chip,Write_success_count"), std::string::npos);

    mc::filesystem::remove_all(test_dir);
}

TEST_F(DevmonAppTest, dump_accessors_info)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    register_accessor_driver_stub();

    EXPECT_NO_THROW(test_service().dump_accessors_info(test_dir));

    std::string expected_file = test_dir + "/snapshot.csv";
    EXPECT_TRUE(mc::filesystem::exists(expected_file));

    auto content_opt = mc::filesystem::read_file(expected_file);
    ASSERT_TRUE(content_opt.has_value());
    std::string content = content_opt.value();
    EXPECT_FALSE(content.empty());
    // 验证文件包含访问器信息的标题
    EXPECT_NE(content.find("Chip,Accessor/"
                           "Scanner,Period,Aggregate_status,Status,Scan_status,Success_count,"
                           "Failure_count,Value,Emit_signal_count,Error"),
              std::string::npos);

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_drivers_load_info 文件写入失败场景
TEST_F(DevmonAppTest, dump_drivers_load_info_write_failure)
{
    // 使用只读目录或无效路径来模拟文件写入失败
    std::string test_dir = "/proc/sys"; // 使用系统只读目录

    // 不会抛出异常,但会记录错误日志,这是正常行为
    EXPECT_NO_THROW(test_service().dump_drivers_load_info(test_dir));
}

// 测试 dump_chips_access_info 文件写入失败场景
TEST_F(DevmonAppTest, dump_chips_access_info_write_failure)
{
    // 使用只读目录或无效路径来模拟文件写入失败
    std::string test_dir = "/proc/sys"; // 使用系统只读目录

    // 不会抛出异常,但会记录错误日志,这是正常行为
    EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));
}

// 测试 dump_scanners_info 文件写入失败场景
TEST_F(DevmonAppTest, dump_scanners_info_write_failure)
{
    // 使用只读目录或无效路径来模拟文件写入失败
    std::string test_dir = "/proc/sys"; // 使用系统只读目录

    // 不会抛出异常,但会记录错误日志,这是正常行为
    EXPECT_NO_THROW(test_service().dump_scanners_info(test_dir));
}

// 测试 dump_accessors_info 文件写入失败场景
TEST_F(DevmonAppTest, dump_accessors_info_write_failure)
{
    // 使用只读目录或无效路径来模拟文件写入失败
    std::string test_dir = "/proc/sys"; // 使用系统只读目录

    register_accessor_driver_stub();

    // 不会抛出异常,但会记录错误日志,这是正常行为
    EXPECT_NO_THROW(test_service().dump_accessors_info(test_dir));
}

// 测试 init 方法成功路径(不带 app_paths)
TEST_F(DevmonAppTest, init_without_app_paths)
{
    devmon::devmon_service test_service{"bmc.kepler.test_devmon_init_no_app_paths"};

    mc::dict args = {{"driver_path", "./subprojects/component_drivers/opt/bmc/drivers"}};

    bool result = test_service.init(args);
    EXPECT_TRUE(result);

    // 清理
    test_service.stop();
}

// 测试 init 方法空参数场景
TEST_F(DevmonAppTest, init_with_empty_args)
{
    devmon::devmon_service test_service{"bmc.kepler.test_devmon_init_empty"};

    mc::dict args; // 空参数

    // 空参数可能导致 mc::from_variant 失败或使用默认值
    // 这里主要验证函数不会崩溃
    bool result = test_service.init(args);
    // 结果可能是 true 或 false,取决于 mc::engine::service::init 的行为
    // 主要验证不会抛出异常
    EXPECT_NO_THROW(test_service.stop());
}

// 测试 on_dump 方法
TEST_F(DevmonAppTest, on_dump)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    register_accessor_driver_stub();

    EXPECT_NO_THROW(test_service().on_dump(test_dir));

    // 验证相关文件是否生成
    std::string snapshot_file = test_dir + "/snapshot.csv";
    std::string drivers_file  = test_dir + "/drivers_load_info.csv";

    // snapshot.csv 应该存在(由 dump_scanners_info 和 dump_accessors_info 生成)
    if (mc::filesystem::exists(snapshot_file)) {
        auto content_opt = mc::filesystem::read_file(snapshot_file);
        ASSERT_TRUE(content_opt.has_value());
    }

    // drivers_load_info.csv 应该存在
    EXPECT_TRUE(mc::filesystem::exists(drivers_file));

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_scanners_info 没有 Scanner 驱动器的场景
TEST_F(DevmonAppTest, dump_scanners_info_no_driver)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 确保没有注册 Scanner 驱动器
    try {
        devmon::device_driver_factory::get_instance().remove_device_driver("Scanner");
    } catch (...) {
        // 忽略删除不存在的驱动器的错误
    }

    // 应该不会抛出异常,但会记录错误日志
    EXPECT_NO_THROW(test_service().dump_scanners_info(test_dir));

    // 文件应该仍然生成(即使没有数据)
    std::string expected_file = test_dir + "/snapshot.csv";
    if (mc::filesystem::exists(expected_file)) {
        auto content_opt = mc::filesystem::read_file(expected_file);
        if (content_opt.has_value()) {
            std::string content = content_opt.value();
            // 应该至少包含标题行
            EXPECT_NE(content.find("Chip,Accessor/Scanner"), std::string::npos);
        }
    }

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_scanners_info Scanner 驱动器没有 dump 方法的场景
TEST_F(DevmonAppTest, dump_scanners_info_no_dump_method)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 注册一个没有 dump 方法的 Scanner 驱动器
    device_driver_t scanner_driver{"Scanner", scanner_ctor_stub, scanner_init_stub, scanner_start_stub,
                                   scanner_stop_stub};
    // 不设置 dump 方法
    scanner_driver.dump = nullptr;

    devmon::device_drivers drivers;
    drivers.emplace_back(std::make_shared<device_driver_t>(scanner_driver));
    devmon::device_driver_factory::get_instance().set_device_driver("Scanner", &drivers);

    // 应该不会抛出异常,但会记录错误日志
    EXPECT_NO_THROW(test_service().dump_scanners_info(test_dir));

    // 清理
    devmon::device_driver_factory::get_instance().remove_device_driver("Scanner");

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_accessors_info 没有 Accessor 驱动器的场景
TEST_F(DevmonAppTest, dump_accessors_info_no_driver)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 确保没有注册 Accessor 驱动器
    try {
        devmon::device_driver_factory::get_instance().remove_device_driver("Accessor");
    } catch (...) {
        // 忽略删除不存在的驱动器的错误
    }

    // 应该不会抛出异常,但会记录错误日志
    EXPECT_NO_THROW(test_service().dump_accessors_info(test_dir));

    // 文件应该仍然生成(即使没有数据)
    std::string expected_file = test_dir + "/snapshot.csv";
    if (mc::filesystem::exists(expected_file)) {
        auto content_opt = mc::filesystem::read_file(expected_file);
        if (content_opt.has_value()) {
            std::string content = content_opt.value();
            // 应该至少包含标题行
            EXPECT_NE(content.find("Chip,Accessor/Scanner"), std::string::npos);
        }
    }

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_jbog_manager_info 没有 jbog 驱动器的场景
TEST_F(DevmonAppTest, dump_jbog_manager_info_no_driver)
{
    // 确保没有注册 jbog 驱动器
    try {
        devmon::device_driver_factory::get_instance().remove_device_driver("jbog");
    } catch (...) {
        // 忽略删除不存在的驱动器的错误
    }

    // 应该不会抛出异常,但会记录错误日志
    EXPECT_NO_THROW(test_service().dump_jbog_manager_info());
}

// 测试 dump_accessors_info Accessor 驱动器没有 dump 方法的场景
TEST_F(DevmonAppTest, dump_accessors_info_no_dump_method)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 注册一个没有 dump 方法的 Accessor 驱动器
    device_driver_t accessor_driver{"Accessor", accessor_ctor_stub_no_dump, accessor_init_stub_no_dump,
                                    accessor_start_stub_no_dump, accessor_stop_stub_no_dump};
    // 不设置 dump 方法
    accessor_driver.dump = nullptr;

    devmon::device_drivers drivers;
    drivers.emplace_back(std::make_shared<device_driver_t>(accessor_driver));
    devmon::device_driver_factory::get_instance().set_device_driver("Accessor", &drivers);

    // 应该不会抛出异常,但会记录错误日志
    EXPECT_NO_THROW(test_service().dump_accessors_info(test_dir));

    // 清理
    devmon::device_driver_factory::get_instance().remove_device_driver("Accessor");

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_jbog_manager_info Manager 驱动器没有 dump 方法的场景
TEST_F(DevmonAppTest, dump_jbog_manager_info_no_dump_method)
{
    // 注册一个没有 dump 方法的 Accessor 驱动器
    device_driver_t jbog_manager_driver{"Manager", accessor_ctor_stub_no_dump, accessor_init_stub_no_dump,
                                        accessor_start_stub_no_dump, accessor_stop_stub_no_dump};
    // 不设置 dump 方法
    jbog_manager_driver.dump = nullptr;

    devmon::device_drivers drivers;
    drivers.emplace_back(std::make_shared<device_driver_t>(jbog_manager_driver));
    devmon::device_driver_factory::get_instance().set_device_driver("Manager", &drivers);

    // 应该不会抛出异常,但会记录错误日志
    EXPECT_NO_THROW(test_service().dump_jbog_manager_info());

    // 清理
    devmon::device_driver_factory::get_instance().remove_device_driver("Manager");
}

// 测试 dump_chips_access_info 不依赖 DevTopology 根对象的场景
TEST_F(DevmonAppTest, dump_chips_access_info_no_root_topo)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 使用已启动的服务,临时删除 DevTopology 对象来模拟缺少根对象的场景
    auto& object_table = test_service().get_object_table();
    auto  topo_obj     = object_table.find_object(mc::engine::by_object_name::field == "DevTopology");

    // 如果 DevTopology 对象存在,临时删除它
    std::string topo_path;
    if (topo_obj) {
        topo_path = std::string(static_cast<mc::engine::abstract_object*>(topo_obj.get())->get_object_path());
        test_service().unregister_object(topo_path);
    }

    // chip 按对象表枚举,不再依赖根对象,因此仍应正常写出文件
    EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));

    std::string expected_file = test_dir + "/chips_access_statistic.csv";
    ASSERT_TRUE(mc::filesystem::exists(expected_file));
    auto content = mc::filesystem::read_file(expected_file);
    ASSERT_TRUE(content.has_value());
    EXPECT_NE(content->find("Bus,Chip,Write_success_count"), std::string::npos);

    // 恢复 DevTopology 对象(如果需要)
    if (!topo_path.empty()) {
        // 重新创建 DevTopology 对象(如果不存在)
        auto check_obj = object_table.find_object(mc::engine::by_object_name::field == "DevTopology");
        if (!check_obj) {
            try {
                root_topo_object::create_root_topo_object(&test_service());
            } catch (...) {
                // 如果创建失败(例如路径冲突),忽略错误
            }
        }
    }

    mc::filesystem::remove_all(test_dir);
}

// 测试 root_topo_object 重复创建抛出异常
TEST_F(DevmonAppTest, root_topo_object_duplicate_creation_throws)
{
    // 再次创建根拓扑对象应因路径冲突抛出异常
    EXPECT_THROW(root_topo_object::create_root_topo_object(&test_service()), std::exception);
}

// 测试 start 多次调用
TEST_F(DevmonAppTest, start_multiple_calls)
{
    // mcapp service 的 start 是幂等的,已运行时直接返回成功。
    EXPECT_NO_THROW(EXPECT_TRUE(test_service().start()));

    // 验证根对象仍然存在且唯一
    auto& object_table = test_service().get_object_table();
    auto  devmon_obj   = object_table.find_object(mc::engine::by_object_name::field == "Devmon");
    ASSERT_TRUE(devmon_obj);
}

// 测试 on_dump 在 release build 下不调用 dump_chips_access_info
TEST_F(DevmonAppTest, on_dump_release_build_skips_chips_access_info)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    register_accessor_driver_stub();

    EXPECT_NO_THROW(test_service().on_dump(test_dir));

    // 验证相关文件是否生成
    std::string snapshot_file = test_dir + "/snapshot.csv";
    std::string drivers_file  = test_dir + "/drivers_load_info.csv";
    std::string chips_file    = test_dir + "/chips_access_statistic.csv";

    // snapshot.csv 应该存在(由 dump_scanners_info 和 dump_accessors_info 生成)
    if (mc::filesystem::exists(snapshot_file)) {
        auto content_opt = mc::filesystem::read_file(snapshot_file);
        ASSERT_TRUE(content_opt.has_value());
    }

    // drivers_load_info.csv 应该存在
    EXPECT_TRUE(mc::filesystem::exists(drivers_file));

    // chips_access_statistic.csv 的存在取决于构建类型
    // 如果是 release build,文件不应该存在;如果不是 release build,文件应该存在
    bool is_release = devmon::utils::is_release_build();
    if (is_release) {
        // release build 下,dump_chips_access_info 不会被调用,文件不应该存在
        EXPECT_FALSE(mc::filesystem::exists(chips_file));
    } else {
        // 非 release build 下,dump_chips_access_info 会被调用,文件应该存在
        if (mc::filesystem::exists(chips_file)) {
            auto content_opt = mc::filesystem::read_file(chips_file);
            if (content_opt.has_value()) {
                std::string content = content_opt.value();
                EXPECT_FALSE(content.empty());
            }
        }
    }

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_chips_access_info 中 class_name 为空的情况
TEST_F(DevmonAppTest, dump_chips_access_info_empty_class_name)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 这个测试主要验证当对象的 class_name 为空时,函数能够正常处理而不崩溃
    // 由于创建具有空 class_name 的对象较为困难,这里主要验证函数能够正常运行
    EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_chips_access_info 中 dump 返回 nullptr 的情况
TEST_F(DevmonAppTest, dump_chips_access_info_dump_returns_null)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 这个测试验证当 driver.dump 返回 nullptr 时,函数能够正常处理
    // 由于需要创建一个返回 nullptr 的 driver,这里主要验证函数不会崩溃
    EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_chips_access_info 中 dump 返回空字符串的情况
TEST_F(DevmonAppTest, dump_chips_access_info_dump_returns_empty_string)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 这个测试验证当 driver.dump 返回空字符串时,函数能够正常处理
    // 主要验证函数不会崩溃,且会记录错误日志
    EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_scanners_info 中 get_device_object 返回 nullptr 的情况
TEST_F(DevmonAppTest, dump_scanners_info_device_object_not_found)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 测试当 get_device_object 返回 nullptr 时,函数能够正常处理
    // 主要验证函数不会崩溃,且会记录错误日志
    EXPECT_NO_THROW(test_service().dump_scanners_info(test_dir));

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_accessors_info 中 get_device_object 返回 nullptr 的情况
TEST_F(DevmonAppTest, dump_accessors_info_device_object_not_found)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    register_accessor_driver_stub();

    // 测试当 get_device_object 返回 nullptr 时,函数能够正常处理
    // 主要验证函数不会崩溃,且会记录错误日志
    EXPECT_NO_THROW(test_service().dump_accessors_info(test_dir));

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_scanners_info 中 dump 返回空字符串的情况
TEST_F(DevmonAppTest, dump_scanners_info_dump_returns_empty_string)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 测试当 dump 返回空字符串时,函数能够正常处理
    EXPECT_NO_THROW(test_service().dump_scanners_info(test_dir));

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_accessors_info 中 dump 返回空字符串的情况
TEST_F(DevmonAppTest, dump_accessors_info_dump_returns_empty_string)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    register_accessor_driver_stub();

    // 测试当 dump 返回空字符串时,函数能够正常处理
    EXPECT_NO_THROW(test_service().dump_accessors_info(test_dir));

    mc::filesystem::remove_all(test_dir);
}

// 测试 on_dump 中 file_path 为空的情况
TEST_F(DevmonAppTest, on_dump_empty_file_path)
{
    std::string empty_path = "";

    register_accessor_driver_stub();

    // 测试当 file_path 为空时,函数能够正常处理(可能会写入到当前目录或失败)
    EXPECT_NO_THROW(test_service().on_dump(empty_path));
}

// 测试 on_dump 中 file_path 包含特殊字符的情况
TEST_F(DevmonAppTest, on_dump_file_path_with_special_chars)
{
    std::string special_path = "/tmp/devmon_test_special_" + std::to_string(getpid());

    register_accessor_driver_stub();

    // 测试当 file_path 包含特殊字符时,函数能够正常处理
    EXPECT_NO_THROW(test_service().on_dump(special_path));

    // 清理
    if (mc::filesystem::exists(special_path)) {
        mc::filesystem::remove_all(special_path);
    }
}

// 测试 dump_chips_access_info 中对象表为空时的处理
TEST_F(DevmonAppTest, dump_chips_access_info_null_object_handling)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 表中没有 bmc.dev.Chip 对象时,只写出表头且不崩溃
    EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_chips_access_info 中对象名称去除 "_dev" 后缀的情况
TEST_F(DevmonAppTest, dump_chips_access_info_object_name_strip_dev_suffix)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 这个测试验证对象名称处理逻辑(去除 "_dev" 后缀)
    // 由于需要创建具有 Chip 接口的对象,这里主要验证函数不会崩溃
    EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_drivers_load_info 中空驱动列表的情况
TEST_F(DevmonAppTest, dump_drivers_load_info_empty_driver_list)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 即使驱动列表为空,也应该生成文件(至少包含标题行)
    EXPECT_NO_THROW(test_service().dump_drivers_load_info(test_dir));

    std::string expected_file = test_dir + "/drivers_load_info.csv";
    if (mc::filesystem::exists(expected_file)) {
        auto content_opt = mc::filesystem::read_file(expected_file);
        if (content_opt.has_value()) {
            std::string content = content_opt.value();
            // 应该至少包含标题行
            EXPECT_NE(content.find("DriverName,Load_status"), std::string::npos);
        }
    }

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_scanners_info 中空 Scanner 对象列表的情况
TEST_F(DevmonAppTest, dump_scanners_info_empty_scanner_list)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 即使没有 Scanner 对象,也应该生成文件(至少包含标题行)
    EXPECT_NO_THROW(test_service().dump_scanners_info(test_dir));

    std::string expected_file = test_dir + "/snapshot.csv";
    if (mc::filesystem::exists(expected_file)) {
        auto content_opt = mc::filesystem::read_file(expected_file);
        if (content_opt.has_value()) {
            std::string content = content_opt.value();
            // 应该至少包含标题行
            EXPECT_NE(content.find("Chip,Accessor/Scanner"), std::string::npos);
        }
    }

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_accessors_info 中空 Accessor 对象列表的情况
TEST_F(DevmonAppTest, dump_accessors_info_empty_accessor_list)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    register_accessor_driver_stub();

    // 即使没有 Accessor 对象,也应该生成文件(至少包含标题行)
    EXPECT_NO_THROW(test_service().dump_accessors_info(test_dir));

    std::string expected_file = test_dir + "/snapshot.csv";
    if (mc::filesystem::exists(expected_file)) {
        auto content_opt = mc::filesystem::read_file(expected_file);
        if (content_opt.has_value()) {
            std::string content = content_opt.value();
            // 应该至少包含标题行
            EXPECT_NE(content.find("Chip,Accessor/Scanner"), std::string::npos);
        }
    }

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_chips_access_info 中处理具有 Chip 接口但无驱动的情况
TEST_F(DevmonAppTest, dump_chips_access_info_chip_without_driver)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 这个测试验证当有 Chip 对象但没有对应驱动时,函数能够正常处理
    // 主要验证 dump_single_chip 中的异常处理路径
    EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));

    mc::filesystem::remove_all(test_dir);
}

// 测试 dump_chips_access_info 中处理对象名称长度小于4的情况(无法去除 "_dev" 后缀)
TEST_F(DevmonAppTest, dump_chips_access_info_short_object_name)
{
    std::string test_dir = "/tmp/devmon_dt_test_" + std::to_string(getpid());
    mc::filesystem::create_directories(test_dir);

    // 这个测试验证当对象名称长度小于4时,不会尝试去除 "_dev" 后缀
    // 主要验证函数不会崩溃
    EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));

    mc::filesystem::remove_all(test_dir);
}