Add a test for duration 0ns and 1ns manual lease
Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
parent
5632ed46b5
commit
4af531a1c3
2 changed files with 270 additions and 1 deletions
|
@ -215,7 +215,7 @@ script:
|
||||||
${SCAN_BUILD} cmake --build . --config ${BUILD_TYPE} --target install
|
${SCAN_BUILD} cmake --build . --config ${BUILD_TYPE} --target install
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
- CYCLONEDDS_URI='<CycloneDDS><Domain><Internal><EnableExpensiveChecks>all</EnableExpensiveChecks></Internal><Tracing><Verbosity>config</Verbosity><OutputFile>stderr</OutputFile></Tracing></Domain></CycloneDDS>' ctest -j 4 --output-on-failure -T test -E '^CUnit_ddsrt_random_default_random$' -C ${BUILD_TYPE}
|
- CYCLONEDDS_URI='<CycloneDDS><Domain><Internal><EnableExpensiveChecks>all</EnableExpensiveChecks><LivelinessMonitoring>true</LivelinessMonitoring></Internal><Tracing><Verbosity>config</Verbosity><OutputFile>stderr</OutputFile></Tracing></Domain></CycloneDDS>' ctest -j 4 --output-on-failure -T test -E '^CUnit_ddsrt_random_default_random$' -C ${BUILD_TYPE}
|
||||||
- if [ "${ASAN}" != "none" ]; then
|
- if [ "${ASAN}" != "none" ]; then
|
||||||
CMAKE_LINKER_FLAGS="-DCMAKE_LINKER_FLAGS=-fsanitize=${USE_SANITIZER}";
|
CMAKE_LINKER_FLAGS="-DCMAKE_LINKER_FLAGS=-fsanitize=${USE_SANITIZER}";
|
||||||
CMAKE_C_FLAGS="-DCMAKE_C_FLAGS=-fsanitize=${USE_SANITIZER}";
|
CMAKE_C_FLAGS="-DCMAKE_C_FLAGS=-fsanitize=${USE_SANITIZER}";
|
||||||
|
|
|
@ -814,3 +814,272 @@ CU_Theory((uint32_t wr_cnt_auto, uint32_t wr_cnt_man_pp, uint32_t wr_cnt_man_tp)
|
||||||
} while (!test_finished);
|
} while (!test_finished);
|
||||||
}
|
}
|
||||||
#undef MAX_WRITERS
|
#undef MAX_WRITERS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that manual-by-participant/topic writers with lease duration 0ns and 1ns work.
|
||||||
|
*/
|
||||||
|
struct liveliness_changed_state {
|
||||||
|
ddsrt_mutex_t lock;
|
||||||
|
dds_instance_handle_t w0_handle;
|
||||||
|
bool weirdness;
|
||||||
|
uint32_t w0_alive, w0_not_alive;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void liveliness_changed_listener (dds_entity_t rd, const dds_liveliness_changed_status_t status, void *arg)
|
||||||
|
{
|
||||||
|
struct liveliness_changed_state *st = arg;
|
||||||
|
(void) rd;
|
||||||
|
|
||||||
|
ddsrt_mutex_lock (&st->lock);
|
||||||
|
if (status.last_publication_handle != st->w0_handle)
|
||||||
|
{
|
||||||
|
if (st->w0_handle == 0)
|
||||||
|
{
|
||||||
|
printf ("liveliness_changed_listener: w0 = %"PRIx64"\n", status.last_publication_handle);
|
||||||
|
st->w0_handle = status.last_publication_handle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("liveliness_changed_listener: too many writer handles\n");
|
||||||
|
st->weirdness = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.alive_count_change != 0 || status.not_alive_count_change != 0)
|
||||||
|
{
|
||||||
|
switch (status.alive_count_change)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (status.last_publication_handle == st->w0_handle)
|
||||||
|
st->w0_alive++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("liveliness_changed_listener: alive_count_change = %d: unrecognized writer\n", status.alive_count_change);
|
||||||
|
st->weirdness = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf ("liveliness_changed_listener: alive_count_change = %d\n", status.alive_count_change);
|
||||||
|
st->weirdness = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (status.not_alive_count_change)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (status.last_publication_handle == st->w0_handle)
|
||||||
|
st->w0_not_alive++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("liveliness_changed_listener: not_alive_count_change = %d: unrecognized writer\n", status.not_alive_count_change);
|
||||||
|
st->weirdness = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf ("liveliness_changed_listener: not_alive_count_change = %d\n", status.not_alive_count_change);
|
||||||
|
st->weirdness = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ddsrt_mutex_unlock (&st->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool get_and_check_status (dds_entity_t reader, dds_entity_t writer_active)
|
||||||
|
{
|
||||||
|
struct dds_liveliness_changed_status lstatus;
|
||||||
|
struct dds_subscription_matched_status sstatus;
|
||||||
|
struct dds_publication_matched_status pstatus;
|
||||||
|
dds_return_t rc;
|
||||||
|
rc = dds_get_subscription_matched_status(reader, &sstatus);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
rc = dds_get_liveliness_changed_status(reader, &lstatus);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
rc = dds_get_publication_matched_status(writer_active, &pstatus);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
CU_ASSERT_FATAL(lstatus.alive_count + lstatus.not_alive_count <= 2);
|
||||||
|
printf ("%d %d %d %d\n", (int)sstatus.current_count, (int)lstatus.alive_count, (int)lstatus.not_alive_count, (int)pstatus.current_count);
|
||||||
|
return (sstatus.current_count == 2 && lstatus.not_alive_count == 2 && pstatus.current_count == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lease_duration_zero_or_one_impl (dds_duration_t sleep, dds_liveliness_kind_t lkind, dds_duration_t ldur)
|
||||||
|
{
|
||||||
|
const uint32_t nsamples = (sleep <= DDS_MSECS(10)) ? 100 : 10;
|
||||||
|
dds_entity_t pub_topic;
|
||||||
|
dds_entity_t sub_topic;
|
||||||
|
dds_entity_t reader;
|
||||||
|
dds_entity_t writer_active; /* writing */
|
||||||
|
dds_entity_t writer_inactive; /* not writing, liveliness should still toggle */
|
||||||
|
dds_entity_t waitset;
|
||||||
|
dds_listener_t *listener;
|
||||||
|
dds_qos_t *qos;
|
||||||
|
dds_return_t rc;
|
||||||
|
struct dds_liveliness_changed_status lstatus;
|
||||||
|
char name[100];
|
||||||
|
Space_Type1 sample = {1, 0, 0};
|
||||||
|
struct liveliness_changed_state listener_state = {
|
||||||
|
.weirdness = false,
|
||||||
|
.w0_handle = 0,
|
||||||
|
.w0_alive = 0,
|
||||||
|
.w0_not_alive = 0,
|
||||||
|
};
|
||||||
|
ddsrt_mutex_init (&listener_state.lock);
|
||||||
|
|
||||||
|
waitset = dds_create_waitset(DDS_CYCLONEDDS_HANDLE);
|
||||||
|
CU_ASSERT_FATAL(waitset > 0);
|
||||||
|
|
||||||
|
qos = dds_create_qos();
|
||||||
|
CU_ASSERT_FATAL(qos != NULL);
|
||||||
|
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);
|
||||||
|
pub_topic = dds_create_topic(g_pub_participant, &Space_Type1_desc, name, qos, NULL);
|
||||||
|
CU_ASSERT_FATAL(pub_topic > 0);
|
||||||
|
sub_topic = dds_create_topic(g_sub_participant, &Space_Type1_desc, name, qos, NULL);
|
||||||
|
CU_ASSERT_FATAL(sub_topic > 0);
|
||||||
|
|
||||||
|
/* reader liveliness is always automatic/infinity */
|
||||||
|
dds_qset_liveliness(qos, DDS_LIVELINESS_AUTOMATIC, DDS_INFINITY);
|
||||||
|
reader = dds_create_reader(g_sub_participant, sub_topic, qos, NULL);
|
||||||
|
CU_ASSERT_FATAL(reader > 0);
|
||||||
|
rc = dds_set_status_mask(reader, DDS_LIVELINESS_CHANGED_STATUS | DDS_SUBSCRIPTION_MATCHED_STATUS);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
rc = dds_waitset_attach(waitset, reader, reader);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
|
||||||
|
/* writer liveliness varies */
|
||||||
|
dds_qset_liveliness(qos, lkind, ldur);
|
||||||
|
writer_active = dds_create_writer(g_pub_participant, pub_topic, qos, NULL);
|
||||||
|
CU_ASSERT_FATAL(writer_active > 0);
|
||||||
|
writer_inactive = dds_create_writer(g_pub_participant, pub_topic, qos, NULL);
|
||||||
|
CU_ASSERT_FATAL(writer_inactive > 0);
|
||||||
|
rc = dds_set_status_mask(writer_active, DDS_PUBLICATION_MATCHED_STATUS);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
rc = dds_waitset_attach(waitset, writer_active, writer_active);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
|
||||||
|
dds_delete_qos(qos);
|
||||||
|
|
||||||
|
/* wait for writers to be discovered and to have lost their liveliness, and for
|
||||||
|
writer_active to have discovered the reader */
|
||||||
|
while (!get_and_check_status (reader, writer_active))
|
||||||
|
{
|
||||||
|
rc = dds_waitset_wait(waitset, NULL, 0, DDS_SECS(5));
|
||||||
|
if (rc < 1)
|
||||||
|
{
|
||||||
|
get_and_check_status (reader, writer_active);
|
||||||
|
CU_ASSERT_FATAL(rc >= 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* switch to using a listener: those allow us to observe all events */
|
||||||
|
listener = dds_create_listener (&listener_state);
|
||||||
|
dds_lset_liveliness_changed(listener, liveliness_changed_listener);
|
||||||
|
rc = dds_set_listener (reader, listener);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
dds_delete_listener (listener);
|
||||||
|
|
||||||
|
/* write as fast as possible - we don't expect this to cause the writers
|
||||||
|
to gain and lose liveliness once for each sample, but it should have
|
||||||
|
become alive at least once and fall back to not alive afterward */
|
||||||
|
for (uint32_t i = 0; i < nsamples; i++)
|
||||||
|
{
|
||||||
|
rc = dds_write(writer_active, &sample);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
if (sleep && i < nsamples - 1)
|
||||||
|
dds_sleepfor(sleep);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = dds_wait_for_acks(writer_active, DDS_SECS(5));
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
|
||||||
|
/* verify the reader received all samples */
|
||||||
|
{
|
||||||
|
void *raw[] = { &sample };
|
||||||
|
dds_sample_info_t si;
|
||||||
|
uint32_t cnt = 0;
|
||||||
|
while (dds_take(reader, raw, &si, 1, 1) == 1)
|
||||||
|
cnt++;
|
||||||
|
CU_ASSERT(cnt == nsamples);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* transition to not alive is not necessarily immediate */
|
||||||
|
{
|
||||||
|
int retries = 100;
|
||||||
|
rc = dds_get_liveliness_changed_status(reader, &lstatus);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
printf("early liveliness changed status: alive %"PRId32" not-alive %"PRId32"\n", lstatus.alive_count, lstatus.not_alive_count);
|
||||||
|
|
||||||
|
ddsrt_mutex_lock (&listener_state.lock);
|
||||||
|
printf("early w0 %"PRIx64" alive %"PRId32" not-alive %"PRId32"\n", listener_state.w0_handle, listener_state.w0_alive, listener_state.w0_not_alive);
|
||||||
|
CU_ASSERT(!listener_state.weirdness);
|
||||||
|
CU_ASSERT(listener_state.w0_handle != 0);
|
||||||
|
while (listener_state.w0_not_alive < listener_state.w0_alive && retries-- > 0)
|
||||||
|
{
|
||||||
|
ddsrt_mutex_unlock(&listener_state.lock);
|
||||||
|
dds_sleepfor(DDS_MSECS(10));
|
||||||
|
rc = dds_get_liveliness_changed_status(reader, &lstatus);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
ddsrt_mutex_lock(&listener_state.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("late liveliness changed status: alive %"PRId32" not-alive %"PRId32"\n", lstatus.alive_count, lstatus.not_alive_count);
|
||||||
|
printf("final w0 %"PRIx64" alive %"PRId32" not-alive %"PRId32"\n", listener_state.w0_handle, listener_state.w0_alive, listener_state.w0_not_alive);
|
||||||
|
CU_ASSERT(listener_state.w0_alive == listener_state.w0_not_alive);
|
||||||
|
if (sleep == 0)
|
||||||
|
{
|
||||||
|
/* if not sleeping, it's ok if the transition happens only once */
|
||||||
|
CU_ASSERT(listener_state.w0_alive > 0);
|
||||||
|
}
|
||||||
|
else if (sleep <= DDS_MSECS(10))
|
||||||
|
{
|
||||||
|
/* if sleeping briefly, expect the a good number of writes to toggle liveliness */
|
||||||
|
CU_ASSERT(listener_state.w0_alive >= nsamples / 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* if sleeping, expect the vast majority (90%) of the writes to toggle liveliness */
|
||||||
|
CU_ASSERT(listener_state.w0_alive >= nsamples - nsamples / 10);
|
||||||
|
}
|
||||||
|
ddsrt_mutex_unlock(&listener_state.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
|
rc = dds_delete(waitset);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
rc = dds_delete(reader);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
rc = dds_delete(writer_active);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
rc = dds_delete(writer_inactive);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
rc = dds_delete(sub_topic);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
rc = dds_delete(pub_topic);
|
||||||
|
CU_ASSERT_FATAL(rc == DDS_RETCODE_OK);
|
||||||
|
|
||||||
|
ddsrt_mutex_destroy(&listener_state.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
CU_Test(ddsc_liveliness, lease_duration_zero_or_one, .init = liveliness_init, .fini = liveliness_fini, .timeout = 30)
|
||||||
|
{
|
||||||
|
static const dds_duration_t sleep[] = { 0, DDS_MSECS(10), DDS_MSECS(100) };
|
||||||
|
static const dds_liveliness_kind_t lkind[] = { DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, DDS_LIVELINESS_MANUAL_BY_TOPIC };
|
||||||
|
static const dds_duration_t ldur[] = { 0, 1 };
|
||||||
|
for (size_t sleep_idx = 0; sleep_idx < sizeof (sleep) / sizeof (sleep[0]); sleep_idx++)
|
||||||
|
{
|
||||||
|
for (size_t lkind_idx = 0; lkind_idx < sizeof (lkind) / sizeof (lkind[0]); lkind_idx++)
|
||||||
|
{
|
||||||
|
for (size_t ldur_idx = 0; ldur_idx < sizeof (ldur) / sizeof (ldur[0]); ldur_idx++)
|
||||||
|
{
|
||||||
|
dds_duration_t s = sleep[sleep_idx];
|
||||||
|
dds_liveliness_kind_t k = lkind[lkind_idx];
|
||||||
|
dds_duration_t d = ldur[ldur_idx];
|
||||||
|
printf ("lease_duration_zero_or_one: sleep = %"PRId64" lkind = %d ldur = %"PRId64"\n", s, (int) k, d);
|
||||||
|
lease_duration_zero_or_one_impl (s, k, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue