Skip to content

Commit

Permalink
Merge pull request #570 from wazuh/enhancement/518-refactor-tests-to-…
Browse files Browse the repository at this point in the history
…mock-database-access

Avoid the use/creation of real databases in the UTs.
  • Loading branch information
TomasTurina authored Feb 11, 2025
2 parents 655f7e3 + d867e33 commit 19719ce
Show file tree
Hide file tree
Showing 15 changed files with 873 additions and 274 deletions.
15 changes: 10 additions & 5 deletions src/agent/agent_info/include/agent_info.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
#include <nlohmann/json.hpp>

#include <functional>
#include <memory>
#include <string>
#include <vector>

class AgentInfoPersistance;

/// @brief Stores and manages information about an agent.
///
/// This class provides methods for getting and setting the agent's name, key,
Expand All @@ -25,10 +28,12 @@ class AgentInfo
/// @param getOSInfo Function to retrieve OS information in JSON format.
/// @param getNetworksInfo Function to retrieve network information in JSON format.
/// @param agentIsRegistering True if the agent is being registered, false otherwise.
AgentInfo(std::string dbFolderPath = config::DEFAULT_DATA_PATH,
/// @param persistence Optional pointer to an AgentInfoPersistance object.
AgentInfo(const std::string& dbFolderPath = config::DEFAULT_DATA_PATH,
std::function<nlohmann::json()> getOSInfo = nullptr,
std::function<nlohmann::json()> getNetworksInfo = nullptr,
bool agentIsRegistering = false);
bool agentIsRegistering = false,
std::shared_ptr<AgentInfoPersistance> persistence = nullptr);

/// @brief Gets the agent's name.
/// @return The agent's name.
Expand Down Expand Up @@ -112,9 +117,6 @@ class AgentInfo
/// @return Vector of strings with the active IP addresses.
std::vector<std::string> GetActiveIPAddresses(const nlohmann::json& networksJson) const;

/// @brief The agent's data folder path.
std::string m_dataFolderPath;

/// @brief The agent's name.
std::string m_name;

Expand All @@ -141,4 +143,7 @@ class AgentInfo

/// @brief Specify if the agent is about to register.
bool m_agentIsRegistering;

/// @brief Pointer to the agent info persistence instance.
std::shared_ptr<AgentInfoPersistance> m_persistence;
};
33 changes: 16 additions & 17 deletions src/agent/agent_info/src/agent_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <memory>
#include <random>
#include <utility>

Expand All @@ -16,20 +17,20 @@ namespace
const std::string PRODUCT_NAME = "WazuhXDR";
} // namespace

AgentInfo::AgentInfo(std::string dbFolderPath,
AgentInfo::AgentInfo(const std::string& dbFolderPath,
std::function<nlohmann::json()> getOSInfo,
std::function<nlohmann::json()> getNetworksInfo,
bool agentIsRegistering)
: m_dataFolderPath(std::move(dbFolderPath))
, m_agentIsRegistering(agentIsRegistering)
bool agentIsRegistering,
std::shared_ptr<AgentInfoPersistance> persistence)
: m_agentIsRegistering(agentIsRegistering)
, m_persistence(persistence ? std::move(persistence) : std::make_shared<AgentInfoPersistance>(dbFolderPath))
{
if (!m_agentIsRegistering)
{
AgentInfoPersistance agentInfoPersistance(m_dataFolderPath);
m_name = agentInfoPersistance.GetName();
m_key = agentInfoPersistance.GetKey();
m_uuid = agentInfoPersistance.GetUUID();
m_groups = agentInfoPersistance.GetGroups();
m_name = m_persistence->GetName();
m_key = m_persistence->GetKey();
m_uuid = m_persistence->GetUUID();
m_groups = m_persistence->GetGroups();
}

if (m_uuid.empty())
Expand Down Expand Up @@ -183,18 +184,16 @@ std::string AgentInfo::GetMetadataInfo() const

void AgentInfo::Save() const
{
AgentInfoPersistance agentInfoPersistance(m_dataFolderPath);
agentInfoPersistance.ResetToDefault();
agentInfoPersistance.SetName(m_name);
agentInfoPersistance.SetKey(m_key);
agentInfoPersistance.SetUUID(m_uuid);
agentInfoPersistance.SetGroups(m_groups);
m_persistence->ResetToDefault();
m_persistence->SetName(m_name);
m_persistence->SetKey(m_key);
m_persistence->SetUUID(m_uuid);
m_persistence->SetGroups(m_groups);
}

bool AgentInfo::SaveGroups() const
{
AgentInfoPersistance agentInfoPersistance(m_dataFolderPath);
return agentInfoPersistance.SetGroups(m_groups);
return m_persistence->SetGroups(m_groups);
}

std::vector<std::string> AgentInfo::GetActiveIPAddresses(const nlohmann::json& networksJson) const
Expand Down
57 changes: 44 additions & 13 deletions src/agent/agent_info/src/agent_info_persistance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include <logger.hpp>

#include <column.hpp>
#include <persistence.hpp>
#include <persistence_factory.hpp>

using namespace column;
Expand All @@ -25,13 +24,20 @@ namespace
const std::string AGENT_GROUP_NAME_COLUMN_NAME = "name";
} // namespace

