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

Adding a few unit tests for the EvseV2G module #1013

Merged
merged 1 commit into from
Jan 22, 2025
Merged
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: 0 additions & 3 deletions modules/EvseV2G/connection/tls_connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,6 @@ void process_connection_thread(std::shared_ptr<tls::ServerConnection> con, struc
const auto result = con->accept();
switch (result) {
case tls::Connection::result_t::success:

// TODO(james-ctc) v2g_ctx->tls_key_logging

if (ctx->state == 0) {
const auto rv = ::v2g_handle_connection(connection.get());
dlog(DLOG_LEVEL_INFO, "v2g_dispatch_connection exited with %d", rv);
Expand Down
39 changes: 23 additions & 16 deletions modules/EvseV2G/din_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,14 @@ static din_responseCodeType din_validate_state(int state, enum V2gMsgTypeId curr
: din_responseCodeType_FAILED_SequenceError;
}

namespace utils {
/*!
* \brief din_validate_response_code This function checks if an external error has occurred (sequence error, user
* abort)... ). \param din_response_code is a pointer to the current response code. The value will be modified if an
* external error has occurred. \param conn the structure with the external error information. \return Returns the next
* v2g-event.
*/
static v2g_event din_validate_response_code(din_responseCodeType* const din_response_code,
struct v2g_connection const* conn) {
v2g_event din_validate_response_code(din_responseCodeType* const din_response_code, struct v2g_connection const* conn) {
enum v2g_event nextEvent = V2G_EVENT_NO_EVENT;
din_responseCodeType response_code_tmp;

Expand Down Expand Up @@ -118,6 +118,7 @@ static v2g_event din_validate_response_code(din_responseCodeType* const din_resp

return nextEvent;
}
} // namespace utils

/*!
* \brief publish_DIN_DcEvStatus This function is a helper function to publish EVStatusType.
Expand Down Expand Up @@ -295,14 +296,16 @@ static void publish_din_current_demand_req(struct v2g_context* ctx,
// Request Handling
//=============================================

namespace states {

/*!
* \brief handle_iso_session_setup This function handles the din_session_setup msg pair. It analyzes the request msg and
* fills the response msg. The request and response msg based on the open V2G structures. This structures must be
* provided within the \c conn structure. [V2G-DC-436]
* \param conn holds the structure with the V2G msg pair.
* \return Returns the next V2G-event.
*/
static enum v2g_event handle_din_session_setup(struct v2g_connection* conn) {
enum v2g_event handle_din_session_setup(struct v2g_connection* conn) {
struct din_SessionSetupReqType* req = &conn->exi_in.dinEXIDocument->V2G_Message.Body.SessionSetupReq;
struct din_SessionSetupResType* res = &conn->exi_out.dinEXIDocument->V2G_Message.Body.SessionSetupRes;
enum v2g_event nextEvent = V2G_EVENT_NO_EVENT;
Expand Down Expand Up @@ -348,7 +351,7 @@ static enum v2g_event handle_din_session_setup(struct v2g_connection* conn) {
res->DateTimeNow = time(NULL);

/* Check the current response code and check if no external error has occurred */
nextEvent = din_validate_response_code(&res->ResponseCode, conn);
nextEvent = utils::din_validate_response_code(&res->ResponseCode, conn);

/* Set next expected req msg */
conn->ctx->state = WAIT_FOR_SERVICEDISCOVERY; // [V2G-DC-438]
Expand All @@ -363,7 +366,7 @@ static enum v2g_event handle_din_session_setup(struct v2g_connection* conn) {
* \param conn is the structure with the V2G msg pair.
* \return Returns the next V2G-event.
*/
static enum v2g_event handle_din_service_discovery(struct v2g_connection* conn) {
enum v2g_event handle_din_service_discovery(struct v2g_connection* conn) {
struct din_ServiceDiscoveryReqType* req = &conn->exi_in.dinEXIDocument->V2G_Message.Body.ServiceDiscoveryReq;
struct din_ServiceDiscoveryResType* res = &conn->exi_out.dinEXIDocument->V2G_Message.Body.ServiceDiscoveryRes;
enum v2g_event nextEvent = V2G_EVENT_NO_EVENT;
Expand Down Expand Up @@ -401,14 +404,16 @@ static enum v2g_event handle_din_service_discovery(struct v2g_connection* conn)
res->PaymentOptions.PaymentOption.arrayLen = 1;

/* Check the current response code and check if no external error has occurred */
nextEvent = din_validate_response_code(&res->ResponseCode, conn);
nextEvent = utils::din_validate_response_code(&res->ResponseCode, conn);

/* Set next expected req msg */
conn->ctx->state = WAIT_FOR_PAYMENTSERVICESELECTION; // [V2G-DC-441]

return nextEvent;
}

} // namespace states

/*!
* \brief handle_din_service_discovery This function handles the din service payment selection msg pair. It analyzes the
* request msg and fills the response msg. The request and response msg based on the open V2G structures. This
Expand Down Expand Up @@ -441,7 +446,7 @@ static enum v2g_event handle_din_service_payment_selection(struct v2g_connection
// shall be limited to 1)

/* Check the current response code and check if no external error has occurred */
nextEvent = din_validate_response_code(&res->ResponseCode, conn);
nextEvent = utils::din_validate_response_code(&res->ResponseCode, conn);

/* Set next expected req msg */
conn->ctx->state = WAIT_FOR_AUTHORIZATION; // [V2G-DC-444]
Expand All @@ -456,7 +461,7 @@ static enum v2g_event handle_din_service_payment_selection(struct v2g_connection
* \param conn is the structure with the V2G msg pair.
* \return Returns the next V2G-event.
*/
static enum v2g_event handle_din_contract_authentication(struct v2g_connection* conn) {
enum v2g_event states::handle_din_contract_authentication(struct v2g_connection* conn) {
struct din_ContractAuthenticationResType* res =
&conn->exi_out.dinEXIDocument->V2G_Message.Body.ContractAuthenticationRes;
enum v2g_event nextEvent = V2G_EVENT_NO_EVENT;
Expand All @@ -468,7 +473,7 @@ static enum v2g_event handle_din_contract_authentication(struct v2g_connection*
: din_EVSEProcessingType_Ongoing;

/* Check the current response code and check if no external error has occurred */
nextEvent = din_validate_response_code(&res->ResponseCode, conn);
nextEvent = utils::din_validate_response_code(&res->ResponseCode, conn);

/* Set next expected req msg */
conn->ctx->state = (res->EVSEProcessing == din_EVSEProcessingType_Ongoing)
Expand Down Expand Up @@ -600,7 +605,7 @@ static enum v2g_event handle_din_charge_parameter(struct v2g_connection* conn) {
res->SASchedules_isUsed = (unsigned int)0;

/* Check the current response code and check if no external error has occurred */
nextEvent = din_validate_response_code(&res->ResponseCode, conn);
nextEvent = utils::din_validate_response_code(&res->ResponseCode, conn);

/* Set next expected req msg */
if (res->EVSEProcessing == din_EVSEProcessingType_Finished) {
Expand Down Expand Up @@ -684,7 +689,7 @@ static enum v2g_event handle_din_power_delivery(struct v2g_connection* conn) {
: res->ResponseCode; // [V2G-DC-401]

/* Check the current response code and check if no external error has occurred */
nextEvent = din_validate_response_code(&res->ResponseCode, conn);
nextEvent = utils::din_validate_response_code(&res->ResponseCode, conn);

/* Set next expected req msg */
if ((req->ReadyToChargeState == (int)1) && (V2G_CURRENT_DEMAND_MSG != conn->ctx->last_v2g_msg)) {
Expand Down Expand Up @@ -740,7 +745,7 @@ static enum v2g_event handle_din_cable_check(struct v2g_connection* conn) {
}

/* Check the current response code and check if no external error has occurred */
nextEvent = din_validate_response_code(&res->ResponseCode, conn);
nextEvent = utils::din_validate_response_code(&res->ResponseCode, conn);

/* Set next expected req msg */
if ((res->EVSEProcessing == din_EVSEProcessingType_Finished) &&
Expand Down Expand Up @@ -794,7 +799,7 @@ static enum v2g_event handle_din_pre_charge(struct v2g_connection* conn) {
load_din_physical_value(&res->EVSEPresentVoltage, &conn->ctx->evse_v2g_data.evse_present_voltage);

/* Check the current response code and check if no external error has occurred */
nextEvent = din_validate_response_code(&res->ResponseCode, conn);
nextEvent = utils::din_validate_response_code(&res->ResponseCode, conn);

/* Set next expected req msg */
conn->ctx->state = WAIT_FOR_PRECHARGE_POWERDELIVERY; // [V2G-DC-458]
Expand Down Expand Up @@ -848,7 +853,7 @@ static enum v2g_event handle_din_current_demand(struct v2g_connection* conn) {
res->EVSEVoltageLimitAchieved = conn->ctx->evse_v2g_data.evse_voltage_limit_achieved;

/* Check the current response code and check if no external error has occurred */
nextEvent = din_validate_response_code(&res->ResponseCode, conn);
nextEvent = utils::din_validate_response_code(&res->ResponseCode, conn);

/* Set next expected req msg */
conn->ctx->state = WAIT_FOR_CURRENTDEMAND_POWERDELIVERY; // [V2G-DC-465]
Expand Down Expand Up @@ -888,7 +893,7 @@ static enum v2g_event handle_din_welding_detection(struct v2g_connection* conn)
load_din_physical_value(&res->EVSEPresentVoltage, &conn->ctx->evse_v2g_data.evse_present_voltage);

/* Check the current response code and check if no external error has occurred */
nextEvent = din_validate_response_code(&res->ResponseCode, conn);
nextEvent = utils::din_validate_response_code(&res->ResponseCode, conn);

/* Set next expected req msg */
conn->ctx->state = WAIT_FOR_WELDINGDETECTION_SESSIONSTOP; // [V2G-DC-469]
Expand All @@ -910,7 +915,7 @@ static enum v2g_event handle_din_session_stop(struct v2g_connection* conn) {
res->ResponseCode = din_responseCodeType_OK; // [V2G-DC-388]

/* Check the current response code and check if no external error has occurred */
din_validate_response_code(&res->ResponseCode, conn);
utils::din_validate_response_code(&res->ResponseCode, conn);

/* Setuo dlink action */
conn->dlink_action = MQTT_DLINK_ACTION_TERMINATE;
Expand All @@ -923,6 +928,8 @@ static enum v2g_event handle_din_session_stop(struct v2g_connection* conn) {
}

enum v2g_event din_handle_request(v2g_connection* conn) {
using namespace states;

struct din_exiDocument* exi_in = conn->exi_in.dinEXIDocument;
struct din_exiDocument* exi_out = conn->exi_out.dinEXIDocument;
enum v2g_event next_v2g_event = V2G_EVENT_TERMINATE_CONNECTION; // ERROR_UNEXPECTED_REQUEST_MESSAGE;
Expand Down
13 changes: 13 additions & 0 deletions modules/EvseV2G/din_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,17 @@ static const struct din_state din_states[] = {
*/
enum v2g_event din_handle_request(v2g_connection* conn);

namespace utils {
enum v2g_event din_validate_response_code(din_responseCodeType* const din_response_code,
struct v2g_connection const* conn);
} // namespace utils

namespace states {

enum v2g_event handle_din_session_setup(struct v2g_connection* conn);
enum v2g_event handle_din_service_discovery(struct v2g_connection* conn);
enum v2g_event handle_din_contract_authentication(struct v2g_connection* conn);

} // namespace states

#endif /* DIN_SERVER_HPP */
15 changes: 2 additions & 13 deletions modules/EvseV2G/sdp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,6 @@

#define POLL_TIMEOUT 20

enum sdp_security {
SDP_SECURITY_TLS = 0x00,
SDP_SECURITY_NONE = 0x10,
};

enum sdp_transport_protocol {
SDP_TRANSPORT_PROTOCOL_TCP = 0x00,
SDP_TRANSPORT_PROTOCOL_UDP = 0x10,
};

/* link-local multicast address ff02::1 aka ip6-allnodes */
#define IN6ADDR_ALLNODES \
{ 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 }
Expand All @@ -63,7 +53,7 @@ struct sdp_query {
/*
* Fills the SDP header into a given buffer
*/
static int sdp_write_header(uint8_t* buffer, uint16_t payload_type, uint32_t payload_len) {
int sdp_write_header(uint8_t* buffer, uint16_t payload_type, uint32_t payload_len) {
int offset = 0;

buffer[offset++] = SDP_VERSION;
Expand All @@ -82,7 +72,7 @@ static int sdp_write_header(uint8_t* buffer, uint16_t payload_type, uint32_t pay
return offset;
}

static int sdp_validate_header(uint8_t* buffer, uint16_t expected_payload_type, uint32_t expected_payload_len) {
int sdp_validate_header(uint8_t* buffer, uint16_t expected_payload_type, uint32_t expected_payload_len) {
uint16_t payload_type;
uint32_t payload_len;

Expand Down Expand Up @@ -134,7 +124,6 @@ int sdp_create_response(uint8_t* buffer, struct sockaddr_in6* addr, enum sdp_sec

return offset;
}

/*
* Sends a SDP response packet
*/
Expand Down
14 changes: 14 additions & 0 deletions modules/EvseV2G/sdp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@

#include "v2g.hpp"

enum sdp_security {
SDP_SECURITY_TLS = 0x00,
SDP_SECURITY_NONE = 0x10,
};

enum sdp_transport_protocol {
SDP_TRANSPORT_PROTOCOL_TCP = 0x00,
SDP_TRANSPORT_PROTOCOL_UDP = 0x10,
};

int sdp_write_header(uint8_t* buffer, uint16_t payload_type, uint32_t payload_len);
int sdp_validate_header(uint8_t* buffer, uint16_t expected_payload_type, uint32_t expected_payload_len);
int sdp_create_response(uint8_t* buffer, struct sockaddr_in6* addr, enum sdp_security security,
enum sdp_transport_protocol proto);
int sdp_init(struct v2g_context* v2g_ctx);
int sdp_listen(struct v2g_context* v2g_ctx);

Expand Down
109 changes: 109 additions & 0 deletions modules/EvseV2G/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
get_target_property(GENERATED_INCLUDE_DIR generate_cpp_files EVEREST_GENERATED_INCLUDE_DIR)
find_package(libevent)
find_package(OpenSSL 3)

set(TLS_TEST_FILES
alt_openssl-pki.conf
Expand Down Expand Up @@ -93,3 +94,111 @@ target_link_libraries(${V2G_MAIN_NAME} PRIVATE
# runs fine locally, fails in CI
add_test(${TLS_GTEST_NAME} ${TLS_GTEST_NAME})
ev_register_test_target(${TLS_GTEST_NAME})


set(DIN_SERVER_NAME din_server_test)
add_executable(${DIN_SERVER_NAME})

target_include_directories(${DIN_SERVER_NAME} PRIVATE
.. ../connection ../../../tests/include
${GENERATED_INCLUDE_DIR}
${CMAKE_BINARY_DIR}/generated/modules/${MODULE_NAME}
${CMAKE_BINARY_DIR}/generated/include
)

target_compile_definitions(${DIN_SERVER_NAME} PRIVATE
-DUNIT_TEST
-DLIBEVSE_CRYPTO_SUPPLIER_OPENSSL
)

target_sources(${DIN_SERVER_NAME} PRIVATE
din_server_test.cpp
log.cpp
../din_server.cpp
../tools.cpp # TODO: Maybe mock this one
)

target_link_libraries(${DIN_SERVER_NAME}
PRIVATE
GTest::gtest_main
OpenSSL::SSL
OpenSSL::Crypto
cbv2g::din
cbv2g::iso2
cbv2g::tp
everest::framework
everest::evse_security
everest::tls
)

add_test(${DIN_SERVER_NAME} ${DIN_SERVER_NAME})
ev_register_test_target(${DIN_SERVER_NAME})

set(SDP_NAME sdp_test)
add_executable(${SDP_NAME})
target_include_directories(${SDP_NAME} PRIVATE
.. ../connection ../../../tests/include
${GENERATED_INCLUDE_DIR}
${CMAKE_BINARY_DIR}/generated/modules/${MODULE_NAME}
${CMAKE_BINARY_DIR}/generated/include
)

target_compile_definitions(${SDP_NAME} PRIVATE
-DUNIT_TEST
)

target_sources(${SDP_NAME} PRIVATE
sdp_test.cpp
log.cpp
../sdp.cpp
)

target_link_libraries(${SDP_NAME}
PRIVATE
GTest::gtest_main
cbv2g::tp
everest::framework
everest::tls
)

add_test(${SDP_NAME} ${SDP_NAME})
ev_register_test_target(${SDP_NAME})

set(V2GCTX_NAME v2g_ctx_test)
add_executable(${V2GCTX_NAME})

target_include_directories(${V2GCTX_NAME} PRIVATE
.. ../connection ../../../tests/include
${GENERATED_INCLUDE_DIR}
${CMAKE_BINARY_DIR}/generated/modules/${MODULE_NAME}
${CMAKE_BINARY_DIR}/generated/include
)

target_compile_definitions(${V2GCTX_NAME} PRIVATE
-DUNIT_TEST
-DLIBEVSE_CRYPTO_SUPPLIER_OPENSSL
)

target_sources(${V2GCTX_NAME} PRIVATE
v2g_ctx_test.cpp
log.cpp
../v2g_ctx.cpp
../tools.cpp # TODO: Maybe mock this one
)

target_link_libraries(${V2GCTX_NAME}
PRIVATE
GTest::gtest_main
OpenSSL::SSL
OpenSSL::Crypto
cbv2g::din
cbv2g::iso2
cbv2g::tp
everest::framework
everest::evse_security
everest::tls
-levent -lpthread -levent_pthreads
)

add_test(${V2GCTX_NAME} ${V2GCTX_NAME})
ev_register_test_target(${V2GCTX_NAME})
Loading