Skip to content

Commit

Permalink
Initial commit: add device model test helper class.
Browse files Browse the repository at this point in the history
Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
  • Loading branch information
maaikez committed Jan 2, 2025
1 parent 8d5ae96 commit ad648d0
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 1 deletion.
3 changes: 2 additions & 1 deletion tests/lib/ocpp/v201/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ target_include_directories(libocpp_unit_tests PUBLIC
${CMAKE_CURRENT_SOURCE_DIR})

target_sources(libocpp_unit_tests PRIVATE
device_model_test_helper.cpp
test_charge_point.cpp
test_database_handler.cpp
test_database_migration_files.cpp
Expand All @@ -24,4 +25,4 @@ target_sources(libocpp_unit_tests PRIVATE
# Copy the json files used for testing to the destination directory
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/json DESTINATION ${TEST_PROFILES_LOCATION_V201})

add_subdirectory(functional_blocks)
add_subdirectory(functional_blocks)
88 changes: 88 additions & 0 deletions tests/lib/ocpp/v201/device_model_test_helper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest

#include "device_model_test_helper.hpp"

#include <ocpp/common/database/database_connection.hpp>
#include <ocpp/v201/device_model.hpp>
#include <ocpp/v201/device_model_storage_sqlite.hpp>

namespace ocpp::v201 {
DeviceModelTestHelper::DeviceModelTestHelper(const std::string& database_path, const std::string& migration_files_path,
const std::string& config_path) :
database_path(database_path),
migration_files_path(migration_files_path),
config_path(config_path),
database_connection(std::make_unique<ocpp::common::DatabaseConnection>(database_path)) {
this->database_connection->open_connection();
this->device_model = create_device_model();
}

DeviceModel* DeviceModelTestHelper::get_device_model() {
if (this->device_model == nullptr) {
return nullptr;
}

return this->device_model.get();
}

bool DeviceModelTestHelper::remove_variable_from_db(const std::string component_name,

Check warning on line 29 in tests/lib/ocpp/v201/device_model_test_helper.cpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/lib/ocpp/v201/device_model_test_helper.cpp#L29

Function parameter 'component_name' should be passed by const reference.
const std::optional<std::string> component_instance,
const std::optional<uint32_t> evse_id,
const std::optional<uint32_t> connector_id,
const std::string variable_name,

Check warning on line 33 in tests/lib/ocpp/v201/device_model_test_helper.cpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/lib/ocpp/v201/device_model_test_helper.cpp#L33

Function parameter 'variable_name' should be passed by const reference.
const std::optional<std::string> variable_instance) {
const std::string delete_query = "DELETE FROM VARIABLE WHERE ID = "
"(SELECT ID FROM VARIABLE WHERE COMPONENT_ID = "
"(SELECT ID FROM COMPONENT WHERE NAME = ? AND INSTANCE IS ? AND "
"EVSE_ID IS ? AND CONNECTOR_ID IS ?) "
"AND NAME = ? AND INSTANCE IS ?)";

auto delete_stmt = this->database_connection->new_statement(delete_query);
delete_stmt->bind_text(1, component_name, common::SQLiteString::Transient);
if (component_instance.has_value()) {
delete_stmt->bind_text(2, component_instance.value(), common::SQLiteString::Transient);
} else {
delete_stmt->bind_null(2);
}
if (evse_id.has_value()) {
delete_stmt->bind_int(3, evse_id.value());
if (connector_id.has_value()) {
delete_stmt->bind_int(4, connector_id.value());
} else {
delete_stmt->bind_null(4);
}
} else {
delete_stmt->bind_null(3);
delete_stmt->bind_null(4);
}

delete_stmt->bind_text(5, variable_name, common::SQLiteString::Transient);
if (variable_instance.has_value()) {
delete_stmt->bind_text(6, variable_instance.value(), common::SQLiteString::Transient);
} else {
delete_stmt->bind_null(6);
}

if (delete_stmt->step() == SQLITE_DONE) {
EVLOG_error << this->database_connection->get_error_message();
return false;
}

return true;
}

void DeviceModelTestHelper::create_device_model_db() {
InitDeviceModelDb db(this->database_path, this->migration_files_path);
db.initialize_database(this->config_path, true);
}

std::unique_ptr<DeviceModel> DeviceModelTestHelper::create_device_model() {
create_device_model_db();
auto device_model_storage = std::make_unique<DeviceModelStorageSqlite>(this->database_path);
auto dm = std::make_unique<DeviceModel>(std::move(device_model_storage));

return dm;
}
} // namespace ocpp::v201

81 changes: 81 additions & 0 deletions tests/lib/ocpp/v201/device_model_test_helper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest

/**
* @file device_model_test_helper.hpp
* @brief @copybrief ocpp::v201::DeviceModelTestHelper
*
* @class ocpp::v201::DeviceModelTestHelper
* @brief Helper for tests where the device model is needed.
*
* If the device model is stored in memory, a database connection must be kept open at all times to prevent the
* device model to be thrown away.
*/

#pragma once

#include <memory>

#include <ocpp/v201/init_device_model_db.hpp>

const static std::string MIGRATION_FILES_PATH = "./resources/v201/device_model_migration_files";
const static std::string CONFIG_PATH = "./resources/example_config/v201/component_config";
const static std::string DEVICE_MODEL_DB_IN_MEMORY_PATH = "file::memory:?cache=shared";

namespace ocpp {
namespace common {
class DatabaseConnection;
}

namespace v201 {
class DeviceModel;

class DeviceModelTestHelper {
public:
DeviceModelTestHelper(const std::string& database_path = DEVICE_MODEL_DB_IN_MEMORY_PATH,

Check notice on line 35 in tests/lib/ocpp/v201/device_model_test_helper.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/lib/ocpp/v201/device_model_test_helper.hpp#L35

Class 'DeviceModelTestHelper' has a constructor with 1 argument that is not explicit.
const std::string& migration_files_path = MIGRATION_FILES_PATH,
const std::string& config_path = CONFIG_PATH);
DeviceModel* get_device_model();

///
/// \brief Remove a variable from the database.
/// \param component_name The component name.
/// \param component_instance Component instance (optional).
/// \param evse_id Evse id (optional).
/// \param connector_id Connector id (optional).
/// \param variable_name Variable name to remove.
/// \param variable_instance Variable instance (optional).
/// \return True on success.
///
bool remove_variable_from_db(const std::string component_name, const std::optional<std::string> component_instance,

Check warning on line 50 in tests/lib/ocpp/v201/device_model_test_helper.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/lib/ocpp/v201/device_model_test_helper.hpp#L50

Function parameter 'component_name' should be passed by const reference.
const std::optional<uint32_t> evse_id, const std::optional<uint32_t> connector_id,
const std::string variable_name, const std::optional<std::string> variable_instance);

Check warning on line 52 in tests/lib/ocpp/v201/device_model_test_helper.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/lib/ocpp/v201/device_model_test_helper.hpp#L52

Function parameter 'variable_name' should be passed by const reference.

private:
const std::string& database_path;

Check notice on line 55 in tests/lib/ocpp/v201/device_model_test_helper.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/lib/ocpp/v201/device_model_test_helper.hpp#L55

class member 'DeviceModelTestHelper::database_path' is never used.
const std::string& migration_files_path;

Check notice on line 56 in tests/lib/ocpp/v201/device_model_test_helper.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/lib/ocpp/v201/device_model_test_helper.hpp#L56

class member 'DeviceModelTestHelper::migration_files_path' is never used.
const std::string& config_path;

Check notice on line 57 in tests/lib/ocpp/v201/device_model_test_helper.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/lib/ocpp/v201/device_model_test_helper.hpp#L57

class member 'DeviceModelTestHelper::config_path' is never used.

// DatabaseConnection as member so the database keeps open and is not destroyed (because this is an in memory
// database).
std::unique_ptr<ocpp::common::DatabaseConnection> database_connection;
// Device model is a unique ptr here because of the database: it is stored in memory so as soon as the handle to
// the database closes, the database is removed. So the handle should be opened before creating the devide model.
// So the device model is initialized on nullptr, then the handle is opened, the devide model is created and the
// handle stays open until the whole test is destructed.
std::unique_ptr<DeviceModel> device_model;

///
/// \brief Create the database for the device model and apply migrations.
/// \param path Database path.
///
void create_device_model_db();

///
/// \brief Create device model.
/// \return The created device model.
///
std::unique_ptr<DeviceModel> create_device_model();
};
} // namespace v201
} // namespace ocpp

0 comments on commit ad648d0

Please sign in to comment.