AgentInfoPersistance::AgentInfoPersistance(const std::string& dbFolderPath)
AgentInfoPersistance::AgentInfoPersistance(const std::string& dbFolderPath, std::unique_ptr<Persistence> persistence)
{
const auto dbFilePath = dbFolderPath + "/" + AGENT_INFO_DB_NAME;

try
{
m_db = PersistenceFactory::CreatePersistence(PersistenceFactory::PersistenceType::SQLITE3, dbFilePath);
if (persistence)
{
m_db = std::move(persistence);
}
else
{
m_db = PersistenceFactory::CreatePersistence(PersistenceFactory::PersistenceType::SQLITE3, dbFilePath);
}

if (!m_db->TableExists(AGENT_INFO_TABLE_NAME))
{
Expand Down Expand Up @@ -126,17 +132,20 @@ void AgentInfoPersistance::InsertDefaultAgentInfo()
}
}

void AgentInfoPersistance::SetAgentInfoValue(const std::string& column, const std::string& value)
bool AgentInfoPersistance::SetAgentInfoValue(const std::string& column, const std::string& value)
{
try
{
const Row columns = {ColumnValue(column, ColumnType::TEXT, value)};
m_db->Update(AGENT_INFO_TABLE_NAME, columns);
return true;
}
catch (const std::exception& e)
{
LogError("Error updating {}: {}.", column, e.what());
}

return false;
}

std::string AgentInfoPersistance::GetAgentInfoValue(const std::string& column) const
Expand Down Expand Up @@ -201,24 +210,35 @@ std::vector<std::string> AgentInfoPersistance::GetGroups() const
return groupList;
}

void AgentInfoPersistance::SetName(const std::string& name)
bool AgentInfoPersistance::SetName(const std::string& name)
{
SetAgentInfoValue(AGENT_INFO_NAME_COLUMN_NAME, name);
return SetAgentInfoValue(AGENT_INFO_NAME_COLUMN_NAME, name);
}

void AgentInfoPersistance::SetKey(const std::string& key)
bool AgentInfoPersistance::SetKey(const std::string& key)
{
SetAgentInfoValue(AGENT_INFO_KEY_COLUMN_NAME, key);
return SetAgentInfoValue(AGENT_INFO_KEY_COLUMN_NAME, key);
}

void AgentInfoPersistance::SetUUID(const std::string& uuid)
bool AgentInfoPersistance::SetUUID(const std::string& uuid)
{
SetAgentInfoValue(AGENT_INFO_UUID_COLUMN_NAME, uuid);
return SetAgentInfoValue(AGENT_INFO_UUID_COLUMN_NAME, uuid);
}

