* 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;
}
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;
}
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;
}
}
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::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:
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 (...) {
}
}
}
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;
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());
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;
});
for (const auto& position : positions) {
try {
topo.remove_device_object(position);
} catch (...) {
}
}
} catch (...) {
}
}
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());
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 {
cleanup_device_objects();
cleanup_device_topo();
cleanup_object_groups();
object_group_data::reset_for_test();
} 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>();
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);
(void)test_drv.release();
}
};
mc::shared_ptr<devmon::devmon_service> DevmonAppTest::m_test_service;
devmon::device_drivers DevmonAppTest::m_test_device_driver;
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();
}
TEST_F(DevmonAppTest, cleanup)
{
devmon::devmon_service test_service{"bmc.kepler.test_devmon_cleanup"};
EXPECT_NO_THROW(test_service.cleanup());
}
TEST_F(DevmonAppTest, cleanup_after_start)
{
EXPECT_NO_THROW(test_service().cleanup());
}
TEST_F(DevmonAppTest, cleanup_multiple_calls)
{
devmon::devmon_service test_service{"bmc.kepler.test_devmon_cleanup_multiple"};
EXPECT_NO_THROW(test_service.cleanup());
EXPECT_NO_THROW(test_service.cleanup());
EXPECT_NO_THROW(test_service.cleanup());
}
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}};
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");
std::unordered_map<std::string, std::string> empty_paths;
app_schema::get_instance().init(empty_paths);
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));
EXPECT_TRUE(service.stop());
}
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"}}));
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);
}
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));
}
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));
}
TEST_F(DevmonAppTest, dump_scanners_info_write_failure)
{
std::string test_dir = "/proc/sys";
EXPECT_NO_THROW(test_service().dump_scanners_info(test_dir));
}
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));
}
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();
}
TEST_F(DevmonAppTest, init_with_empty_args)
{
devmon::devmon_service test_service{"bmc.kepler.test_devmon_init_empty"};
mc::dict args;
bool result = test_service.init(args);
EXPECT_NO_THROW(test_service.stop());
}
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";
if (mc::filesystem::exists(snapshot_file)) {
auto content_opt = mc::filesystem::read_file(snapshot_file);
ASSERT_TRUE(content_opt.has_value());
}
EXPECT_TRUE(mc::filesystem::exists(drivers_file));
mc::filesystem::remove_all(test_dir);
}
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);
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);
}
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);
device_driver_t scanner_driver{"Scanner", scanner_ctor_stub, scanner_init_stub, scanner_start_stub,
scanner_stop_stub};
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);
}
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);
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);
}
TEST_F(DevmonAppTest, dump_jbog_manager_info_no_driver)
{
try {
devmon::device_driver_factory::get_instance().remove_device_driver("jbog");
} catch (...) {
}
EXPECT_NO_THROW(test_service().dump_jbog_manager_info());
}
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);
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};
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);
}
TEST_F(DevmonAppTest, dump_jbog_manager_info_no_dump_method)
{
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};
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");
}
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);
auto& object_table = test_service().get_object_table();
auto topo_obj = object_table.find_object(mc::engine::by_object_name::field == "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);
}
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);
if (!topo_path.empty()) {
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);
}
TEST_F(DevmonAppTest, root_topo_object_duplicate_creation_throws)
{
EXPECT_THROW(root_topo_object::create_root_topo_object(&test_service()), std::exception);
}
TEST_F(DevmonAppTest, start_multiple_calls)
{
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);
}
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";
if (mc::filesystem::exists(snapshot_file)) {
auto content_opt = mc::filesystem::read_file(snapshot_file);
ASSERT_TRUE(content_opt.has_value());
}
EXPECT_TRUE(mc::filesystem::exists(drivers_file));
bool is_release = devmon::utils::is_release_build();
if (is_release) {
EXPECT_FALSE(mc::filesystem::exists(chips_file));
} else {
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);
}
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);
EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));
mc::filesystem::remove_all(test_dir);
}
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);
EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));
mc::filesystem::remove_all(test_dir);
}
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);
EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));
mc::filesystem::remove_all(test_dir);
}
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);
EXPECT_NO_THROW(test_service().dump_scanners_info(test_dir));
mc::filesystem::remove_all(test_dir);
}
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();
EXPECT_NO_THROW(test_service().dump_accessors_info(test_dir));
mc::filesystem::remove_all(test_dir);
}
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);
EXPECT_NO_THROW(test_service().dump_scanners_info(test_dir));
mc::filesystem::remove_all(test_dir);
}
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();
EXPECT_NO_THROW(test_service().dump_accessors_info(test_dir));
mc::filesystem::remove_all(test_dir);
}
TEST_F(DevmonAppTest, on_dump_empty_file_path)
{
std::string empty_path = "";
register_accessor_driver_stub();
EXPECT_NO_THROW(test_service().on_dump(empty_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();
EXPECT_NO_THROW(test_service().on_dump(special_path));
if (mc::filesystem::exists(special_path)) {
mc::filesystem::remove_all(special_path);
}
}
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);
EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));
mc::filesystem::remove_all(test_dir);
}
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);
EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));
mc::filesystem::remove_all(test_dir);
}
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);
}
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);
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);
}
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();
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);
}
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);
EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));
mc::filesystem::remove_all(test_dir);
}
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);
EXPECT_NO_THROW(test_service().dump_chips_access_info(test_dir));
mc::filesystem::remove_all(test_dir);
}