-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial commit: add device model test helper class.
Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
- Loading branch information
Showing
3 changed files
with
171 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
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; | ||
const std::string& migration_files_path; | ||
const std::string& config_path; | ||
|
||
// 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 |