Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial commit: add device model test helper class. #927

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
87 changes: 87 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,87 @@
// 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,
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,
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
82 changes: 82 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,82 @@
// 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:
explicit DeviceModelTestHelper(const std::string& database_path = DEVICE_MODEL_DB_IN_MEMORY_PATH,
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,
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);

private:
const std::string& database_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::database_path' is never used.
const std::string& migration_files_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::migration_files_path' is never used.
const std::string& config_path;

Check notice on line 58 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#L58

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
Loading