Skip to content

Commit

Permalink
Tests and fixes for PSMX interface
Browse files Browse the repository at this point in the history
This adds some tests verifying that the configuration, API and PSMX interface are aligned.

It fixes the initialization code to reject a configuration that defines multiple plugins.

Signed-off-by: Michel van den Hoek <[email protected]>
  • Loading branch information
mvandenhoek authored Jul 15, 2024
1 parent ce7cf3d commit f5e5d6c
Show file tree
Hide file tree
Showing 7 changed files with 747 additions and 47 deletions.
44 changes: 18 additions & 26 deletions src/core/ddsc/src/dds_psmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,40 +327,32 @@ static dds_return_t psmx_instance_load (const struct ddsi_domaingv *gv, const st
return ret;
}

static int compare_psmx_prio (const void *va, const void *vb)
{
const struct dds_psmx *psmx1 = va;
const struct dds_psmx *psmx2 = vb;
return (psmx1->priority == psmx2->priority) ? 0 : ((psmx1->priority < psmx2->priority) ? 1 : -1);
}

dds_return_t dds_pubsub_message_exchange_init (const struct ddsi_domaingv *gv, struct dds_domain *domain)
{
dds_return_t ret = DDS_RETCODE_OK;
if (gv->config.psmx_instances != NULL)
{
struct ddsi_config_psmx_listelem *iface = gv->config.psmx_instances;
while (iface && domain->psmx_instances.length < DDS_MAX_PSMX_INSTANCES)
{
GVLOG(DDS_LC_INFO, "Loading PSMX instances %s\n", iface->cfg.name);
struct dds_psmx *psmx = NULL;
ddsrt_dynlib_t lib_handle;
if (psmx_instance_load (gv, &iface->cfg, &psmx, &lib_handle) == DDS_RETCODE_OK)
{
domain->psmx_instances.instances[domain->psmx_instances.length] = psmx;
domain->psmx_instances.lib_handles[domain->psmx_instances.length] = lib_handle;
domain->psmx_instances.length++;
}
else
{
GVERROR ("error loading PSMX instance \"%s\"\n", iface->cfg.name);
ret = DDS_RETCODE_ERROR;
break;
if ( iface != NULL ) {
if ( iface->next != NULL ) {
ret = DDS_RETCODE_UNSUPPORTED; // Only one psmx interface is supported.
}else{
GVLOG(DDS_LC_INFO, "Loading PSMX instances %s\n", iface->cfg.name);
struct dds_psmx *psmx = NULL;
ddsrt_dynlib_t lib_handle;
if (psmx_instance_load (gv, &iface->cfg, &psmx, &lib_handle) == DDS_RETCODE_OK)
{
domain->psmx_instances.instances[domain->psmx_instances.length] = psmx;
domain->psmx_instances.lib_handles[domain->psmx_instances.length] = lib_handle;
domain->psmx_instances.length++;
}
else
{
GVERROR ("error loading PSMX instance \"%s\"\n", iface->cfg.name);
ret = DDS_RETCODE_ERROR;
}
}
iface = iface->next;
}

qsort (domain->psmx_instances.instances, domain->psmx_instances.length, sizeof (*domain->psmx_instances.instances), compare_psmx_prio);
}
return ret;
}
Expand Down
40 changes: 35 additions & 5 deletions src/core/ddsc/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ set(ddsc_test_sources
"nwpart.c"
"participant.c"
"pp_lease_dur.c"
"psmxif.c"
"publisher.c"
"qos.c"
"qosmatch.c"
Expand Down Expand Up @@ -157,10 +158,43 @@ if(ENABLE_QOS_PROVIDER)
"qos_provider.c")
endif()

# PSMX dummy implementation for interface testing
if(BUILD_SHARED_LIBS)
add_library(psmx_dummy SHARED "psmx_dummy_impl.c")
else()
add_library(psmx_dummy OBJECT "psmx_dummy_impl.c")
set_property(GLOBAL APPEND PROPERTY cdds_plugin_list psmx_dummy)
set_property(GLOBAL PROPERTY psmx_dummy_symbols dummy_create_psmx)
endif()
generate_export_header(psmx_dummy BASE_NAME PSMX_DUMMY EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/psmx_dummy/export.h")
target_include_directories(
psmx_dummy PRIVATE
"$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/src/ddsrt/include>"
"$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/src/core/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/src/core/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../../ddsrt/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../ddsc/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../ddsi/include>"
)
if(BUILD_SHARED_LIBS)
target_link_libraries(psmx_dummy PRIVATE ddsc)
else()
install(
TARGETS psmx_dummy
EXPORT "${PROJECT_NAME}"
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
endif()


add_cunit_executable(cunit_ddsc ${ddsc_test_sources})
target_include_directories(
cunit_ddsc PRIVATE
"$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/src/include/>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../ddsc/src>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../ddsi/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../ddsi/src>"
Expand All @@ -181,6 +215,7 @@ target_link_libraries(cunit_ddsc PRIVATE
CdrStreamSkipDefault
CdrStreamDataTypeInfo
PsmxDataModels
psmx_dummy
DynamicData
Array100
CdrStreamKeySize
Expand Down Expand Up @@ -243,7 +278,6 @@ target_include_directories(

target_link_libraries(oneliner PRIVATE RoundTrip Space ddsc)


# PSMX implementation with Cyclone as transport, for testing
if (BUILD_SHARED_LIBS)
idlc_generate(TARGET psmx_cdds_data FILES psmx_cdds_data.idl)
Expand All @@ -258,10 +292,6 @@ if (BUILD_SHARED_LIBS)
target_link_libraries(psmx_cdds PRIVATE ddsc psmx_cdds_data)

generate_export_header(psmx_cdds BASE_NAME PSMX_CDDS EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/psmx_cdds/export.h")

install(TARGETS psmx_cdds
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
endif()

# If Iceoryx is available, then also run all PSMX tests using Iceoryx. Colcon complicates
Expand Down
49 changes: 33 additions & 16 deletions src/core/ddsc/tests/psmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,22 +113,13 @@ static bool endpoint_has_psmx_enabled (dds_entity_t rd_or_wr)
bool psmx_enabled = false;
rc = dds_entity_pin (rd_or_wr, &x);
CU_ASSERT_FATAL (rc == DDS_RETCODE_OK);
switch (dds_entity_kind (x))
{
case DDS_KIND_READER: {
struct dds_reader const * const rd = (struct dds_reader *) x;
psmx_enabled = (rd->m_endpoint.psmx_endpoints.length > 0);
break;
}
case DDS_KIND_WRITER: {
struct dds_writer const * const wr = (struct dds_writer *) x;
psmx_enabled = (wr->m_endpoint.psmx_endpoints.length > 0);
break;
}
default: {
CU_ASSERT_FATAL (dds_entity_kind (x) == DDS_KIND_READER || dds_entity_kind (x) == DDS_KIND_WRITER);
break;
}
if ( dds_entity_kind (x) == DDS_KIND_READER ) {
struct dds_reader const * const rd = (struct dds_reader *) x;
psmx_enabled = (rd->m_endpoint.psmx_endpoints.length > 0);
} else {
CU_ASSERT_FATAL(dds_entity_kind (x) == DDS_KIND_WRITER);
struct dds_writer const * const wr = (struct dds_writer *) x;
psmx_enabled = (wr->m_endpoint.psmx_endpoints.length > 0);
}
dds_entity_unpin (x);
return psmx_enabled;
Expand Down Expand Up @@ -1208,6 +1199,32 @@ CU_Test(ddsc_psmx, partition_xtalk)
CU_ASSERT_FATAL (rc == 0);
}

/// @brief Check that shared memory is not supported by endpoints created from a default Cyclone domain.
/// @methodology
/// - Create endpoints with a from a default domain.
/// - Assert that shared memory is not available.
CU_Test(ddsc_psmx, no_shared_memory)
{
dds_entity_t participant, topic, writer, reader;

participant = dds_create_participant(0, NULL, NULL);
CU_ASSERT_FATAL(participant > 0);

char topicname[100];
create_unique_topic_name("test_psmx_no_shared_memory", topicname, sizeof(topicname));
topic = dds_create_topic(participant, &SC_Model_desc, topicname, NULL, NULL);
CU_ASSERT_FATAL(topic > 0);

writer = dds_create_writer(participant, topic, NULL, NULL);
CU_ASSERT_FATAL(writer > 0);

reader = dds_create_reader(participant, topic, NULL, NULL);
CU_ASSERT_FATAL(reader > 0);

CU_ASSERT_FATAL(!dds_is_shared_memory_available(writer));
CU_ASSERT_FATAL(!dds_is_shared_memory_available(reader));
dds_delete(dds_get_parent(participant));
}

#define MAX_SAMPLES 8
CU_Test (ddsc_psmx, basic)
Expand Down
Loading

0 comments on commit f5e5d6c

Please sign in to comment.