diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 394b7e4..701f50d 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -94,7 +94,6 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, rd->m_loan = buf[0]; rd->m_loan_size = maxs; } - nodata_cleanups = NC_RESET_BUF; } else { @@ -103,7 +102,7 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, rd->m_loan_size = maxs; } rd->m_loan_out = true; - nodata_cleanups |= NC_CLEAR_LOAN_OUT; + nodata_cleanups = NC_RESET_BUF | NC_CLEAR_LOAN_OUT; } ddsrt_mutex_unlock (&rd->m_entity.m_mutex); } @@ -457,12 +456,11 @@ dds_return_t dds_take_next_wl (dds_entity_t reader, void **buf, dds_sample_info_ dds_return_t dds_return_loan (dds_entity_t reader_or_condition, void **buf, int32_t bufsz) { - const struct ddsi_sertopic *st; dds_reader *rd; dds_entity *entity; - dds_return_t ret = DDS_RETCODE_OK; + dds_return_t ret; - if (buf == NULL || (*buf == NULL && bufsz > 0)) + if (buf == NULL || (buf[0] == NULL && bufsz > 0) || (buf[0] != NULL && bufsz <= 0)) return DDS_RETCODE_BAD_PARAMETER; if ((ret = dds_entity_pin (reader_or_condition, &entity)) < 0) { @@ -476,16 +474,46 @@ dds_return_t dds_return_loan (dds_entity_t reader_or_condition, void **buf, int3 rd = (dds_reader *) entity->m_parent; } - st = rd->m_topic->m_stopic; - for (int32_t i = 0; i < bufsz; i++) - ddsi_sertopic_free_sample (st, buf[i], DDS_FREE_CONTENTS); - - /* If possible return loan buffer to reader */ - ddsrt_mutex_lock (&rd->m_entity.m_mutex); - if (rd->m_loan != 0 && (buf[0] == rd->m_loan)) + if (bufsz <= 0) { - rd->m_loan_out = false; + /* No data whatsoever, or an invocation following a failed read/take call. Read/take + already take care of restoring the state prior to their invocation if they return + no data. Return late so invalid handles can be detected. */ + dds_entity_unpin (entity); + return DDS_RETCODE_OK; + } + assert (buf[0] != NULL); + + const struct ddsi_sertopic *st = rd->m_topic->m_stopic; + + /* The potentially time consuming part of what happens here (freeing samples) + can safely be done without holding the reader lock, but that particular + lock is not used during insertion of data & triggering waitsets (that's + the observer_lock), so holding it for a bit longer in return for simpler + code is a fair trade-off. */ + ddsrt_mutex_lock (&rd->m_entity.m_mutex); + if (buf[0] != rd->m_loan) + { + /* Not so much a loan as a buffer allocated by the middleware on behalf of the + application. So it really is no more than a sophisticated variant of "free". */ + ddsi_sertopic_free_samples (st, buf, (size_t) bufsz, DDS_FREE_ALL); + buf[0] = NULL; + } + else if (!rd->m_loan_out) + { + /* Trying to return a loan that has been returned already */ + ddsrt_mutex_unlock (&rd->m_entity.m_mutex); + dds_entity_unpin (entity); + return DDS_RETCODE_PRECONDITION_NOT_MET; + } + else + { + /* Free only the memory referenced from the samples, not the samples themselves. + Zero them to guarantee the absence of dangling pointers that might cause + trouble on a following operation. FIXME: there's got to be a better way */ + ddsi_sertopic_free_samples (st, buf, (size_t) bufsz, DDS_FREE_CONTENTS); ddsi_sertopic_zero_samples (st, rd->m_loan, rd->m_loan_size); + rd->m_loan_out = false; buf[0] = NULL; } ddsrt_mutex_unlock (&rd->m_entity.m_mutex); diff --git a/src/core/ddsc/tests/CMakeLists.txt b/src/core/ddsc/tests/CMakeLists.txt index 4a234eb..2dac5e3 100644 --- a/src/core/ddsc/tests/CMakeLists.txt +++ b/src/core/ddsc/tests/CMakeLists.txt @@ -30,6 +30,7 @@ set(ddsc_test_sources "instance_get_key.c" "listener.c" "liveliness.c" + "loan.c" "multi_sertopic.c" "participant.c" "publisher.c" @@ -41,7 +42,6 @@ set(ddsc_test_sources "reader_iterator.c" "read_instance.c" "register.c" - "return_loan.c" "subscriber.c" "take_instance.c" "time.c" @@ -55,7 +55,9 @@ set(ddsc_test_sources "whc.c" "write.c" "write_various_types.c" - "writer.c") + "writer.c" + "test_common.c" + "test_common.h") if(ENABLE_LIFESPAN) list(APPEND ddsc_test_sources "lifespan.c") diff --git a/src/core/ddsc/tests/basic.c b/src/core/ddsc/tests/basic.c index b2bb597..d08b5b6 100644 --- a/src/core/ddsc/tests/basic.c +++ b/src/core/ddsc/tests/basic.c @@ -10,7 +10,7 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include "dds/dds.h" -#include "CUnit/Test.h" +#include "test_common.h" CU_Test(ddsc_basic, test) { diff --git a/src/core/ddsc/tests/builtin_topics.c b/src/core/ddsc/tests/builtin_topics.c index 747b1d2..3c511fd 100644 --- a/src/core/ddsc/tests/builtin_topics.c +++ b/src/core/ddsc/tests/builtin_topics.c @@ -10,10 +10,7 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include "dds/dds.h" -#include "RoundTrip.h" -#include "Space.h" -#include "test-common.h" -#include "CUnit/Test.h" +#include "test_common.h" static dds_entity_t g_participant = 0; static dds_entity_t g_subscriber = 0; @@ -336,7 +333,7 @@ CU_Test(ddsc_builtin_topics, read_nothing) CU_ASSERT_FATAL (ret == 0); ret = dds_return_loan (rd, &raw2, n2); CU_ASSERT_FATAL (ret == 0); - + ret = dds_delete (pp); CU_ASSERT_FATAL (ret == 0); } diff --git a/src/core/ddsc/tests/config.c b/src/core/ddsc/tests/config.c index 159a4ac..bb8f234 100644 --- a/src/core/ddsc/tests/config.c +++ b/src/core/ddsc/tests/config.c @@ -12,7 +12,6 @@ #include #include "dds/dds.h" -#include "CUnit/Test.h" #include "config_env.h" #include "dds/version.h" @@ -22,6 +21,8 @@ #include "dds/ddsi/q_misc.h" #include "dds/ddsi/ddsi_xqos.h" +#include "test_common.h" + #define FORCE_ENV #define URI_VARIABLE DDS_PROJECT_NAME_NOSPACE_CAPS"_URI" diff --git a/src/core/ddsc/tests/deadline.c b/src/core/ddsc/tests/deadline.c index 818847a..e10bd74 100644 --- a/src/core/ddsc/tests/deadline.c +++ b/src/core/ddsc/tests/deadline.c @@ -13,9 +13,6 @@ #include #include "dds/dds.h" -#include "CUnit/Theory.h" -#include "Space.h" - #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" #include "dds/ddsrt/environ.h" @@ -24,6 +21,8 @@ #include "dds/ddsi/q_whc.h" #include "dds__entity.h" +#include "test_common.h" + #define MAX_RUNS 4 #define WRITER_DEADLINE DDS_MSECS(50) @@ -42,15 +41,6 @@ static dds_entity_t g_remote_participant = 0; static dds_entity_t g_remote_subscriber = 0; static dds_entity_t g_remote_topic = 0; - -static char * create_topic_name(const char *prefix, char *name, size_t size) -{ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} - static void sync_reader_writer(dds_entity_t participant, dds_entity_t reader, dds_entity_t writer) { dds_attach_t triggered; @@ -126,7 +116,7 @@ static void deadline_init(void) g_publisher = dds_create_publisher(g_participant, NULL, NULL); CU_ASSERT_FATAL(g_publisher > 0); - create_topic_name("ddsc_qos_deadline_test", name, sizeof name); + create_unique_topic_name("ddsc_qos_deadline_test", name, sizeof name); g_topic = dds_create_topic(g_participant, &Space_Type1_desc, name, NULL, NULL); CU_ASSERT_FATAL(g_topic > 0); g_remote_topic = dds_create_topic(g_remote_participant, &Space_Type1_desc, name, NULL, NULL); diff --git a/src/core/ddsc/tests/dispose.c b/src/core/ddsc/tests/dispose.c index ef6435f..b0a0dc4 100644 --- a/src/core/ddsc/tests/dispose.c +++ b/src/core/ddsc/tests/dispose.c @@ -12,13 +12,12 @@ #include #include "dds/dds.h" -#include "CUnit/Theory.h" -#include "Space.h" - #include "dds/ddsrt/misc.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" +#include "test_common.h" + /************************************************************************************************** * * Test fixtures @@ -41,16 +40,6 @@ static void* g_samples[MAX_SAMPLES]; static Space_Type1 g_data[MAX_SAMPLES]; static dds_sample_info_t g_info[MAX_SAMPLES]; -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} - static void disposing_init(void) { @@ -69,7 +58,7 @@ disposing_init(void) g_waitset = dds_create_waitset(g_participant); CU_ASSERT_FATAL(g_waitset > 0); - g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_disposing_test", name, sizeof name), qos, NULL); + g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_unique_topic_name("ddsc_disposing_test", name, sizeof name), qos, NULL); CU_ASSERT_FATAL(g_topic > 0); /* Create a reader that keeps one sample on three instances. */ diff --git a/src/core/ddsc/tests/entity_hierarchy.c b/src/core/ddsc/tests/entity_hierarchy.c index 44d5917..851cadb 100644 --- a/src/core/ddsc/tests/entity_hierarchy.c +++ b/src/core/ddsc/tests/entity_hierarchy.c @@ -12,14 +12,12 @@ #include #include "dds/dds.h" -#include "CUnit/Test.h" -#include "CUnit/Theory.h" -#include "RoundTrip.h" - #include "dds/ddsrt/misc.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" +#include "test_common.h" + /************************************************************************************************** * * Test fixtures @@ -44,16 +42,6 @@ accept_all(const void * sample) return true; } -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} - static void hierarchy_init(void) { @@ -63,7 +51,7 @@ hierarchy_init(void) g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(g_participant > 0 ); - g_topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_hierarchy_test", name, sizeof name), NULL, NULL); + g_topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, create_unique_topic_name("ddsc_hierarchy_test", name, sizeof name), NULL, NULL); CU_ASSERT_FATAL(g_topic > 0); g_publisher = dds_create_publisher(g_participant, NULL, NULL); @@ -179,7 +167,7 @@ CU_Test(ddsc_entity_delete, recursive_with_deleted_topic) /* First, create a topic and a writer with that topic. */ g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(g_participant > 0); - g_topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_hierarchy_test", name, 100), NULL, NULL); + g_topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, create_unique_topic_name("ddsc_hierarchy_test", name, 100), NULL, NULL); CU_ASSERT_FATAL(g_topic > 0); g_writer = dds_create_writer(g_participant, g_topic, NULL, NULL); CU_ASSERT_FATAL(g_writer> 0); @@ -747,7 +735,7 @@ CU_Test(ddsc_entity_implicit_publisher, deleted) participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); - topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_publisher_test", name, 100), NULL, NULL); + topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_unique_topic_name("ddsc_entity_implicit_publisher_test", name, 100), NULL, NULL); CU_ASSERT_FATAL(topic > 0); writer = dds_create_writer(participant, topic, NULL, NULL); @@ -799,7 +787,7 @@ CU_Test(ddsc_entity_implicit_subscriber, deleted) participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); - topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_subscriber_test", name, 100), NULL, NULL); + topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_unique_topic_name("ddsc_entity_implicit_subscriber_test", name, 100), NULL, NULL); CU_ASSERT_FATAL(topic > 0); reader = dds_create_reader(participant, topic, NULL, NULL); @@ -854,7 +842,7 @@ CU_Test(ddsc_entity_get_children, implicit_publisher) participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); - topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_publisher_test", name, 100), NULL, NULL); + topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_unique_topic_name("ddsc_entity_implicit_publisher_test", name, 100), NULL, NULL); CU_ASSERT_FATAL(topic > 0); writer = dds_create_writer(participant, topic, NULL, NULL); @@ -898,7 +886,7 @@ CU_Test(ddsc_entity_get_children, implicit_subscriber) participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); - topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_subscriber_test", name, 100), NULL, NULL); + topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_unique_topic_name("ddsc_entity_implicit_subscriber_test", name, 100), NULL, NULL); CU_ASSERT_FATAL(topic > 0); reader = dds_create_reader(participant, topic, NULL, NULL); @@ -942,7 +930,7 @@ CU_Test(ddsc_entity_get_parent, implicit_publisher) participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); - topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_publisher_promotion_test", name, 100), NULL, NULL); + topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_unique_topic_name("ddsc_entity_implicit_publisher_promotion_test", name, 100), NULL, NULL); CU_ASSERT_FATAL(topic > 0); writer = dds_create_writer(participant, topic, NULL, NULL); @@ -973,7 +961,7 @@ CU_Test(ddsc_entity_get_parent, implicit_subscriber) participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); - topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_subscriber_promotion_test", name, 100), NULL, NULL); + topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_unique_topic_name("ddsc_entity_implicit_subscriber_promotion_test", name, 100), NULL, NULL); CU_ASSERT_FATAL(topic > 0); reader = dds_create_reader(participant, topic, NULL, NULL); @@ -1005,7 +993,7 @@ CU_Test(ddsc_entity_implicit, delete_publisher) participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); - topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_delete_publisher", name, 100), NULL, NULL); + topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_unique_topic_name("ddsc_entity_implicit_delete_publisher", name, 100), NULL, NULL); CU_ASSERT_FATAL(topic > 0); writer = dds_create_writer(participant, topic, NULL, NULL); @@ -1037,7 +1025,7 @@ CU_Test(ddsc_entity_implicit, delete_subscriber) participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); - topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_delete_subscriber", name, 100), NULL, NULL); + topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_unique_topic_name("ddsc_entity_implicit_delete_subscriber", name, 100), NULL, NULL); CU_ASSERT_FATAL(topic > 0); reader = dds_create_reader(participant, topic, NULL, NULL); diff --git a/src/core/ddsc/tests/entity_status.c b/src/core/ddsc/tests/entity_status.c index 297f2cd..be14103 100644 --- a/src/core/ddsc/tests/entity_status.c +++ b/src/core/ddsc/tests/entity_status.c @@ -11,13 +11,13 @@ */ #include #include -#include "CUnit/Theory.h" -#include "dds/dds.h" -#include "RoundTrip.h" +#include "dds/dds.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" +#include "test_common.h" + /**************************************************************************** * Test globals. ****************************************************************************/ @@ -56,15 +56,6 @@ static dds_instance_handle_t writer_i_hdl = 0; /**************************************************************************** * Test initializations and teardowns. ****************************************************************************/ -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} static void init_entity_status(void) @@ -74,7 +65,7 @@ init_entity_status(void) participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT(participant > 0); - top = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_status_test", topicName, 100), NULL, NULL); + top = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_unique_topic_name("ddsc_status_test", topicName, 100), NULL, NULL); CU_ASSERT(top > 0); qos = dds_create_qos(); diff --git a/src/core/ddsc/tests/lifespan.c b/src/core/ddsc/tests/lifespan.c index fea4079..ff296c4 100644 --- a/src/core/ddsc/tests/lifespan.c +++ b/src/core/ddsc/tests/lifespan.c @@ -13,9 +13,6 @@ #include #include "dds/dds.h" -#include "CUnit/Theory.h" -#include "Space.h" - #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" #include "dds/ddsi/ddsi_entity_index.h" @@ -23,6 +20,8 @@ #include "dds/ddsi/q_whc.h" #include "dds__entity.h" +#include "test_common.h" + static dds_entity_t g_participant = 0; static dds_entity_t g_subscriber = 0; static dds_entity_t g_publisher = 0; @@ -33,16 +32,6 @@ static dds_entity_t g_waitset = 0; static dds_entity_t g_rcond = 0; static dds_entity_t g_qcond = 0; -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} - static void lifespan_init(void) { dds_attach_t triggered; @@ -65,7 +54,7 @@ static void lifespan_init(void) g_waitset = dds_create_waitset(g_participant); CU_ASSERT_FATAL(g_waitset > 0); - g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_qos_lifespan_test", name, sizeof name), NULL, NULL); + g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_unique_topic_name("ddsc_qos_lifespan_test", name, sizeof name), NULL, NULL); CU_ASSERT_FATAL(g_topic > 0); dds_qset_history(qos, DDS_HISTORY_KEEP_ALL, DDS_LENGTH_UNLIMITED); diff --git a/src/core/ddsc/tests/listener.c b/src/core/ddsc/tests/listener.c index 49a2915..1ad9f71 100644 --- a/src/core/ddsc/tests/listener.c +++ b/src/core/ddsc/tests/listener.c @@ -10,8 +10,6 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include "dds/dds.h" -#include "RoundTrip.h" -#include "CUnit/Test.h" #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/misc.h" @@ -19,6 +17,8 @@ #include "dds/ddsrt/sync.h" #include "dds/ddsrt/threads.h" +#include "test_common.h" + /**************************************************************************** * TODO: Add DDS_INCONSISTENT_TOPIC_STATUS test * TODO: Add DDS_OFFERED/REQUESTED_DEADLINE_MISSED_STATUS test @@ -311,15 +311,6 @@ waitfor_cb(uint32_t expected) /**************************************************************************** * Test initializations and teardowns. ****************************************************************************/ -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} static void init_triggering_base(void) @@ -340,7 +331,7 @@ init_triggering_base(void) g_publisher = dds_create_publisher(g_participant, NULL, NULL); CU_ASSERT_FATAL(g_publisher > 0); - g_topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_listener_test", name, 100), NULL, NULL); + g_topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, create_unique_topic_name("ddsc_listener_test", name, 100), NULL, NULL); CU_ASSERT_FATAL(g_topic > 0); g_listener = dds_create_listener(NULL); diff --git a/src/core/ddsc/tests/liveliness.c b/src/core/ddsc/tests/liveliness.c index 04cec98..cf3adab 100644 --- a/src/core/ddsc/tests/liveliness.c +++ b/src/core/ddsc/tests/liveliness.c @@ -13,8 +13,6 @@ #include #include "dds/dds.h" -#include "CUnit/Theory.h" -#include "Space.h" #include "config_env.h" #include "dds/version.h" @@ -29,12 +27,13 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/time.h" +#include "test_common.h" + #define DDS_DOMAINID_PUB 0 #define DDS_DOMAINID_SUB 1 #define DDS_CONFIG_NO_PORT_GAIN "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}0" #define DDS_CONFIG_NO_PORT_GAIN_LOG "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}cyclonedds_liveliness_tests.${CYCLONEDDS_DOMAIN_ID}.${CYCLONEDDS_PID}.logfinest0" -uint32_t g_topic_nr = 0; static dds_entity_t g_pub_domain = 0; static dds_entity_t g_pub_participant = 0; static dds_entity_t g_pub_publisher = 0; @@ -43,15 +42,6 @@ static dds_entity_t g_sub_domain = 0; static dds_entity_t g_sub_participant = 0; static dds_entity_t g_sub_subscriber = 0; -static char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size) -{ - /* Get unique g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void)snprintf(name, size, "%s%d_pid%" PRIdPID "_tid%" PRIdTID "", prefix, nr, pid, tid); - return name; -} - static void liveliness_init(void) { /* Domains for pub and sub use a different domain id, but the portgain setting @@ -179,7 +169,7 @@ static void test_pmd_count(dds_liveliness_kind_t kind, uint32_t ldur, double mul dds_sleepfor(DDS_MSECS(50)); /* topics */ - create_topic_name("ddsc_liveliness_pmd_count", g_topic_nr++, name, sizeof name); + create_unique_topic_name("ddsc_liveliness_pmd_count", name, sizeof name); CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); if (remote_reader) CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); @@ -272,7 +262,7 @@ static void test_expire_liveliness_kinds(uint32_t ldur, double mult, uint32_t wr ldur, mult, wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, remote_reader ? "remote" : "local"); /* topics */ - create_topic_name("ddsc_liveliness_expire_kinds", g_topic_nr++, name, sizeof name); + create_unique_topic_name("ddsc_liveliness_expire_kinds", name, sizeof name); CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); if (remote_reader) CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); @@ -428,7 +418,7 @@ CU_Test(ddsc_liveliness, lease_duration, .init = liveliness_init, .fini = liveli uint32_t n; /* topics */ - create_topic_name("ddsc_liveliness_ldur", g_topic_nr++, name, sizeof name); + create_unique_topic_name("ddsc_liveliness_ldur", name, sizeof name); CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); @@ -489,7 +479,7 @@ static void test_lease_duration_pwr(bool remote_reader) printf("running test lease_duration_pwr: %s reader\n", remote_reader ? "remote" : "local"); /* topics */ - create_topic_name("ddsc_liveliness_ldurpwr", g_topic_nr++, name, sizeof name); + create_unique_topic_name("ddsc_liveliness_ldurpwr", name, sizeof name); CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); if (remote_reader) CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); @@ -571,7 +561,7 @@ static void test_create_delete_writer_stress(bool remote_reader) printf("running test create_delete_writer_stress: %s reader\n", remote_reader ? "remote" : "local"); /* topics */ - create_topic_name("ddsc_liveliness_wr_stress", g_topic_nr++, name, sizeof name); + create_unique_topic_name("ddsc_liveliness_wr_stress", name, sizeof name); CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); if (remote_reader) CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); @@ -672,7 +662,7 @@ static void test_status_counts(bool remote_reader) printf("running test status_counts: %s reader\n", remote_reader ? "remote" : "local"); /* topics */ - create_topic_name("ddsc_liveliness_status_counts", g_topic_nr++, name, sizeof name); + create_unique_topic_name("ddsc_liveliness_status_counts", name, sizeof name); CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); if (remote_reader) CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); @@ -772,7 +762,7 @@ static void test_assert_liveliness(uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, wr_cnt_auto, wr_cnt_man_pp, wr_cnt_man_tp, ldur, remote_reader ? "remote" : "local"); /* topics */ - create_topic_name("ddsc_liveliness_assert", g_topic_nr++, name, sizeof name); + create_unique_topic_name("ddsc_liveliness_assert", name, sizeof name); CU_ASSERT_FATAL((pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); if (remote_reader) CU_ASSERT_FATAL((sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, NULL, NULL)) > 0); @@ -1018,7 +1008,7 @@ static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_livelines dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); dds_qset_history(qos, DDS_HISTORY_KEEP_ALL, 0); - create_topic_name("ddsc_liveliness_lease_duration_zero", g_topic_nr++, name, sizeof name); + create_unique_topic_name("ddsc_liveliness_lease_duration_zero", name, sizeof name); pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, qos, NULL); CU_ASSERT_FATAL(pub_topic > 0); if (remote_reader) diff --git a/src/core/ddsc/tests/loan.c b/src/core/ddsc/tests/loan.c new file mode 100644 index 0000000..5e12d84 --- /dev/null +++ b/src/core/ddsc/tests/loan.c @@ -0,0 +1,321 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include "dds/dds.h" +#include "test_common.h" + +static dds_entity_t participant, topic, reader, writer, read_condition, read_condition_unread; + +static void create_entities (void) +{ + char topicname[100]; + struct dds_qos *qos; + + create_unique_topic_name ("ddsc_return_loan_test", topicname, sizeof topicname); + participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); + CU_ASSERT_FATAL (participant > 0); + + qos = dds_create_qos (); + dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, 0); + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 1); + topic = dds_create_topic (participant, &RoundTripModule_DataType_desc, topicname, qos, NULL); + CU_ASSERT_FATAL (topic > 0); + dds_delete_qos (qos); + + 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); + read_condition = dds_create_readcondition (reader, DDS_ANY_STATE); + CU_ASSERT_FATAL (read_condition > 0); + read_condition_unread = dds_create_readcondition (reader, DDS_ANY_INSTANCE_STATE | DDS_ANY_VIEW_STATE | DDS_NOT_READ_SAMPLE_STATE); + CU_ASSERT_FATAL (read_condition > 0); +} + +static void delete_entities (void) +{ + dds_return_t result; + result = dds_delete (participant); + CU_ASSERT_FATAL (result == DDS_RETCODE_OK); +} + +CU_Test (ddsc_loan, bad_params, .init = create_entities, .fini = delete_entities) +{ + dds_return_t result; + + /* buf = NULL */ + result = dds_return_loan (reader, NULL, -1); + CU_ASSERT (result == DDS_RETCODE_BAD_PARAMETER); + result = dds_return_loan (reader, NULL, 0); + CU_ASSERT (result == DDS_RETCODE_BAD_PARAMETER); + result = dds_return_loan (reader, NULL, 1); + CU_ASSERT (result == DDS_RETCODE_BAD_PARAMETER); + + /* buf[0] = NULL, size > 0 */ + void *buf = NULL; + result = dds_return_loan (reader, &buf, 1); + CU_ASSERT (result == DDS_RETCODE_BAD_PARAMETER); + /* buf[0] != NULL, size <= 0 */ + char dummy = 0; + buf = &dummy; + result = dds_return_loan (reader, &buf, 0); + CU_ASSERT (result == DDS_RETCODE_BAD_PARAMETER); + result = dds_return_loan (reader, &buf, -1); + CU_ASSERT (result == DDS_RETCODE_BAD_PARAMETER); + + /* not a reader or condition (checking only the ones we have at hand) */ + result = dds_return_loan (participant, &buf, 1); + CU_ASSERT (result == DDS_RETCODE_ILLEGAL_OPERATION); + result = dds_return_loan (topic, &buf, 1); + CU_ASSERT (result == DDS_RETCODE_ILLEGAL_OPERATION); +} + +CU_Test (ddsc_loan, success, .init = create_entities, .fini = delete_entities) +{ + const RoundTripModule_DataType s = { + .payload = { + ._length = 1, + ._buffer = (uint8_t[]) { 'a' } + } + }; + const unsigned char zeros[3 * sizeof (s)] = { 0 }; + dds_return_t result; + for (size_t i = 0; i < 3; i++) + { + result = dds_write (writer, &s); + CU_ASSERT_FATAL (result == 0); + } + + /* rely on things like address sanitizer, valgrind for detecting double frees and leaks */ + int32_t n; + void *ptrs[3] = { NULL }; + void *ptr0copy, *ptr1copy; + dds_sample_info_t si[3]; + + /* read 1, return: this should cause memory to be allocated for 1 sample only */ + n = dds_read (reader, ptrs, si, 1, 1); + CU_ASSERT_FATAL (n == 1); + CU_ASSERT_FATAL (ptrs[0] != NULL && ptrs[1] == NULL); + ptr0copy = ptrs[0]; + result = dds_return_loan (reader, ptrs, n); + CU_ASSERT_FATAL (result == DDS_RETCODE_OK); + /* return resets buf[0] (so that it picks up the loan the next time) and zeros the data */ + CU_ASSERT_FATAL (ptrs[0] == NULL); + CU_ASSERT_FATAL (memcmp (ptr0copy, zeros, sizeof (s)) == 0); + + /* read 3, return: should work fine, causes realloc */ + n = dds_read (reader, ptrs, si, 3, 3); + CU_ASSERT_FATAL (n == 3); + CU_ASSERT_FATAL (ptrs[0] != NULL && ptrs[1] != NULL && ptrs[2] != NULL); + ptr0copy = ptrs[0]; + ptr1copy = ptrs[1]; + result = dds_return_loan (reader, ptrs, n); + CU_ASSERT_FATAL (result == DDS_RETCODE_OK); + CU_ASSERT_FATAL (ptrs[0] == NULL); + CU_ASSERT_FATAL (memcmp (ptr0copy, zeros, 3 * sizeof (s)) == 0); + + /* read 1 using loan, expecting to get the same address (no realloc needed), defer return. + Expect ptrs[1] to remain unchanged, although that probably is really an implementation + detail rather than something one might want to rely on */ + n = dds_read (read_condition, ptrs, si, 1, 1); + CU_ASSERT_FATAL (n == 1); + CU_ASSERT_FATAL (ptrs[0] == ptr0copy && ptrs[1] == ptr1copy); + + /* read 3, letting read allocate */ + int32_t n2; + void *ptrs2[3] = { NULL }; + n2 = dds_read (read_condition, ptrs2, si, 3, 3); + CU_ASSERT_FATAL (n2 == 3); + CU_ASSERT_FATAL (ptrs2[0] != NULL && ptrs2[1] != NULL && ptrs2[2] != NULL); + CU_ASSERT_FATAL (ptrs2[0] != ptrs[0]); + + /* contents of first sample should be the same; the point of comparing them + is that valgrind/address sanitizer will get angry with us if one of them + has been freed; can't use memcmp because the sequence buffers should be + at different addresses */ + { + const struct RoundTripModule_DataType *a = ptrs[0]; + const struct RoundTripModule_DataType *b = ptrs2[0]; + CU_ASSERT_FATAL (a->payload._length == b->payload._length); + CU_ASSERT_FATAL (a->payload._buffer != b->payload._buffer); + CU_ASSERT_FATAL (a->payload._buffer[0] == b->payload._buffer[0]); + } + + /* return loan -- to be freed when we delete the reader */ + result = dds_return_loan (read_condition, ptrs, n); + CU_ASSERT_FATAL (result == DDS_RETCODE_OK); + CU_ASSERT_FATAL (ptrs[0] == NULL); + + /* use "dds_return_loan" to free the second result immediately, there's no + easy way to check this happens short of using a custom sertopic */ + ptr0copy = ptrs2[0]; + result = dds_return_loan (read_condition, ptrs2, n2); + CU_ASSERT_FATAL (result == DDS_RETCODE_OK); + CU_ASSERT_FATAL (ptrs2[0] == NULL); + + //This should be a use-after-free + //CU_ASSERT_FATAL (memcmp (ptr0copy, zeros, sizeof (s)) == 0); +} + +CU_Test (ddsc_loan, take_cleanup, .init = create_entities, .fini = delete_entities) +{ + const RoundTripModule_DataType s = { + .payload = { + ._length = 1, + ._buffer = (uint8_t[]) { 'a' } + } + }; + dds_return_t result; + + /* rely on things like address sanitizer, valgrind for detecting double frees and leaks */ + int32_t n; + void *ptrs[3] = { NULL }; + void *ptr0copy; + dds_sample_info_t si[3]; + + /* take 1 from an empty reader: this should cause memory to be allocated for + 1 sample only, be stored as the loan, but not become visisble to the + application */ + n = dds_take (reader, ptrs, si, 1, 1); + CU_ASSERT_FATAL (n == 0); + CU_ASSERT_FATAL (ptrs[0] == NULL && ptrs[1] == NULL); + + /* take 1 that's present: allocates a loan */ + result = dds_write (writer, &s); + CU_ASSERT_FATAL (result == 0); + n = dds_take (reader, ptrs, si, 1, 1); + CU_ASSERT_FATAL (n == 1); + CU_ASSERT_FATAL (ptrs[0] != NULL && ptrs[1] == NULL); + ptr0copy = ptrs[0]; + result = dds_return_loan (reader, ptrs, n); + CU_ASSERT_FATAL (result == DDS_RETCODE_OK); + + /* if it really got handled as a loan, the same address must come out again + (rely on address sanitizer allocating at a different address each time) */ + result = dds_write (writer, &s); + CU_ASSERT_FATAL (result == 0); + n = dds_take (reader, ptrs, si, 1, 1); + CU_ASSERT_FATAL (n == 1); + CU_ASSERT_FATAL (ptrs[0] == ptr0copy && ptrs[1] == NULL); + ptr0copy = ptrs[0]; + result = dds_return_loan (reader, ptrs, n); + CU_ASSERT_FATAL (result == DDS_RETCODE_OK); + + /* take that fails (for lack of data in this case) must reuse the loan, but + hand it back and restore the null pointer */ + n = dds_take (reader, ptrs, si, 1, 1); + CU_ASSERT_FATAL (n == 0); + CU_ASSERT_FATAL (ptrs[0] == NULL && ptrs[1] == NULL); + + /* take that succeeds again must therefore still be using the same address */ + result = dds_write (writer, &s); + CU_ASSERT_FATAL (result == 0); + n = dds_take (reader, ptrs, si, 1, 1); + CU_ASSERT_FATAL (n == 1); + CU_ASSERT_FATAL (ptrs[0] == ptr0copy && ptrs[1] == NULL); + + /* take that fails (with the loan still out) must allocate new memory and + free it */ + int32_t n2; + void *ptrs2[3] = { NULL }; + n2 = dds_take (reader, ptrs2, si, 1, 1); + CU_ASSERT_FATAL (n2 == 0); + CU_ASSERT_FATAL (ptrs2[0] == NULL && ptrs2[1] == NULL); + + /* return the loan and the next take should reuse the memory */ + result = dds_return_loan (reader, ptrs, n); + CU_ASSERT_FATAL (result == DDS_RETCODE_OK); + result = dds_write (writer, &s); + CU_ASSERT_FATAL (result == 0); + n = dds_take (reader, ptrs, si, 1, 1); + CU_ASSERT_FATAL (n == 1); + CU_ASSERT_FATAL (ptrs[0] == ptr0copy && ptrs[1] == NULL); + result = dds_return_loan (reader, ptrs, n); + CU_ASSERT_FATAL (result == DDS_RETCODE_OK); +} + +CU_Test (ddsc_loan, read_cleanup, .init = create_entities, .fini = delete_entities) +{ + const RoundTripModule_DataType s = { + .payload = { + ._length = 1, + ._buffer = (uint8_t[]) { 'a' } + } + }; + dds_return_t result; + + /* rely on things like address sanitizer, valgrind for detecting double frees and leaks */ + int32_t n; + void *ptrs[3] = { NULL }; + void *ptr0copy; + dds_sample_info_t si[3]; + + /* read 1 from an empty reader: this should cause memory to be allocated for + 1 sample only, be stored as the loan, but not become visisble to the + application */ + n = dds_read (reader, ptrs, si, 1, 1); + CU_ASSERT_FATAL (n == 0); + CU_ASSERT_FATAL (ptrs[0] == NULL && ptrs[1] == NULL); + + /* read 1 that's present: allocates a loan */ + result = dds_write (writer, &s); + CU_ASSERT_FATAL (result == 0); + n = dds_take (reader, ptrs, si, 1, 1); + CU_ASSERT_FATAL (n == 1); + CU_ASSERT_FATAL (ptrs[0] != NULL && ptrs[1] == NULL); + ptr0copy = ptrs[0]; + result = dds_return_loan (reader, ptrs, n); + CU_ASSERT_FATAL (result == DDS_RETCODE_OK); + + /* if it really got handled as a loan, the same address must come out again + (rely on address sanitizer allocating at a different address each time) */ + result = dds_write (writer, &s); + CU_ASSERT_FATAL (result == 0); + n = dds_read (read_condition_unread, ptrs, si, 1, 1); + CU_ASSERT_FATAL (n == 1); + CU_ASSERT_FATAL (ptrs[0] == ptr0copy && ptrs[1] == NULL); + ptr0copy = ptrs[0]; + result = dds_return_loan (reader, ptrs, n); + CU_ASSERT_FATAL (result == DDS_RETCODE_OK); + + /* take that fails (for lack of data in this case) must reuse the loan, but + hand it back and restore the null pointer */ + n = dds_read (read_condition_unread, ptrs, si, 1, 1); + CU_ASSERT_FATAL (n == 0); + CU_ASSERT_FATAL (ptrs[0] == NULL && ptrs[1] == NULL); + + /* take that succeeds again must therefore still be using the same address */ + result = dds_write (writer, &s); + CU_ASSERT_FATAL (result == 0); + n = dds_read (read_condition_unread, ptrs, si, 1, 1); + CU_ASSERT_FATAL (n == 1); + CU_ASSERT_FATAL (ptrs[0] == ptr0copy && ptrs[1] == NULL); + + /* take that fails (with the loan still out) must allocate new memory and + free it */ + int32_t n2; + void *ptrs2[3] = { NULL }; + n2 = dds_read (read_condition_unread, ptrs2, si, 1, 1); + CU_ASSERT_FATAL (n2 == 0); + CU_ASSERT_FATAL (ptrs2[0] == NULL && ptrs2[1] == NULL); + + /* return the loan and the next take should reuse the memory */ + result = dds_return_loan (reader, ptrs, n); + CU_ASSERT_FATAL (result == DDS_RETCODE_OK); + result = dds_write (writer, &s); + CU_ASSERT_FATAL (result == 0); + n = dds_read (read_condition_unread, ptrs, si, 1, 1); + CU_ASSERT_FATAL (n == 1); + CU_ASSERT_FATAL (ptrs[0] == ptr0copy && ptrs[1] == NULL); + result = dds_return_loan (reader, ptrs, n); + CU_ASSERT_FATAL (result == DDS_RETCODE_OK); +} diff --git a/src/core/ddsc/tests/multi_sertopic.c b/src/core/ddsc/tests/multi_sertopic.c index 1bbdfbf..f66b89b 100644 --- a/src/core/ddsc/tests/multi_sertopic.c +++ b/src/core/ddsc/tests/multi_sertopic.c @@ -13,8 +13,6 @@ #include #include "dds/dds.h" -#include "CUnit/Theory.h" -#include "Space.h" #include "config_env.h" #include "dds/version.h" @@ -30,6 +28,8 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/time.h" +#include "test_common.h" + #define DDS_DOMAINID_PUB 0 #define DDS_DOMAINID_SUB 1 #define DDS_CONFIG_NO_PORT_GAIN "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}0" @@ -167,7 +167,6 @@ static const dds_topic_descriptor_t type_ary2_desc = .m_meta = "" /* this is on its way out anyway */ }; -static uint32_t g_topic_nr = 0; static dds_entity_t g_pub_domain = 0; static dds_entity_t g_pub_participant = 0; static dds_entity_t g_pub_publisher = 0; @@ -176,15 +175,6 @@ static dds_entity_t g_sub_domain = 0; static dds_entity_t g_sub_participant = 0; static dds_entity_t g_sub_subscriber = 0; -static char *create_topic_name (const char *prefix, uint32_t nr, char *name, size_t size) -{ - /* Get unique g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf (name, size, "%s%d_pid%" PRIdPID "_tid%" PRIdTID "", prefix, nr, pid, tid); - return name; -} - static void multi_sertopic_init (void) { /* Domains for pub and sub use a different domain id, but the portgain setting @@ -366,7 +356,7 @@ static void ddsc_multi_sertopic_impl (dds_entity_t pp_pub, dds_entity_t pp_sub, dds_qset_destination_order (qos, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP); dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0); - create_topic_name ("ddsc_multi_sertopic_lease_duration_zero", g_topic_nr++, name, sizeof name); + create_unique_topic_name ("ddsc_multi_sertopic_lease_duration_zero", name, sizeof name); for (size_t i = 0; i < sizeof (pub_topics) / sizeof (pub_topics[0]); i++) { diff --git a/src/core/ddsc/tests/querycondition.c b/src/core/ddsc/tests/querycondition.c index d1afbf5..960437e 100644 --- a/src/core/ddsc/tests/querycondition.c +++ b/src/core/ddsc/tests/querycondition.c @@ -12,13 +12,12 @@ #include #include "dds/dds.h" -#include "CUnit/Theory.h" -#include "Space.h" - #include "dds/ddsrt/misc.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" +#include "test_common.h" + /************************************************************************************************** * * Test fixtures @@ -68,16 +67,6 @@ filter_mod2(const void * sample) return (s->long_1 % 2 == 0); } -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} - static void querycondition_init_hdepth(int hdepth) { @@ -93,7 +82,7 @@ querycondition_init_hdepth(int hdepth) g_waitset = dds_create_waitset(g_participant); CU_ASSERT_FATAL(g_waitset > 0); - g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_querycondition_test", name, sizeof name), NULL, NULL); + g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_unique_topic_name("ddsc_querycondition_test", name, sizeof name), NULL, NULL); CU_ASSERT_FATAL(g_topic > 0); /* Create a reader that keeps last sample of all instances. */ diff --git a/src/core/ddsc/tests/read_instance.c b/src/core/ddsc/tests/read_instance.c index db46759..4c85e1b 100644 --- a/src/core/ddsc/tests/read_instance.c +++ b/src/core/ddsc/tests/read_instance.c @@ -13,13 +13,11 @@ #include #include "dds/dds.h" -#include "Space.h" -#include "RoundTrip.h" -#include "CUnit/Theory.h" - #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" +#include "test_common.h" + /************************************************************************************************** * * Test fixtures @@ -67,16 +65,6 @@ filter_mod2(const void * sample) return (s->long_2 % 2 == 0); } -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} - static void read_instance_init(void) { @@ -101,7 +89,7 @@ read_instance_init(void) g_waitset = dds_create_waitset(g_participant); CU_ASSERT_FATAL(g_waitset > 0); - g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_read_instance_test", name, sizeof name), NULL, NULL); + g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_unique_topic_name("ddsc_read_instance_test", name, sizeof name), NULL, NULL); CU_ASSERT_FATAL(g_topic > 0); /* Create a writer that will not automatically dispose unregistered samples. */ diff --git a/src/core/ddsc/tests/readcondition.c b/src/core/ddsc/tests/readcondition.c index 4566d0c..af180a9 100644 --- a/src/core/ddsc/tests/readcondition.c +++ b/src/core/ddsc/tests/readcondition.c @@ -10,14 +10,12 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include "dds/dds.h" -#include "CUnit/Test.h" -#include "CUnit/Theory.h" -#include "Space.h" - #include "dds/ddsrt/misc.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" +#include "test_common.h" + /************************************************************************************************** * * Test fixtures @@ -60,16 +58,6 @@ static void* g_samples[MAX_SAMPLES]; static Space_Type1 g_data[MAX_SAMPLES]; static dds_sample_info_t g_info[MAX_SAMPLES]; -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} - static void readcondition_init(void) { @@ -85,7 +73,7 @@ readcondition_init(void) g_waitset = dds_create_waitset(g_participant); CU_ASSERT_FATAL(g_waitset > 0); - g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_readcondition_test", name, 100), NULL, NULL); + g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_unique_topic_name("ddsc_readcondition_test", name, 100), NULL, NULL); CU_ASSERT_FATAL(g_topic > 0); /* Create a reader that keeps last sample of all instances. */ diff --git a/src/core/ddsc/tests/reader.c b/src/core/ddsc/tests/reader.c index 97f8131..ca5d9fe 100644 --- a/src/core/ddsc/tests/reader.c +++ b/src/core/ddsc/tests/reader.c @@ -13,14 +13,12 @@ #include #include "dds/dds.h" -#include "Space.h" -#include "RoundTrip.h" -#include "CUnit/Theory.h" - #include "dds/ddsrt/misc.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" +#include "test_common.h" + /************************************************************************************************** * * Test fixtures @@ -64,16 +62,6 @@ static void* g_samples[MAX_SAMPLES]; static Space_Type1 g_data[MAX_SAMPLES]; static dds_sample_info_t g_info[MAX_SAMPLES]; -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} - static void reader_init(void) { @@ -94,7 +82,7 @@ reader_init(void) g_waitset = dds_create_waitset(g_participant); CU_ASSERT_FATAL(g_waitset > 0); - g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_reader_test", name, sizeof name), NULL, NULL); + g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_unique_topic_name("ddsc_reader_test", name, sizeof name), NULL, NULL); CU_ASSERT_FATAL(g_topic > 0); /* Create a reader that keeps last sample of all instances. */ @@ -306,7 +294,7 @@ CU_Test(ddsc_reader_create, participant_mismatch) sub1 = dds_create_subscriber(par1, NULL, NULL); CU_ASSERT_FATAL(sub1 > 0); - top2 = dds_create_topic(par2, &Space_Type1_desc, create_topic_name("ddsc_reader_participant_mismatch", name, sizeof name), NULL, NULL); + top2 = dds_create_topic(par2, &Space_Type1_desc, create_unique_topic_name("ddsc_reader_participant_mismatch", name, sizeof name), NULL, NULL); CU_ASSERT_FATAL(top2 > 0); /* Create reader with participant mismatch. */ @@ -2512,7 +2500,7 @@ CU_Test(ddsc_take_mask, take_instance_last_sample) CU_ASSERT_FATAL(g_participant > 0); g_waitset = dds_create_waitset(g_participant); CU_ASSERT_FATAL(g_waitset > 0); - g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_reader_test", name, 100), NULL, NULL); + g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_unique_topic_name("ddsc_reader_test", name, 100), NULL, NULL); CU_ASSERT_FATAL(g_topic > 0); g_reader = dds_create_reader(g_participant, g_topic, g_qos, NULL); CU_ASSERT_FATAL(g_reader > 0); diff --git a/src/core/ddsc/tests/reader_iterator.c b/src/core/ddsc/tests/reader_iterator.c index a714a67..df1e4c1 100644 --- a/src/core/ddsc/tests/reader_iterator.c +++ b/src/core/ddsc/tests/reader_iterator.c @@ -13,13 +13,11 @@ #include #include "dds/dds.h" -#include "Space.h" -#include "RoundTrip.h" -#include "CUnit/Theory.h" - #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" +#include "test_common.h" + /************************************************************************************************** * * Test fixtures @@ -83,16 +81,6 @@ static void* g_samples[MAX_SAMPLES]; static Space_Type1 g_data[MAX_SAMPLES]; static dds_sample_info_t g_info[MAX_SAMPLES]; -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} - static bool filter_init(const void * sample) { @@ -140,7 +128,7 @@ reader_iterator_init(void) g_waitset = dds_create_waitset(g_participant); CU_ASSERT_FATAL(g_waitset > 0); - g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_read_iterator_test", name, sizeof name), NULL, NULL); + g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_unique_topic_name("ddsc_read_iterator_test", name, sizeof name), NULL, NULL); CU_ASSERT_FATAL(g_topic > 0); /* Create a writer that will not automatically dispose unregistered samples. */ @@ -459,7 +447,8 @@ CU_Test(ddsc_read_next_wl, reader, .init=reader_iterator_init, .fini=reader_iter CU_ASSERT_EQUAL_FATAL(cnt, RDR_NOT_READ_CNT); CU_ASSERT_EQUAL_FATAL(cntinv, RDR_INV_READ_CNT); - ret = dds_return_loan(g_reader, g_loans, ret); + /* return_loan 3rd arg should be in [highest count ever returned, read limit] */ + ret = dds_return_loan(g_reader, g_loans, 1); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); /* All samples should still be available. */ @@ -683,7 +672,8 @@ CU_Test(ddsc_take_next_wl, reader, .init=reader_iterator_init, .fini=reader_iter CU_ASSERT_EQUAL_FATAL(cnt, RDR_NOT_READ_CNT); CU_ASSERT_EQUAL_FATAL(cntinv, RDR_INV_READ_CNT); - ret = dds_return_loan(g_reader, g_loans, ret); + /* return_loan 3rd arg should be in [highest count ever returned, read limit] */ + ret = dds_return_loan(g_reader, g_loans, 1); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); /* All samples should still be available. */ diff --git a/src/core/ddsc/tests/register.c b/src/core/ddsc/tests/register.c index b04d35f..05aec4f 100644 --- a/src/core/ddsc/tests/register.c +++ b/src/core/ddsc/tests/register.c @@ -12,14 +12,12 @@ #include #include "dds/dds.h" -#include "CUnit/Test.h" -#include "CUnit/Theory.h" -#include "Space.h" - #include "dds/ddsrt/misc.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" +#include "test_common.h" + /************************************************************************************************** * * Test fixtures @@ -41,16 +39,6 @@ static dds_time_t g_present = 0; static void* g_samples[MAX_SAMPLES]; static Space_Type1 g_data[MAX_SAMPLES]; -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} - static void registering_init(void) { @@ -69,7 +57,7 @@ registering_init(void) g_waitset = dds_create_waitset(g_participant); CU_ASSERT_FATAL(g_waitset > 0); - g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_registering_test", name, sizeof name), qos, NULL); + g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_unique_topic_name("ddsc_registering_test", name, sizeof name), qos, NULL); CU_ASSERT_FATAL(g_topic > 0); /* Create a reader that keeps one sample on three instances. */ diff --git a/src/core/ddsc/tests/return_loan.c b/src/core/ddsc/tests/return_loan.c deleted file mode 100644 index 812e024..0000000 --- a/src/core/ddsc/tests/return_loan.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include "dds/dds.h" -#include "RoundTrip.h" - -#include -#include "CUnit/Test.h" - -static dds_entity_t participant = 0, topic = 0, reader = 0, read_condition = 0; - -static void create_entities(void) -{ - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - CU_ASSERT_FATAL(participant > 0); - - topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, "ddsc_reader_return_loan_RoundTrip", NULL, NULL); - CU_ASSERT_FATAL(topic > 0); - - reader = dds_create_reader(participant, topic, NULL, NULL); - CU_ASSERT_FATAL(reader > 0); - - read_condition = dds_create_readcondition(reader, DDS_ANY_STATE); - CU_ASSERT_FATAL(read_condition > 0); -} - -static void delete_entities(void) -{ - dds_return_t result; - result = dds_delete(participant); - CU_ASSERT_EQUAL_FATAL(result, DDS_RETCODE_OK); - dds_delete(read_condition); -} - -static void** create_loan_buf(size_t sz, bool empty) -{ - size_t i; - void **buf = NULL; - buf = dds_alloc(sz * sizeof(*buf)); - for (i = 0; i < sz; i++) { - buf[i] = dds_alloc(sizeof(RoundTripModule_DataType)); - if (empty) { - memset(buf[i], 0, sizeof(RoundTripModule_DataType)); - } else { - RoundTripModule_DataType *s = buf[i]; - s->payload._maximum = 0; - s->payload._length = 25; - s->payload._buffer = dds_alloc(25); - memset(s->payload._buffer, 'z', 25); - s->payload._release = true; - } - } - return buf; -} - -static void delete_loan_buf(void **buf, size_t sz, bool empty) -{ - size_t i; - for (i = 0; i < sz; i++) { - RoundTripModule_DataType *s = buf[i]; - if (!empty) { - CU_ASSERT(s->payload._length > 0); - if (s->payload._length > 0) { - /* Freed by a successful dds_return_loan */ - dds_free(s->payload._buffer); - } - } - /* dds_return_loan only free's sample contents */ - dds_free(s); - } - dds_free(buf); -} - -/* Verify DDS_RETCODE_BAD_PARAMETER is returned */ -CU_Test(ddsc_reader, return_loan_bad_params, .init = create_entities, .fini = delete_entities) -{ - dds_return_t result; - void **buf = NULL; - - result = dds_return_loan(reader, NULL, 0); - CU_ASSERT_EQUAL(result, DDS_RETCODE_BAD_PARAMETER); - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable: 6387) -#endif - result = dds_return_loan(reader, buf, 10); -#ifdef _MSC_VER -#pragma warning(pop) -#endif - CU_ASSERT_EQUAL(result, DDS_RETCODE_BAD_PARAMETER); - - buf = create_loan_buf(10, false); -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable: 28020) -#endif - result = dds_return_loan(0, buf, 10); -#ifdef _MSC_VER -#pragma warning(pop) -#endif - CU_ASSERT_EQUAL(result, DDS_RETCODE_BAD_PARAMETER); - - result = dds_return_loan(participant, buf, 0); - CU_ASSERT_EQUAL(result, DDS_RETCODE_ILLEGAL_OPERATION); - - delete_loan_buf(buf, 10, false); -} - -/* Verify DDS_RETCODE_OK is returned */ -CU_Test(ddsc_reader, return_loan_success, .init = create_entities, .fini = delete_entities) -{ - void **buf; - void *buf2 = NULL; - dds_return_t result; - - buf = create_loan_buf(10, false); - result = dds_return_loan(reader, buf, 10); - CU_ASSERT_EQUAL(result, DDS_RETCODE_OK); - - result = dds_return_loan(reader, &buf2, 0); - CU_ASSERT_EQUAL(result, DDS_RETCODE_OK); - delete_loan_buf(buf, 10, true); - - buf = create_loan_buf(10, false); - result = dds_return_loan(read_condition, buf, 10); - CU_ASSERT_EQUAL(result, DDS_RETCODE_OK); - - result = dds_return_loan(read_condition, &buf2, 0); - CU_ASSERT_EQUAL(result, DDS_RETCODE_OK); - delete_loan_buf(buf, 10, true); -} diff --git a/src/core/ddsc/tests/take_instance.c b/src/core/ddsc/tests/take_instance.c index e8cba48..809ffae 100644 --- a/src/core/ddsc/tests/take_instance.c +++ b/src/core/ddsc/tests/take_instance.c @@ -13,13 +13,11 @@ #include #include "dds/dds.h" -#include "Space.h" -#include "RoundTrip.h" -#include "CUnit/Theory.h" - #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" +#include "test_common.h" + /************************************************************************************************** * * Test fixtures @@ -67,16 +65,6 @@ filter_mod2(const void * sample) return (s->long_2 % 2 == 0); } -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} - static void take_instance_init(void) { @@ -101,7 +89,7 @@ take_instance_init(void) g_waitset = dds_create_waitset(g_participant); CU_ASSERT_FATAL(g_waitset > 0); - g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_take_instance_test", name, sizeof name), NULL, NULL); + g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_unique_topic_name("ddsc_take_instance_test", name, sizeof name), NULL, NULL); CU_ASSERT_FATAL(g_topic > 0); /* Create a writer that will not automatically dispose unregistered samples. */ diff --git a/src/core/ddsc/tests/test-common.c b/src/core/ddsc/tests/test-common.c deleted file mode 100644 index 44b846f..0000000 --- a/src/core/ddsc/tests/test-common.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include "dds/dds.h" - -const char* -entity_kind_str(dds_entity_t ent) { - if(ent <= 0) { - return "(ERROR)"; - } - switch(ent & DDS_ENTITY_KIND_MASK) { - case DDS_KIND_TOPIC: return "Topic"; - case DDS_KIND_PARTICIPANT: return "Participant"; - case DDS_KIND_READER: return "Reader"; - case DDS_KIND_WRITER: return "Writer"; - case DDS_KIND_SUBSCRIBER: return "Subscriber"; - case DDS_KIND_PUBLISHER: return "Publisher"; - case DDS_KIND_COND_READ: return "ReadCondition"; - case DDS_KIND_COND_QUERY: return "QueryCondition"; - case DDS_KIND_WAITSET: return "WaitSet"; - default: return "(INVALID_ENTITY)"; - } -} diff --git a/src/core/ddsc/tests/test_common.c b/src/core/ddsc/tests/test_common.c new file mode 100644 index 0000000..531322b --- /dev/null +++ b/src/core/ddsc/tests/test_common.c @@ -0,0 +1,26 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include "dds/dds.h" +#include "dds/ddsrt/atomics.h" +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/threads.h" +#include "test_common.h" + +char *create_unique_topic_name (const char *prefix, char *name, size_t size) +{ + static ddsrt_atomic_uint32_t count = DDSRT_ATOMIC_UINT64_INIT (0); + const ddsrt_pid_t pid = ddsrt_getpid(); + const ddsrt_tid_t tid = ddsrt_gettid(); + const uint32_t nr = ddsrt_atomic_inc32_nv (&count); + (void) snprintf (name, size, "%s%"PRIu32"_pid%" PRIdPID "_tid%" PRIdTID "", prefix, nr, pid, tid); + return name; +} diff --git a/src/core/ddsc/tests/test-common.h b/src/core/ddsc/tests/test_common.h similarity index 58% rename from src/core/ddsc/tests/test-common.h rename to src/core/ddsc/tests/test_common.h index 917e4b9..6672d93 100644 --- a/src/core/ddsc/tests/test-common.h +++ b/src/core/ddsc/tests/test_common.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -12,6 +12,16 @@ #ifndef _TEST_COMMON_H_ #define _TEST_COMMON_H_ -const char *entity_kind_str(dds_entity_t ent); +#include +#include + +#include "CUnit/Test.h" +#include "CUnit/Theory.h" + +#include "Space.h" +#include "RoundTrip.h" + +/* Get unique g_topic name on each invocation. */ +char *create_unique_topic_name (const char *prefix, char *name, size_t size); #endif /* _TEST_COMMON_H_ */ diff --git a/src/core/ddsc/tests/topic.c b/src/core/ddsc/tests/topic.c index 813d77f..013bf22 100644 --- a/src/core/ddsc/tests/topic.c +++ b/src/core/ddsc/tests/topic.c @@ -10,13 +10,12 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include "dds/dds.h" -#include "RoundTrip.h" -#include "CUnit/Theory.h" - #include "dds/ddsrt/misc.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" +#include "test_common.h" + /************************************************************************************************** * * Test fixtures @@ -36,21 +35,11 @@ char g_topicRtmAddressName[MAX_NAME_SIZE]; char g_topicRtmDataTypeName[MAX_NAME_SIZE]; char g_nameBuffer[MAX_NAME_SIZE]; -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} - static void ddsc_topic_init(void) { - create_topic_name("ddsc_topic_test_rtm_address", g_topicRtmAddressName, MAX_NAME_SIZE); - create_topic_name("ddsc_topic_test_rtm_datatype", g_topicRtmDataTypeName, MAX_NAME_SIZE); + create_unique_topic_name("ddsc_topic_test_rtm_address", g_topicRtmAddressName, MAX_NAME_SIZE); + create_unique_topic_name("ddsc_topic_test_rtm_datatype", g_topicRtmDataTypeName, MAX_NAME_SIZE); g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(g_participant > 0); diff --git a/src/core/ddsc/tests/unregister.c b/src/core/ddsc/tests/unregister.c index 538c661..e3dcf00 100644 --- a/src/core/ddsc/tests/unregister.c +++ b/src/core/ddsc/tests/unregister.c @@ -13,13 +13,11 @@ #include #include "dds/dds.h" -#include "CUnit/Test.h" -#include "CUnit/Theory.h" -#include "Space.h" - #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" +#include "test_common.h" + /************************************************************************************************** * * Test fixtures @@ -41,16 +39,6 @@ static void* g_samples[MAX_SAMPLES]; static Space_Type1 g_data[MAX_SAMPLES]; static dds_sample_info_t g_info[MAX_SAMPLES]; -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} - static void unregistering_init(void) { @@ -69,7 +57,7 @@ unregistering_init(void) g_waitset = dds_create_waitset(g_participant); CU_ASSERT_FATAL(g_waitset > 0); - g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_unregistering_test", name, 100), qos, NULL); + g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_unique_topic_name("ddsc_unregistering_test", name, 100), qos, NULL); CU_ASSERT_FATAL(g_topic > 0); /* Create a reader that keeps one sample on three instances. */ @@ -616,7 +604,7 @@ CU_Test(ddsc_unregister_instance_ih_ts, unregistering_instance) /* Create a writer that WILL automatically dispose unregistered samples. */ g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(g_participant > 0); - g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_unregistering_instance_test", name, 100), NULL, NULL); + g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_unique_topic_name("ddsc_unregistering_instance_test", name, 100), NULL, NULL); CU_ASSERT_FATAL(g_topic > 0); g_writer = dds_create_writer(g_participant, g_topic, NULL, NULL); CU_ASSERT_FATAL(g_writer > 0); diff --git a/src/core/ddsc/tests/unsupported.c b/src/core/ddsc/tests/unsupported.c index 9c538ce..6ec39cc 100644 --- a/src/core/ddsc/tests/unsupported.c +++ b/src/core/ddsc/tests/unsupported.c @@ -15,7 +15,7 @@ #include "dds/dds.h" #include "RoundTrip.h" -#include "test-common.h" +#include "test_common.h" static dds_entity_t e[8]; diff --git a/src/core/ddsc/tests/waitset.c b/src/core/ddsc/tests/waitset.c index 1f6e0b5..0f69025 100644 --- a/src/core/ddsc/tests/waitset.c +++ b/src/core/ddsc/tests/waitset.c @@ -13,9 +13,6 @@ #include #include "dds/dds.h" -#include "CUnit/Theory.h" -#include "RoundTrip.h" - #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/misc.h" #include "dds/ddsrt/process.h" @@ -23,6 +20,8 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/time.h" +#include "test_common.h" + /************************************************************************************************** * * Some thread related convenience stuff. @@ -63,17 +62,6 @@ static dds_entity_t subscriber = 0; static dds_entity_t readcond = 0; -static char* -create_topic_name(const char *prefix, char *name, size_t size) -{ - /* Get semi random g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid(); - ddsrt_tid_t tid = ddsrt_gettid(); - (void) snprintf(name, size, "%s_pid%"PRIdPID"_tid%"PRIdTID"", prefix, pid, tid); - return name; -} - - static void ddsc_waitset_basic_init(void) { @@ -109,7 +97,7 @@ ddsc_waitset_init(void) subscriber = dds_create_subscriber(participant, NULL, NULL); CU_ASSERT_FATAL(subscriber > 0); - topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_waitset_test", name, sizeof name), NULL, NULL); + topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_unique_topic_name("ddsc_waitset_test", name, sizeof name), NULL, NULL); CU_ASSERT_FATAL(topic > 0); reader = dds_create_reader(subscriber, topic, NULL, NULL); diff --git a/src/core/ddsc/tests/whc.c b/src/core/ddsc/tests/whc.c index cdade5e..93fda9e 100644 --- a/src/core/ddsc/tests/whc.c +++ b/src/core/ddsc/tests/whc.c @@ -13,9 +13,6 @@ #include #include "dds/dds.h" -#include "CUnit/Theory.h" -#include "Space.h" - #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" #include "dds/ddsrt/environ.h" @@ -24,6 +21,8 @@ #include "dds/ddsi/q_whc.h" #include "dds__entity.h" +#include "test_common.h" + #define DDS_DOMAINID_PUB 0 #define DDS_DOMAINID_SUB 1 #define DDS_CONFIG_NO_PORT_GAIN "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}0" @@ -32,7 +31,6 @@ #define SAMPLE_COUNT 5 #define DEADLINE_DURATION DDS_MSECS(1) -static uint32_t g_topic_nr = 0; static dds_entity_t g_domain = 0; static dds_entity_t g_participant = 0; static dds_entity_t g_subscriber = 0; @@ -42,15 +40,6 @@ static dds_entity_t g_remote_domain = 0; static dds_entity_t g_remote_participant = 0; static dds_entity_t g_remote_subscriber = 0; -static char *create_topic_name (const char *prefix, uint32_t nr, char *name, size_t size) -{ - /* Get unique g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid (); - ddsrt_tid_t tid = ddsrt_gettid (); - (void) snprintf (name, size, "%s%d_pid%" PRIdPID "_tid%" PRIdTID "", prefix, nr, pid, tid); - return name; -} - static void whc_init(void) { /* Domains for pub and sub use a different domain id, but the portgain setting @@ -177,7 +166,7 @@ static void test_whc_end_state(dds_durability_kind_t d, dds_reliability_kind_t r dds_qset_deadline (g_qos, dl ? DEADLINE_DURATION : DDS_INFINITY); dds_qset_durability_service (g_qos, 0, dh, dh == KA ? 0 : dhd, DDS_LENGTH_UNLIMITED, DDS_LENGTH_UNLIMITED, DDS_LENGTH_UNLIMITED); - create_topic_name ("ddsc_whc_end_state_test", g_topic_nr++, name, sizeof name); + create_unique_topic_name ("ddsc_whc_end_state_test", name, sizeof name); topic = dds_create_topic (g_participant, k ? &Space_Type1_desc : &Space_Type3_desc, name, NULL, NULL); CU_ASSERT_FATAL(topic > 0); remote_topic = dds_create_topic (g_remote_participant, k ? &Space_Type1_desc : &Space_Type3_desc, name, NULL, NULL); diff --git a/src/core/ddsc/tests/write_various_types.c b/src/core/ddsc/tests/write_various_types.c index 861a627..b1f05c3 100644 --- a/src/core/ddsc/tests/write_various_types.c +++ b/src/core/ddsc/tests/write_various_types.c @@ -13,19 +13,18 @@ #include #include "dds/dds.h" -#include "CUnit/Theory.h" -#include "WriteTypes.h" - #include "dds/ddsrt/process.h" #include "dds/ddsrt/threads.h" #include "dds/ddsrt/environ.h" +#include "test_common.h" +#include "WriteTypes.h" + #define DDS_DOMAINID_PUB 0 #define DDS_DOMAINID_SUB 1 #define DDS_CONFIG_NO_PORT_GAIN "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}0" #define DDS_CONFIG_NO_PORT_GAIN_LOG "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}cyclonedds_writetypes_various.${CYCLONEDDS_DOMAIN_ID}.${CYCLONEDDS_PID}.logfinest0" -static uint32_t g_topic_nr = 0; static dds_entity_t g_pub_domain = 0; static dds_entity_t g_pub_participant = 0; static dds_entity_t g_pub_publisher = 0; @@ -34,15 +33,6 @@ static dds_entity_t g_sub_domain = 0; static dds_entity_t g_sub_participant = 0; static dds_entity_t g_sub_subscriber = 0; -static char *create_topic_name (const char *prefix, uint32_t nr, char *name, size_t size) -{ - /* Get unique g_topic name. */ - ddsrt_pid_t pid = ddsrt_getpid (); - ddsrt_tid_t tid = ddsrt_gettid (); - (void) snprintf (name, size, "%s%d_pid%" PRIdPID "_tid%" PRIdTID "", prefix, nr, pid, tid); - return name; -} - static void writetypes_init(void) { /* Domains for pub and sub use a different domain id, but the portgain setting @@ -152,7 +142,7 @@ CU_Theory((const dds_topic_descriptor_t *desc, compare_fn_t cmp, size_t nsamples CU_ASSERT_FATAL (qos != NULL); dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_SECS (1)); dds_qset_writer_data_lifecycle (qos, false); - create_topic_name ("ddsc_writetypes_various", g_topic_nr++, name, sizeof name); + create_unique_topic_name ("ddsc_writetypes_various", name, sizeof name); pub_topic = dds_create_topic (g_pub_participant, desc, name, qos, NULL); CU_ASSERT_FATAL (pub_topic > 0); sub_topic = dds_create_topic (g_sub_participant, desc, name, qos, NULL); diff --git a/src/core/ddsi/src/ddsi_eth.c b/src/core/ddsi/src/ddsi_eth.c index 670667d..a36d314 100644 --- a/src/core/ddsi/src/ddsi_eth.c +++ b/src/core/ddsi/src/ddsi_eth.c @@ -16,6 +16,7 @@ int ddsi_eth_enumerate_interfaces (ddsi_tran_factory_t fact, enum transport_sele int afs[] = { AF_INET, DDSRT_AF_TERM }; (void)fact; + (void)transport_selector; #if DDSRT_HAVE_IPV6 if (transport_selector == TRANS_TCP6 || diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index de7a7e6..e6544e2 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -42,7 +42,9 @@ union addr { struct sockaddr a; struct sockaddr_in a4; +#if DDSRT_HAVE_IPV6 struct sockaddr_in6 a6; +#endif }; typedef struct ddsi_tcp_conn { diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 3410510..65d10fd 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -30,7 +30,9 @@ union addr { struct sockaddr_storage x; struct sockaddr a; struct sockaddr_in a4; +#if DDSRT_HAVE_IPV6 struct sockaddr_in6 a6; +#endif }; typedef struct ddsi_udp_conn { @@ -559,7 +561,7 @@ static int joinleave_asm_mcgroup (ddsrt_socket_t socket, int join, const nn_loca { struct ipv6_mreq ipv6mreq; memset (&ipv6mreq, 0, sizeof (ipv6mreq)); - memcpy (&ipv6mreq.ipv6mr_multiaddr, &mcip.a6, sizeof (ipv6mreq.ipv6mr_multiaddr)); + ipv6mreq.ipv6mr_multiaddr = mcip.a6.sin6_addr; ipv6mreq.ipv6mr_interface = interf ? interf->if_index : 0; rc = ddsrt_setsockopt (socket, IPPROTO_IPV6, join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP, &ipv6mreq, sizeof (ipv6mreq)); } @@ -590,8 +592,8 @@ static int joinleave_ssm_mcgroup (ddsrt_socket_t socket, int join, const nn_loca struct group_source_req gsr; memset (&gsr, 0, sizeof (gsr)); gsr.gsr_interface = interf ? interf->if_index : 0; - memcpy (&gsr.gsr_group, &mcip.a6, sizeof (gsr.gsr_group)); - memcpy (&gsr.gsr_source, &srcip.a6, sizeof (gsr.gsr_source)); + gsr.gsr_group = mcip.x; + gsr.gsr_source = srcip.x; rc = ddsrt_setsockopt (socket, IPPROTO_IPV6, join ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP, &gsr, sizeof (gsr)); } else diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 5f76314..7c1ff62 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -3994,8 +3994,23 @@ dds_return_t writer_wait_for_acks (struct writer *wr, dds_time_t abstimeout) dds_return_t delete_writer_nolinger_locked (struct writer *wr) { - ELOGDISC (wr, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (wr->e.guid)); ASSERT_MUTEX_HELD (&wr->e.lock); + + /* We can get here via multiple paths in parallel, in particular: because all data got + ACK'd while lingering, and because the linger timeout elapses. Those two race each + other, the first calling this function directly, the second calling from + handle_xevk_delete_writer via delete_writer_nolinger. + + There are two practical options to decide whether to ignore the call: one is to check + whether the writer is still in the GUID hashes, the second to check whether the state + is WRST_DELETING. The latter seems a bit less surprising. */ + if (wr->state == WRST_DELETING) + { + ELOGDISC (wr, "delete_writer_nolinger(guid "PGUIDFMT") already done\n", PGUID (wr->e.guid)); + return 0; + } + + ELOGDISC (wr, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (wr->e.guid)); builtintopic_write (wr->e.gv->builtin_topic_interface, &wr->e, ddsrt_time_wallclock(), false); local_reader_ary_setinvalid (&wr->rdary); entidx_remove_writer_guid (wr->e.gv->entity_index, wr); diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index 3c4ff83..b535bbd 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -1271,7 +1271,7 @@ static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_ static void handle_xevk_delete_writer (UNUSED_ARG (struct nn_xpack *xp), struct xevent *ev, UNUSED_ARG (ddsrt_mtime_t tnow)) { - /* don't worry if the writer is already gone by the time we get here. */ + /* don't worry if the writer is already gone by the time we get here, delete_writer_nolinger checks for that. */ struct ddsi_domaingv * const gv = ev->evq->gv; GVTRACE ("handle_xevk_delete_writer: "PGUIDFMT"\n", PGUID (ev->u.delete_writer.guid)); delete_writer_nolinger (gv, &ev->u.delete_writer.guid); diff --git a/src/tools/ddsperf/netload.c b/src/tools/ddsperf/netload.c index ae716a5..f186e44 100644 --- a/src/tools/ddsperf/netload.c +++ b/src/tools/ddsperf/netload.c @@ -78,7 +78,7 @@ struct record_netload_state *record_netload_new (const char *dev, double bw) st->bw = bw; st->data_valid = false; st->errored = false; - record_netload (st, NULL, dds_time ()); + record_netload (st, "", dds_time ()); return st; }