bool AgentInfoPersistance::SetGroups(const std::vector<std::string>& groupList)
{
auto transaction = m_db->BeginTransaction();
TransactionId transaction = 0;

// Handle the exception separately since it would not be necessary to perform RollBack.
try
{
transaction = m_db->BeginTransaction();
}
catch (const std::exception& e)
{
LogError("Failed to begin transaction: {}.", e.what());
return false;
}

try
{
Expand All @@ -235,13 +255,22 @@ bool AgentInfoPersistance::SetGroups(const std::vector<std::string>& groupList)
catch (const std::exception& e)
{
LogError("Error inserting group: {}.", e.what());
m_db->RollbackTransaction(transaction);

try
{
m_db->RollbackTransaction(transaction);
}
catch (const std::exception& ee)
{
LogError("Rollback failed: {}.", ee.what());
}

return false;
}
return true;
}

void AgentInfoPersistance::ResetToDefault()
bool AgentInfoPersistance::ResetToDefault()
{
try
{
Expand All @@ -250,9 +279,11 @@ void AgentInfoPersistance::ResetToDefault()
CreateAgentInfoTable();
CreateAgentGroupTable();
InsertDefaultAgentInfo();
return true;
}
catch (const std::exception& e)
{
LogError("Error resetting to default values: {}.", e.what());
}
return false;
}
22 changes: 14 additions & 8 deletions src/agent/agent_info/src/agent_info_persistance.hpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
#pragma once

#include <persistence.hpp>

#include <memory>
#include <string>
#include <vector>

class Persistence;

/// @brief Manages persistence of agent information and groups in a database.
class AgentInfoPersistance
{
public:
/// @brief Constructs the persistence manager for agent info, initializing the database and tables if necessary.
/// @param dbFolderPath Path to the database folder.
explicit AgentInfoPersistance(const std::string& dbFolderPath);
/// @param persistence Optional pointer to an existing persistence object.
explicit AgentInfoPersistance(const std::string& dbFolderPath, std::unique_ptr<Persistence> persistence = nullptr);

/// @brief Destructor for AgentInfoPersistance.
~AgentInfoPersistance();
Expand Down Expand Up @@ -47,23 +48,27 @@ class AgentInfoPersistance

/// @brief Sets the agent's name in the database.
/// @param name The name to set.
void SetName(const std::string& name);
/// @return True if the operation was successful, false otherwise.
bool SetName(const std::string& name);

/// @brief Sets the agent's key in the database.
/// @param key The key to set.
void SetKey(const std::string& key);
/// @return True if the operation was successful, false otherwise.
bool SetKey(const std::string& key);

/// @brief Sets the agent's UUID in the database.
/// @param uuid The UUID to set.
void SetUUID(const std::string& uuid);
/// @return True if the operation was successful, false otherwise.
bool SetUUID(const std::string& uuid);

/// @brief Sets the agent's group list in the database, replacing any existing groups.
/// @param groupList A vector of strings, each representing a group name.
/// @return True if the operation was successful, false otherwise.
bool SetGroups(const std::vector<std::string>& groupList);

/// @brief Resets the database tables to default values, clearing all data.
void ResetToDefault();
/// @return True if the reset was successful, false otherwise.
bool ResetToDefault();

private:
/// @brief Checks if the agent info table is empty.
Expand All @@ -82,7 +87,8 @@ class AgentInfoPersistance
/// @brief Sets a specific agent info value in the database.
/// @param column The name of the column to set.
/// @param value The value to set in the specified column.
void SetAgentInfoValue(const std::string& column, const std::string& value);
/// @return True if the operation was successful, false otherwise.
bool SetAgentInfoValue(const std::string& column, const std::string& value);

/// @brief Retrieves a specific agent info value from the database.
/// @param column The name of the column to retrieve.
Expand Down
12 changes: 8 additions & 4 deletions src/agent/agent_info/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ find_package(GTest CONFIG REQUIRED)

add_executable(agent_info_test agent_info_test.cpp)
configure_target(agent_info_test)
target_include_directories(agent_info_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src)
target_link_libraries(agent_info_test PRIVATE AgentInfo Persistence GTest::gtest)
target_include_directories(agent_info_test PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../src
${CMAKE_CURRENT_SOURCE_DIR}/../../persistence/tests/mocks)
target_link_libraries(agent_info_test PRIVATE AgentInfo Persistence GTest::gtest GTest::gmock GTest::gmock_main)
add_test(NAME AgentInfoTest COMMAND agent_info_test)

add_executable(agent_info_persistance_test agent_info_persistance_test.cpp)
configure_target(agent_info_persistance_test)
target_include_directories(agent_info_persistance_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src)
target_link_libraries(agent_info_persistance_test PRIVATE AgentInfo Persistence GTest::gtest)
target_include_directories(agent_info_persistance_test PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../src
${CMAKE_CURRENT_SOURCE_DIR}/../../persistence/tests/mocks)
target_link_libraries(agent_info_persistance_test PRIVATE AgentInfo Persistence GTest::gtest GTest::gmock)
add_test(NAME AgentInfoPersistanceTest COMMAND agent_info_persistance_test)
Loading

0 comments on commit 19719ce

Please sign in to comment.