Add limited support for QoS changes
This commit adds support for changing all mutable QoS except those that affect reader/writer matching (i.e., deadline, latency budget and partition). This is simply because the recalculation of the matches hasn't been implemented yet, it is not a fundamental limitation. Implementing this basically forced fixing up a bunch of inconsistencies in handling QoS in entity creation. A silly multi-process ping-pong test built on changing the value of user data has been added. Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
parent
11a1b9d6f9
commit
a4d8aba4f9
32 changed files with 1225 additions and 361 deletions
28
src/mpt/tests/qos/CMakeLists.txt
Normal file
28
src/mpt/tests/qos/CMakeLists.txt
Normal file
|
@ -0,0 +1,28 @@
|
|||
#
|
||||
# Copyright(c) 2019 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(${MPT_CMAKE})
|
||||
|
||||
add_compile_options("-I${PROJECT_SOURCE_DIR}/core/ddsi/include")
|
||||
|
||||
idlc_generate(mpt_rwdata_lib "procs/rwdata.idl")
|
||||
|
||||
set(sources_qosmatch
|
||||
"procs/rw.c"
|
||||
"qosmatch.c")
|
||||
add_mpt_executable(mpt_qosmatch ${sources_qosmatch})
|
||||
target_link_libraries(mpt_qosmatch PRIVATE mpt_rwdata_lib)
|
||||
|
||||
set(sources_ppuserdata
|
||||
"procs/ppud.c"
|
||||
"ppuserdata.c")
|
||||
add_mpt_executable(mpt_ppuserdata ${sources_ppuserdata})
|
||||
target_link_libraries(mpt_ppuserdata PRIVATE mpt_rwdata_lib)
|
58
src/mpt/tests/qos/ppuserdata.c
Normal file
58
src/mpt/tests/qos/ppuserdata.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright(c) 2019 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 "mpt/mpt.h"
|
||||
#include "procs/ppud.h"
|
||||
|
||||
|
||||
/*
|
||||
* Checks whether participant user_data QoS changes work.
|
||||
*/
|
||||
#define TEST_A_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, true, 10)
|
||||
#define TEST_B_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, false, 0)
|
||||
MPT_TestProcess(qos, ppuserdata, a, ppud, TEST_A_ARGS);
|
||||
MPT_TestProcess(qos, ppuserdata, b, ppud, TEST_B_ARGS);
|
||||
MPT_Test(qos, ppuserdata, .init=ppud_init, .fini=ppud_fini);
|
||||
#undef TEST_A_ARGS
|
||||
#undef TEST_B_ARGS
|
||||
|
||||
/*
|
||||
* Checks whether reader/writer user_data QoS changes work.
|
||||
*/
|
||||
#define TEST_A_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwuserdata", true, 10)
|
||||
#define TEST_B_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwuserdata", false, 0)
|
||||
MPT_TestProcess(qos, rwuserdata, a, rwud, TEST_A_ARGS);
|
||||
MPT_TestProcess(qos, rwuserdata, b, rwud, TEST_B_ARGS);
|
||||
MPT_Test(qos, rwuserdata, .init=ppud_init, .fini=ppud_fini);
|
||||
#undef TEST_A_ARGS
|
||||
#undef TEST_B_ARGS
|
||||
|
||||
/*
|
||||
* Checks whether topic_data QoS changes become visible in reader/writer.
|
||||
*/
|
||||
#define TEST_A_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwtopicdata", true, 10)
|
||||
#define TEST_B_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwtopicdata", false, 0)
|
||||
MPT_TestProcess(qos, rwtopicdata, a, rwtd, TEST_A_ARGS);
|
||||
MPT_TestProcess(qos, rwtopicdata, b, rwtd, TEST_B_ARGS);
|
||||
MPT_Test(qos, rwtopicdata, .init=ppud_init, .fini=ppud_fini);
|
||||
#undef TEST_A_ARGS
|
||||
#undef TEST_B_ARGS
|
||||
|
||||
/*
|
||||
* Checks whether group_data QoS changes become visible in reader/writer.
|
||||
*/
|
||||
#define TEST_A_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwgroupdata", true, 10)
|
||||
#define TEST_B_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "rwgroupdata", false, 0)
|
||||
MPT_TestProcess(qos, rwgroupdata, a, rwgd, TEST_A_ARGS);
|
||||
MPT_TestProcess(qos, rwgroupdata, b, rwgd, TEST_B_ARGS);
|
||||
MPT_Test(qos, rwgroupdata, .init=ppud_init, .fini=ppud_fini);
|
||||
#undef TEST_A_ARGS
|
||||
#undef TEST_B_ARGS
|
569
src/mpt/tests/qos/procs/ppud.c
Normal file
569
src/mpt/tests/qos/procs/ppud.c
Normal file
|
@ -0,0 +1,569 @@
|
|||
/*
|
||||
* Copyright(c) 2019 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mpt/mpt.h"
|
||||
#include "rwdata.h"
|
||||
|
||||
#include "dds/dds.h"
|
||||
|
||||
#include "dds/ddsrt/time.h"
|
||||
#include "dds/ddsrt/process.h"
|
||||
#include "dds/ddsrt/sockets.h"
|
||||
#include "dds/ddsrt/heap.h"
|
||||
|
||||
void ppud_init (void) { }
|
||||
void ppud_fini (void) { }
|
||||
|
||||
static const char *exp_ud[] = {
|
||||
"a", "bc", "def", ""
|
||||
};
|
||||
|
||||
MPT_ProcessEntry (ppud,
|
||||
MPT_Args (dds_domainid_t domainid,
|
||||
bool active,
|
||||
unsigned ncycles))
|
||||
{
|
||||
dds_entity_t dp, rd, ws;
|
||||
dds_instance_handle_t dpih;
|
||||
dds_return_t rc;
|
||||
dds_qos_t *qos;
|
||||
int id = (int) ddsrt_getpid ();
|
||||
|
||||
printf ("=== [Check(%d)] active=%d ncycles=%u Start(%d) ...\n", id, active, ncycles, (int) domainid);
|
||||
|
||||
qos = dds_create_qos ();
|
||||
dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0);
|
||||
dp = dds_create_participant (domainid, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (dp, 0, "Could not create participant: %s\n", dds_strretcode (dp));
|
||||
rc = dds_get_instance_handle (dp, &dpih);
|
||||
MPT_ASSERT_FATAL_EQ (rc, 0, "Could not get participant instance handle: %s\n", dds_strretcode (rc));
|
||||
rd = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSPARTICIPANT, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (rd, 0, "Could not create DCPSParticipant reader: %s\n", dds_strretcode (rd));
|
||||
rc = dds_set_status_mask (rd, DDS_DATA_AVAILABLE_STATUS);
|
||||
MPT_ASSERT_FATAL_EQ (rc, 0, "Could not set status mask: %s\n", dds_strretcode (rc));
|
||||
ws = dds_create_waitset (dp);
|
||||
MPT_ASSERT_FATAL_GT (ws, 0, "Could not create waitset: %s\n", dds_strretcode (ws));
|
||||
rc = dds_waitset_attach (ws, rd, 0);
|
||||
MPT_ASSERT_FATAL_EQ (rc, 0, "Could not attach reader to waitset: %s\n", dds_strretcode (rc));
|
||||
|
||||
bool done = false;
|
||||
bool first = true;
|
||||
unsigned exp_index = 0;
|
||||
unsigned exp_cycle = 0;
|
||||
while (!done)
|
||||
{
|
||||
rc = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY);
|
||||
MPT_ASSERT_FATAL_GEQ (rc, 0, "Wait failed: %s\n", dds_strretcode (ws));
|
||||
|
||||
void *raw = NULL;
|
||||
dds_sample_info_t si;
|
||||
int32_t n;
|
||||
while ((n = dds_take (rd, &raw, &si, 1, 1)) == 1)
|
||||
{
|
||||
const dds_builtintopic_participant_t *sample = raw;
|
||||
if (si.instance_state != DDS_IST_ALIVE)
|
||||
done = true;
|
||||
else if (si.instance_handle == dpih || !si.valid_data)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
void *ud = NULL;
|
||||
size_t usz = 0;
|
||||
if (!dds_qget_userdata (sample->qos, &ud, &usz))
|
||||
printf ("%d: user data not set in QoS\n", id);
|
||||
if (first && usz == 0)
|
||||
{
|
||||
dds_qset_userdata (qos, "X", 1);
|
||||
rc = dds_set_qos (dp, qos);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc));
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *exp = exp_ud[exp_index];
|
||||
if (first && strcmp (ud, "X") == 0)
|
||||
exp = "X";
|
||||
const size_t expsz = strlen (exp);
|
||||
bool eq = (usz == expsz && (usz == 0 || memcmp (ud, exp, usz) == 0));
|
||||
printf ("%d: expected %u %zu/%s received %zu/%s\n",
|
||||
id, exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)");
|
||||
MPT_ASSERT (eq, "User data mismatch: expected %u %zu/%s received %zu/%s\n",
|
||||
exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)");
|
||||
if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0]))
|
||||
{
|
||||
exp_index = 0;
|
||||
exp_cycle++;
|
||||
}
|
||||
|
||||
if (active && exp_cycle == ncycles)
|
||||
done = true;
|
||||
else
|
||||
{
|
||||
const void *newud;
|
||||
size_t newusz;
|
||||
if (!active)
|
||||
{
|
||||
/* Set user data to the same value in response */
|
||||
newud = ud; newusz = usz;
|
||||
dds_qset_userdata (qos, ud, usz);
|
||||
}
|
||||
else /* Set next agreed value */
|
||||
{
|
||||
newud = exp_ud[exp_index]; newusz = strlen (exp_ud[exp_index]);
|
||||
dds_qset_userdata (qos, newud, newusz);
|
||||
}
|
||||
|
||||
rc = dds_set_qos (dp, qos);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc));
|
||||
|
||||
dds_qos_t *chk = dds_create_qos ();
|
||||
rc = dds_get_qos (dp, chk);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Get QoS failed: %s\n", dds_strretcode (rc));
|
||||
|
||||
void *chkud = NULL;
|
||||
size_t chkusz = 0;
|
||||
if (!dds_qget_userdata (chk, &chkud, &chkusz))
|
||||
MPT_ASSERT (0, "Check QoS: no user data present\n");
|
||||
MPT_ASSERT (chkusz == newusz && (newusz == 0 || memcmp (chkud, newud, newusz) == 0),
|
||||
"Retrieved user data differs from user data just set (%zu/%s vs %zu/%s)\n",
|
||||
chkusz, chkud ? (char *) chkud : "(null)", newusz, newud ? (char *) newud : "(null)");
|
||||
dds_free (chkud);
|
||||
dds_delete_qos (chk);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
dds_free (ud);
|
||||
}
|
||||
}
|
||||
MPT_ASSERT_FATAL_EQ (n, 0, "Read failed: %s\n", dds_strretcode (n));
|
||||
dds_return_loan (rd, &raw, 1);
|
||||
}
|
||||
dds_delete_qos (qos);
|
||||
rc = dds_delete (dp);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n");
|
||||
printf ("=== [Publisher(%d)] Done\n", id);
|
||||
}
|
||||
|
||||
MPT_ProcessEntry (rwud,
|
||||
MPT_Args (dds_domainid_t domainid,
|
||||
const char *topic_name,
|
||||
bool active,
|
||||
unsigned ncycles))
|
||||
{
|
||||
dds_entity_t dp, tp, ep, rdep, ws;
|
||||
dds_return_t rc;
|
||||
dds_qos_t *qos;
|
||||
int id = (int) ddsrt_getpid ();
|
||||
|
||||
printf ("=== [Check(%d)] active=%d ncycles=%u Start(%d) ...\n", id, active, ncycles, (int) domainid);
|
||||
|
||||
qos = dds_create_qos ();
|
||||
dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0);
|
||||
dp = dds_create_participant (domainid, NULL, NULL);
|
||||
MPT_ASSERT_FATAL_GT (dp, 0, "Could not create participant: %s\n", dds_strretcode (dp));
|
||||
tp = dds_create_topic (dp, &RWData_Msg_desc, topic_name, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (tp, 0, "Could not create topic: %s\n", dds_strretcode (tp));
|
||||
if (active)
|
||||
{
|
||||
rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSSubscription reader: %s\n", dds_strretcode (rdep));
|
||||
ep = dds_create_writer (dp, tp, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (ep, 0, "Could not create writer: %s\n", dds_strretcode (ep));
|
||||
}
|
||||
else
|
||||
{
|
||||
rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSPublication reader: %s\n", dds_strretcode (rdep));
|
||||
ep = dds_create_reader (dp, tp, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (ep, 0, "Could not create reader: %s\n", dds_strretcode (ep));
|
||||
}
|
||||
rc = dds_set_status_mask (rdep, DDS_DATA_AVAILABLE_STATUS);
|
||||
MPT_ASSERT_FATAL_EQ (rc, 0, "Could not set status mask: %s\n", dds_strretcode (rc));
|
||||
ws = dds_create_waitset (dp);
|
||||
MPT_ASSERT_FATAL_GT (ws, 0, "Could not create waitset: %s\n", dds_strretcode (ws));
|
||||
rc = dds_waitset_attach (ws, rdep, 0);
|
||||
MPT_ASSERT_FATAL_EQ (rc, 0, "Could not attach built-in reader to waitset: %s\n", dds_strretcode (rc));
|
||||
|
||||
bool done = false;
|
||||
bool first = true;
|
||||
unsigned exp_index = 0;
|
||||
unsigned exp_cycle = 0;
|
||||
while (!done)
|
||||
{
|
||||
rc = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY);
|
||||
MPT_ASSERT_FATAL_GEQ (rc, 0, "Wait failed: %s\n", dds_strretcode (ws));
|
||||
|
||||
void *raw = NULL;
|
||||
dds_sample_info_t si;
|
||||
int32_t n;
|
||||
while ((n = dds_take (rdep, &raw, &si, 1, 1)) == 1)
|
||||
{
|
||||
const dds_builtintopic_endpoint_t *sample = raw;
|
||||
if (si.instance_state != DDS_IST_ALIVE)
|
||||
done = true;
|
||||
else if (!si.valid_data || strcmp (sample->topic_name, topic_name) != 0)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
void *ud = NULL;
|
||||
size_t usz = 0;
|
||||
if (!dds_qget_userdata (sample->qos, &ud, &usz))
|
||||
printf ("%d: user data not set in QoS\n", id);
|
||||
if (first && usz == 0)
|
||||
{
|
||||
dds_qset_userdata (qos, "X", 1);
|
||||
rc = dds_set_qos (ep, qos);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc));
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *exp = exp_ud[exp_index];
|
||||
if (first && strcmp (ud, "X") == 0)
|
||||
exp = "X";
|
||||
const size_t expsz = first ? 1 : strlen (exp);
|
||||
bool eq = (usz == expsz && (usz == 0 || memcmp (ud, exp, usz) == 0));
|
||||
printf ("%d: expected %u %zu/%s received %zu/%s\n",
|
||||
id, exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)");
|
||||
MPT_ASSERT (eq, "User data mismatch: expected %u %zu/%s received %zu/%s\n",
|
||||
exp_index, expsz, exp, usz, ud ? (char *) ud : "(null)");
|
||||
if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0]))
|
||||
{
|
||||
exp_index = 0;
|
||||
exp_cycle++;
|
||||
}
|
||||
|
||||
if (active && exp_cycle == ncycles)
|
||||
done = true;
|
||||
else
|
||||
{
|
||||
const void *newud;
|
||||
size_t newusz;
|
||||
if (!active)
|
||||
{
|
||||
/* Set user data to the same value in response */
|
||||
newud = ud; newusz = usz;
|
||||
dds_qset_userdata (qos, ud, usz);
|
||||
}
|
||||
else /* Set next agreed value */
|
||||
{
|
||||
newud = exp_ud[exp_index]; newusz = strlen (exp_ud[exp_index]);
|
||||
dds_qset_userdata (qos, newud, newusz);
|
||||
}
|
||||
|
||||
rc = dds_set_qos (ep, qos);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc));
|
||||
|
||||
dds_qos_t *chk = dds_create_qos ();
|
||||
rc = dds_get_qos (ep, chk);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Get QoS failed: %s\n", dds_strretcode (rc));
|
||||
|
||||
void *chkud = NULL;
|
||||
size_t chkusz = 0;
|
||||
if (!dds_qget_userdata (chk, &chkud, &chkusz))
|
||||
MPT_ASSERT (0, "Check QoS: no user data present\n");
|
||||
MPT_ASSERT (chkusz == newusz && (newusz == 0 || memcmp (chkud, newud, newusz) == 0),
|
||||
"Retrieved user data differs from user data just set (%zu/%s vs %zu/%s)\n",
|
||||
chkusz, chkud ? (char *) chkud : "(null)", newusz, newud ? (char *) newud : "(null)");
|
||||
dds_free (chkud);
|
||||
dds_delete_qos (chk);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
dds_free (ud);
|
||||
}
|
||||
}
|
||||
MPT_ASSERT_FATAL_EQ (n, 0, "Read failed: %s\n", dds_strretcode (n));
|
||||
dds_return_loan (rdep, &raw, 1);
|
||||
}
|
||||
dds_delete_qos (qos);
|
||||
rc = dds_delete (dp);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n");
|
||||
printf ("=== [Publisher(%d)] Done\n", id);
|
||||
}
|
||||
|
||||
MPT_ProcessEntry (rwtd,
|
||||
MPT_Args (dds_domainid_t domainid,
|
||||
const char *topic_name,
|
||||
bool active,
|
||||
unsigned ncycles))
|
||||
{
|
||||
dds_entity_t dp, tp, ep, rdep, ws;
|
||||
dds_return_t rc;
|
||||
dds_qos_t *qos;
|
||||
int id = (int) ddsrt_getpid ();
|
||||
|
||||
printf ("=== [Check(%d)] active=%d ncycles=%u Start(%d) ...\n", id, active, ncycles, (int) domainid);
|
||||
|
||||
qos = dds_create_qos ();
|
||||
dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0);
|
||||
dp = dds_create_participant (domainid, NULL, NULL);
|
||||
MPT_ASSERT_FATAL_GT (dp, 0, "Could not create participant: %s\n", dds_strretcode (dp));
|
||||
tp = dds_create_topic (dp, &RWData_Msg_desc, topic_name, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (tp, 0, "Could not create topic: %s\n", dds_strretcode (tp));
|
||||
if (active)
|
||||
{
|
||||
rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSSubscription reader: %s\n", dds_strretcode (rdep));
|
||||
ep = dds_create_writer (dp, tp, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (ep, 0, "Could not create writer: %s\n", dds_strretcode (ep));
|
||||
}
|
||||
else
|
||||
{
|
||||
rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSPublication reader: %s\n", dds_strretcode (rdep));
|
||||
ep = dds_create_reader (dp, tp, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (ep, 0, "Could not create reader: %s\n", dds_strretcode (ep));
|
||||
}
|
||||
rc = dds_set_status_mask (rdep, DDS_DATA_AVAILABLE_STATUS);
|
||||
MPT_ASSERT_FATAL_EQ (rc, 0, "Could not set status mask: %s\n", dds_strretcode (rc));
|
||||
ws = dds_create_waitset (dp);
|
||||
MPT_ASSERT_FATAL_GT (ws, 0, "Could not create waitset: %s\n", dds_strretcode (ws));
|
||||
rc = dds_waitset_attach (ws, rdep, 0);
|
||||
MPT_ASSERT_FATAL_EQ (rc, 0, "Could not attach built-in reader to waitset: %s\n", dds_strretcode (rc));
|
||||
|
||||
bool done = false;
|
||||
bool first = true;
|
||||
unsigned exp_index = 0;
|
||||
unsigned exp_cycle = 0;
|
||||
while (!done)
|
||||
{
|
||||
rc = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY);
|
||||
MPT_ASSERT_FATAL_GEQ (rc, 0, "Wait failed: %s\n", dds_strretcode (ws));
|
||||
|
||||
void *raw = NULL;
|
||||
dds_sample_info_t si;
|
||||
int32_t n;
|
||||
while ((n = dds_take (rdep, &raw, &si, 1, 1)) == 1)
|
||||
{
|
||||
const dds_builtintopic_endpoint_t *sample = raw;
|
||||
if (si.instance_state != DDS_IST_ALIVE)
|
||||
done = true;
|
||||
else if (!si.valid_data || strcmp (sample->topic_name, topic_name) != 0)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
void *td = NULL;
|
||||
size_t tsz = 0;
|
||||
if (!dds_qget_topicdata (sample->qos, &td, &tsz))
|
||||
printf ("%d: topic data not set in QoS\n", id);
|
||||
if (first && tsz == 0)
|
||||
{
|
||||
dds_qset_topicdata (qos, "X", 1);
|
||||
rc = dds_set_qos (tp, qos);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc));
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *exp = exp_ud[exp_index];
|
||||
if (first && strcmp (td, "X") == 0)
|
||||
exp = "X";
|
||||
const size_t expsz = first ? 1 : strlen (exp);
|
||||
bool eq = (tsz == expsz && (tsz == 0 || memcmp (td, exp, tsz) == 0));
|
||||
printf ("%d: expected %u %zu/%s received %zu/%s\n",
|
||||
id, exp_index, expsz, exp, tsz, td ? (char *) td : "(null)");
|
||||
MPT_ASSERT (eq, "Topic data mismatch: expected %u %zu/%s received %zu/%s\n",
|
||||
exp_index, expsz, exp, tsz, td ? (char *) td : "(null)");
|
||||
if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0]))
|
||||
{
|
||||
exp_index = 0;
|
||||
exp_cycle++;
|
||||
}
|
||||
|
||||
if (active && exp_cycle == ncycles)
|
||||
done = true;
|
||||
else
|
||||
{
|
||||
const void *newtd;
|
||||
size_t newtsz;
|
||||
if (!active)
|
||||
{
|
||||
/* Set topic data to the same value in response */
|
||||
newtd = td; newtsz = tsz;
|
||||
dds_qset_topicdata (qos, td, tsz);
|
||||
}
|
||||
else /* Set next agreed value */
|
||||
{
|
||||
newtd = exp_ud[exp_index]; newtsz = strlen (exp_ud[exp_index]);
|
||||
dds_qset_topicdata (qos, newtd, newtsz);
|
||||
}
|
||||
|
||||
rc = dds_set_qos (tp, qos);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc));
|
||||
|
||||
dds_qos_t *chk = dds_create_qos ();
|
||||
rc = dds_get_qos (ep, chk);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Get QoS failed: %s\n", dds_strretcode (rc));
|
||||
|
||||
void *chktd = NULL;
|
||||
size_t chktsz = 0;
|
||||
if (!dds_qget_topicdata (chk, &chktd, &chktsz))
|
||||
MPT_ASSERT (0, "Check QoS: no topic data present\n");
|
||||
MPT_ASSERT (chktsz == newtsz && (newtsz == 0 || memcmp (chktd, newtd, newtsz) == 0),
|
||||
"Retrieved topic data differs from topic data just set (%zu/%s vs %zu/%s)\n",
|
||||
chktsz, chktd ? (char *) chktd : "(null)", newtsz, newtd ? (char *) newtd : "(null)");
|
||||
dds_free (chktd);
|
||||
dds_delete_qos (chk);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
dds_free (td);
|
||||
}
|
||||
}
|
||||
MPT_ASSERT_FATAL_EQ (n, 0, "Read failed: %s\n", dds_strretcode (n));
|
||||
dds_return_loan (rdep, &raw, 1);
|
||||
}
|
||||
dds_delete_qos (qos);
|
||||
rc = dds_delete (dp);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n");
|
||||
printf ("=== [Publisher(%d)] Done\n", id);
|
||||
}
|
||||
|
||||
MPT_ProcessEntry (rwgd,
|
||||
MPT_Args (dds_domainid_t domainid,
|
||||
const char *topic_name,
|
||||
bool active,
|
||||
unsigned ncycles))
|
||||
{
|
||||
dds_entity_t dp, tp, ep, rdep, grp, ws;
|
||||
dds_return_t rc;
|
||||
dds_qos_t *qos;
|
||||
int id = (int) ddsrt_getpid ();
|
||||
|
||||
printf ("=== [Check(%d)] active=%d ncycles=%u Start(%d) ...\n", id, active, ncycles, (int) domainid);
|
||||
|
||||
qos = dds_create_qos ();
|
||||
dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0);
|
||||
dp = dds_create_participant (domainid, NULL, NULL);
|
||||
MPT_ASSERT_FATAL_GT (dp, 0, "Could not create participant: %s\n", dds_strretcode (dp));
|
||||
tp = dds_create_topic (dp, &RWData_Msg_desc, topic_name, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (tp, 0, "Could not create topic: %s\n", dds_strretcode (tp));
|
||||
if (active)
|
||||
{
|
||||
rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSSubscription reader: %s\n", dds_strretcode (rdep));
|
||||
ep = dds_create_writer (dp, tp, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (ep, 0, "Could not create writer: %s\n", dds_strretcode (ep));
|
||||
}
|
||||
else
|
||||
{
|
||||
rdep = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (rdep, 0, "Could not create DCPSPublication reader: %s\n", dds_strretcode (rdep));
|
||||
ep = dds_create_reader (dp, tp, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (ep, 0, "Could not create reader: %s\n", dds_strretcode (ep));
|
||||
}
|
||||
grp = dds_get_parent (ep);
|
||||
MPT_ASSERT_FATAL_GT (grp, 0, "Could not get pub/sub from wr/rd: %s\n", dds_strretcode (grp));
|
||||
rc = dds_set_status_mask (rdep, DDS_DATA_AVAILABLE_STATUS);
|
||||
MPT_ASSERT_FATAL_EQ (rc, 0, "Could not set status mask: %s\n", dds_strretcode (rc));
|
||||
ws = dds_create_waitset (dp);
|
||||
MPT_ASSERT_FATAL_GT (ws, 0, "Could not create waitset: %s\n", dds_strretcode (ws));
|
||||
rc = dds_waitset_attach (ws, rdep, 0);
|
||||
MPT_ASSERT_FATAL_EQ (rc, 0, "Could not attach built-in reader to waitset: %s\n", dds_strretcode (rc));
|
||||
|
||||
bool done = false;
|
||||
bool first = true;
|
||||
unsigned exp_index = 0;
|
||||
unsigned exp_cycle = 0;
|
||||
while (!done)
|
||||
{
|
||||
rc = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY);
|
||||
MPT_ASSERT_FATAL_GEQ (rc, 0, "Wait failed: %s\n", dds_strretcode (ws));
|
||||
|
||||
void *raw = NULL;
|
||||
dds_sample_info_t si;
|
||||
int32_t n;
|
||||
while ((n = dds_take (rdep, &raw, &si, 1, 1)) == 1)
|
||||
{
|
||||
const dds_builtintopic_endpoint_t *sample = raw;
|
||||
if (si.instance_state != DDS_IST_ALIVE)
|
||||
done = true;
|
||||
else if (!si.valid_data || strcmp (sample->topic_name, topic_name) != 0)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
void *gd = NULL;
|
||||
size_t gsz = 0;
|
||||
if (!dds_qget_groupdata (sample->qos, &gd, &gsz))
|
||||
printf ("%d: group data not set in QoS\n", id);
|
||||
if (first && gsz == 0)
|
||||
{
|
||||
dds_qset_groupdata (qos, "X", 1);
|
||||
rc = dds_set_qos (grp, qos);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc));
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *exp = exp_ud[exp_index];
|
||||
if (first && strcmp (gd, "X") == 0)
|
||||
exp = "X";
|
||||
const size_t expsz = first ? 1 : strlen (exp);
|
||||
bool eq = (gsz == expsz && (gsz == 0 || memcmp (gd, exp, gsz) == 0));
|
||||
printf ("%d: expected %u %zu/%s received %zu/%s\n",
|
||||
id, exp_index, expsz, exp, gsz, gd ? (char *) gd : "(null)");
|
||||
MPT_ASSERT (eq, "Group data mismatch: expected %u %zu/%s received %zu/%s\n",
|
||||
exp_index, expsz, exp, gsz, gd ? (char *) gd : "(null)");
|
||||
if (strcmp (exp, "X") != 0 && ++exp_index == sizeof (exp_ud) / sizeof (exp_ud[0]))
|
||||
{
|
||||
exp_index = 0;
|
||||
exp_cycle++;
|
||||
}
|
||||
|
||||
if (active && exp_cycle == ncycles)
|
||||
done = true;
|
||||
else
|
||||
{
|
||||
const void *newgd;
|
||||
size_t newgsz;
|
||||
if (!active)
|
||||
{
|
||||
/* Set group data to the same value in response */
|
||||
newgd = gd; newgsz = gsz;
|
||||
dds_qset_groupdata (qos, gd, gsz);
|
||||
}
|
||||
else /* Set next agreed value */
|
||||
{
|
||||
newgd = exp_ud[exp_index]; newgsz = strlen (exp_ud[exp_index]);
|
||||
dds_qset_groupdata (qos, newgd, newgsz);
|
||||
}
|
||||
|
||||
rc = dds_set_qos (grp, qos);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Set QoS failed: %s\n", dds_strretcode (rc));
|
||||
|
||||
dds_qos_t *chk = dds_create_qos ();
|
||||
rc = dds_get_qos (ep, chk);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "Get QoS failed: %s\n", dds_strretcode (rc));
|
||||
|
||||
void *chkgd = NULL;
|
||||
size_t chkgsz = 0;
|
||||
if (!dds_qget_groupdata (chk, &chkgd, &chkgsz))
|
||||
MPT_ASSERT (0, "Check QoS: no group data present\n");
|
||||
MPT_ASSERT (chkgsz == newgsz && (newgsz == 0 || memcmp (chkgd, newgd, newgsz) == 0),
|
||||
"Retrieved group data differs from group data just set (%zu/%s vs %zu/%s)\n",
|
||||
chkgsz, chkgd ? (char *) chkgd : "(null)", newgsz, newgd ? (char *) newgd : "(null)");
|
||||
dds_free (chkgd);
|
||||
dds_delete_qos (chk);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
dds_free (gd);
|
||||
}
|
||||
}
|
||||
MPT_ASSERT_FATAL_EQ (n, 0, "Read failed: %s\n", dds_strretcode (n));
|
||||
dds_return_loan (rdep, &raw, 1);
|
||||
}
|
||||
dds_delete_qos (qos);
|
||||
rc = dds_delete (dp);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n");
|
||||
printf ("=== [Publisher(%d)] Done\n", id);
|
||||
}
|
55
src/mpt/tests/qos/procs/ppud.h
Normal file
55
src/mpt/tests/qos/procs/ppud.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright(c) 2019 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
|
||||
*/
|
||||
|
||||
#ifndef MPT_QOSMATCH_PROCS_PPUD_H
|
||||
#define MPT_QOSMATCH_PROCS_PPUD_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/dds.h"
|
||||
#include "mpt/mpt.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ppud_init (void);
|
||||
void ppud_fini (void);
|
||||
|
||||
MPT_ProcessEntry (ppud,
|
||||
MPT_Args (dds_domainid_t domainid,
|
||||
bool active,
|
||||
unsigned ncycles));
|
||||
|
||||
MPT_ProcessEntry (rwud,
|
||||
MPT_Args (dds_domainid_t domainid,
|
||||
const char *topic_name,
|
||||
bool active,
|
||||
unsigned ncycles));
|
||||
|
||||
MPT_ProcessEntry (rwtd,
|
||||
MPT_Args (dds_domainid_t domainid,
|
||||
const char *topic_name,
|
||||
bool active,
|
||||
unsigned ncycles));
|
||||
|
||||
MPT_ProcessEntry (rwgd,
|
||||
MPT_Args (dds_domainid_t domainid,
|
||||
const char *topic_name,
|
||||
bool active,
|
||||
unsigned ncycles));
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
387
src/mpt/tests/qos/procs/rw.c
Normal file
387
src/mpt/tests/qos/procs/rw.c
Normal file
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
* Copyright(c) 2019 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mpt/mpt.h"
|
||||
|
||||
#include "dds/dds.h"
|
||||
#include "rwdata.h"
|
||||
|
||||
#include "dds/ddsrt/time.h"
|
||||
#include "dds/ddsrt/process.h"
|
||||
#include "dds/ddsrt/sockets.h"
|
||||
#include "dds/ddsrt/heap.h"
|
||||
|
||||
#include "dds/ddsi/q_xqos.h"
|
||||
|
||||
#define NPUB 10
|
||||
#define NWR_PUB 2
|
||||
|
||||
void rw_init (void)
|
||||
{
|
||||
}
|
||||
|
||||
void rw_fini (void)
|
||||
{
|
||||
}
|
||||
|
||||
static void setqos (dds_qos_t *q, size_t i, bool isrd, bool create)
|
||||
{
|
||||
size_t psi = i - (i % NWR_PUB);
|
||||
/* Participant, publisher & topic get created with i == 0,
|
||||
so make sure those have some crazy data set. The writers
|
||||
should inherit the topic and group data, but the user data
|
||||
should be updated for each writer */
|
||||
if (create)
|
||||
{
|
||||
if (psi == 1)
|
||||
{
|
||||
dds_qset_userdata (q, NULL, 0);
|
||||
dds_qset_topicdata (q, NULL, 0);
|
||||
dds_qset_groupdata (q, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[20];
|
||||
snprintf (buf, sizeof (buf), "ud%zu%c", i, isrd ? 'r' : 'w');
|
||||
dds_qset_userdata (q, buf, strlen (buf));
|
||||
snprintf (buf, sizeof (buf), "td%zu", i);
|
||||
dds_qset_topicdata (q, buf, strlen (buf));
|
||||
snprintf (buf, sizeof (buf), "gd%zu", psi);
|
||||
dds_qset_groupdata (q, buf, strlen (buf));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (psi == 1)
|
||||
{
|
||||
dds_qset_userdata (q, NULL, 0);
|
||||
dds_qset_topicdata (q, NULL, 0);
|
||||
dds_qset_groupdata (q, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[20];
|
||||
snprintf (buf, sizeof (buf), "ud%zu%c", i, isrd ? 'r' : 'w');
|
||||
dds_qset_userdata (q, buf, strlen (buf));
|
||||
snprintf (buf, sizeof (buf), "td%zu", (size_t) 0);
|
||||
dds_qset_topicdata (q, buf, strlen (buf));
|
||||
snprintf (buf, sizeof (buf), "gd%zu", psi);
|
||||
dds_qset_groupdata (q, buf, strlen (buf));
|
||||
}
|
||||
}
|
||||
|
||||
/* Cyclone's accepting unimplemented QoS settings is a bug, but it does allow
|
||||
us to feed it all kinds of nonsense and see whether discovery manages it */
|
||||
|
||||
/* this makes topic transient-local, keep-last 1 */
|
||||
dds_qset_durability (q, (dds_durability_kind_t) ((i + 1) % 4));
|
||||
dds_qset_history (q, (dds_history_kind_t) ((i + 1) % 2), (int32_t) (i + 1));
|
||||
dds_qset_resource_limits (q, (int32_t) i + 3, (int32_t) i + 2, (int32_t) i + 1);
|
||||
dds_qset_presentation (q, (dds_presentation_access_scope_kind_t) ((psi + 1) % 3), 1, 1);
|
||||
dds_qset_lifespan (q, INT64_C (23456789012345678) + (int32_t) i);
|
||||
dds_qset_deadline (q, INT64_C (67890123456789012) + (int32_t) i);
|
||||
dds_qset_latency_budget (q, INT64_C (45678901234567890) + (int32_t) i);
|
||||
dds_qset_ownership (q, (dds_ownership_kind_t) ((i + 1) % 2));
|
||||
dds_qset_ownership_strength (q, 0x12345670 + (int32_t) i);
|
||||
dds_qset_liveliness (q, (dds_liveliness_kind_t) ((i + i) % 2), INT64_C (456789012345678901) + (int32_t) i);
|
||||
dds_qset_time_based_filter (q, INT64_C (34567890123456789) + (int32_t) i); /* must be <= deadline */
|
||||
if (psi == 0)
|
||||
dds_qset_partition1 (q, "p");
|
||||
else if (psi == 1)
|
||||
dds_qset_partition (q, 0, NULL);
|
||||
else
|
||||
{
|
||||
char **ps = ddsrt_malloc (psi * sizeof (*ps));
|
||||
for (size_t j = 0; j < psi; j++)
|
||||
{
|
||||
const size_t n = 40;
|
||||
ps[j] = ddsrt_malloc (n);
|
||||
snprintf (ps[j], n, "p%zu_%zu", psi, isrd ? (psi-j-1) : j);
|
||||
}
|
||||
dds_qset_partition (q, (uint32_t) psi, (const char **) ps);
|
||||
for (size_t j = 0; j < psi; j++)
|
||||
ddsrt_free (ps[j]);
|
||||
ddsrt_free (ps);
|
||||
}
|
||||
dds_qset_reliability (q, (dds_reliability_kind_t) ((i + 1) % 2), INT64_C (890123456789012345) + (int32_t) i);
|
||||
dds_qset_transport_priority (q, 0x23456701 + (int32_t) i);
|
||||
dds_qset_destination_order (q, (dds_destination_order_kind_t) ((i + 1) % 2));
|
||||
dds_qset_writer_data_lifecycle (q, ((i + 1) % 2) != 0);
|
||||
dds_qset_reader_data_lifecycle (q, INT64_C (41234567890123456) + (int32_t) i, INT64_C (912345678901234567) + (int32_t) i);
|
||||
dds_qset_durability_service (q, INT64_C (123456789012345678) + (int32_t) i, (dds_history_kind_t) ((i + 1) % 2), (int32_t) (i + 1), (int32_t) i + 3, (int32_t) i + 2, (int32_t) i + 1);
|
||||
}
|
||||
|
||||
static bool pubsub_qos_eq_h (const dds_qos_t *a, dds_entity_t ent)
|
||||
{
|
||||
dds_qos_t *b = dds_create_qos ();
|
||||
dds_get_qos (ent, b);
|
||||
/* internal interface is more luxurious that a simple compare for equality, and
|
||||
using that here saves us a ton of code */
|
||||
uint64_t delta = nn_xqos_delta (a, b, QP_GROUP_DATA | QP_PRESENTATION | QP_PARTITION);
|
||||
if (delta)
|
||||
{
|
||||
DDS_LOG (DDS_LC_ERROR, "pub/sub: delta = %"PRIx64"\n", delta);
|
||||
nn_log_xqos (DDS_LC_ERROR, a); DDS_LOG (DDS_LC_ERROR, "\n");
|
||||
nn_log_xqos (DDS_LC_ERROR, b); DDS_LOG (DDS_LC_ERROR, "\n");
|
||||
}
|
||||
dds_delete_qos (b);
|
||||
return delta == 0;
|
||||
}
|
||||
|
||||
static uint64_t reader_qos_delta (const dds_qos_t *a, const dds_qos_t *b)
|
||||
{
|
||||
return nn_xqos_delta (a, b, QP_USER_DATA | QP_TOPIC_DATA | QP_GROUP_DATA | QP_DURABILITY | QP_HISTORY | QP_RESOURCE_LIMITS | QP_PRESENTATION | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_LIVELINESS | QP_TIME_BASED_FILTER | QP_PARTITION | QP_RELIABILITY | QP_DESTINATION_ORDER | QP_PRISMTECH_READER_DATA_LIFECYCLE);
|
||||
}
|
||||
|
||||
static bool reader_qos_eq_h (const dds_qos_t *a, dds_entity_t ent)
|
||||
{
|
||||
dds_qos_t *b = dds_create_qos ();
|
||||
dds_get_qos (ent, b);
|
||||
uint64_t delta = reader_qos_delta (a, b);
|
||||
if (delta)
|
||||
{
|
||||
DDS_LOG (DDS_LC_ERROR, "reader: delta = %"PRIx64"\n", delta);
|
||||
nn_log_xqos (DDS_LC_ERROR, a); DDS_LOG (DDS_LC_ERROR, "\n");
|
||||
nn_log_xqos (DDS_LC_ERROR, b); DDS_LOG (DDS_LC_ERROR, "\n");
|
||||
}
|
||||
dds_delete_qos (b);
|
||||
return delta == 0;
|
||||
}
|
||||
|
||||
static uint64_t writer_qos_delta (const dds_qos_t *a, const dds_qos_t *b)
|
||||
{
|
||||
return nn_xqos_delta (a, b, QP_USER_DATA | QP_TOPIC_DATA | QP_GROUP_DATA | QP_DURABILITY | QP_HISTORY | QP_RESOURCE_LIMITS | QP_PRESENTATION | QP_LIFESPAN | QP_DEADLINE | QP_LATENCY_BUDGET | QP_OWNERSHIP | QP_OWNERSHIP_STRENGTH | QP_LIVELINESS | QP_PARTITION | QP_RELIABILITY | QP_DESTINATION_ORDER | QP_PRISMTECH_WRITER_DATA_LIFECYCLE);
|
||||
}
|
||||
|
||||
static bool writer_qos_eq_h (const dds_qos_t *a, dds_entity_t ent)
|
||||
{
|
||||
dds_qos_t *b = dds_create_qos ();
|
||||
dds_get_qos (ent, b);
|
||||
uint64_t delta = writer_qos_delta (a, b);
|
||||
if (delta)
|
||||
{
|
||||
DDS_LOG (DDS_LC_ERROR, "writer: delta = %"PRIx64"\n", delta);
|
||||
nn_log_xqos (DDS_LC_ERROR, a); DDS_LOG (DDS_LC_ERROR, "\n");
|
||||
nn_log_xqos (DDS_LC_ERROR, b); DDS_LOG (DDS_LC_ERROR, "\n");
|
||||
}
|
||||
dds_delete_qos (b);
|
||||
return delta == 0;
|
||||
}
|
||||
|
||||
MPT_ProcessEntry (rw_publisher,
|
||||
MPT_Args (dds_domainid_t domainid,
|
||||
const char *topic_name))
|
||||
{
|
||||
dds_entity_t dp;
|
||||
dds_entity_t tp;
|
||||
dds_entity_t pub[NPUB];
|
||||
dds_entity_t wr[NPUB][NWR_PUB];
|
||||
bool chk[NPUB][NWR_PUB] = { { false } };
|
||||
dds_return_t rc;
|
||||
dds_qos_t *qos;
|
||||
int id = (int) ddsrt_getpid ();
|
||||
|
||||
printf ("=== [Publisher(%d)] Start(%d) ...\n", id, (int) domainid);
|
||||
|
||||
qos = dds_create_qos ();
|
||||
setqos (qos, 0, false, true);
|
||||
dp = dds_create_participant (domainid, NULL, NULL);
|
||||
MPT_ASSERT_FATAL_GT (dp, 0, "Could not create participant: %s\n", dds_strretcode (dp));
|
||||
|
||||
tp = dds_create_topic (dp, &RWData_Msg_desc, topic_name, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (tp, 0, "Could not create topic: %s\n", dds_strretcode (tp));
|
||||
|
||||
for (size_t i = 0; i < NPUB; i++)
|
||||
{
|
||||
setqos (qos, i * NWR_PUB, false, true);
|
||||
pub[i] = dds_create_publisher (dp, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (pub[i], 0, "Could not create publisher %zu: %s\n", i, dds_strretcode (pub[i]));
|
||||
for (size_t j = 0; j < NWR_PUB; j++)
|
||||
{
|
||||
setqos (qos, i * NWR_PUB + j, false, true);
|
||||
wr[i][j] = dds_create_writer (pub[i], tp, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (wr[i][j], 0, "Could not create writer %zu %zu: %s\n", i, j, dds_strretcode (wr[i][j]));
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < NPUB; i++)
|
||||
{
|
||||
setqos (qos, i * NWR_PUB, false, false);
|
||||
MPT_ASSERT (pubsub_qos_eq_h (qos, pub[i]), "publisher %zu QoS mismatch\n", i);
|
||||
for (size_t j = 0; j < NWR_PUB; j++)
|
||||
{
|
||||
setqos (qos, i * NWR_PUB + j, false, false);
|
||||
MPT_ASSERT (writer_qos_eq_h (qos, wr[i][j]), "writer %zu %zu QoS mismatch\n", i, j);
|
||||
}
|
||||
}
|
||||
|
||||
/* Each writer should match exactly one reader */
|
||||
uint32_t nchk = 0;
|
||||
while (nchk != NPUB * NWR_PUB)
|
||||
{
|
||||
for (size_t i = 0; i < NPUB; i++)
|
||||
{
|
||||
for (size_t j = 0; j < NWR_PUB; j++)
|
||||
{
|
||||
if (chk[i][j])
|
||||
continue;
|
||||
dds_instance_handle_t ih;
|
||||
dds_builtintopic_endpoint_t *ep;
|
||||
rc = dds_get_matched_subscriptions (wr[i][j], &ih, 1);
|
||||
MPT_ASSERT (rc == 0 || rc == 1, "Unexpected return from get_matched_subscriptions for writer %zu %zu: %s\n",
|
||||
i, j, dds_strretcode (rc));
|
||||
if (rc == 1)
|
||||
{
|
||||
ep = dds_get_matched_subscription_data (wr[i][j], ih);
|
||||
MPT_ASSERT (ep != NULL, "Failed to retrieve matched subscription data for writer %zu %zu\n", i, j);
|
||||
setqos (qos, i * NWR_PUB + j, true, false);
|
||||
uint64_t delta = reader_qos_delta (qos, ep->qos);
|
||||
if (delta)
|
||||
{
|
||||
DDS_LOG (DDS_LC_ERROR, "matched reader: delta = %"PRIx64"\n", delta);
|
||||
nn_log_xqos (DDS_LC_ERROR, qos); DDS_LOG (DDS_LC_ERROR, "\n");
|
||||
nn_log_xqos (DDS_LC_ERROR, ep->qos); DDS_LOG (DDS_LC_ERROR, "\n");
|
||||
}
|
||||
MPT_ASSERT (delta == 0, "writer %zu %zu matched reader QoS mismatch\n", i, j);
|
||||
dds_delete_qos (ep->qos);
|
||||
dds_free (ep->topic_name);
|
||||
dds_free (ep->type_name);
|
||||
dds_free (ep);
|
||||
chk[i][j] = true;
|
||||
nchk++;
|
||||
}
|
||||
}
|
||||
}
|
||||
dds_sleepfor (DDS_MSECS (100));
|
||||
}
|
||||
|
||||
/* Wait until subscribers terminate */
|
||||
while (true)
|
||||
{
|
||||
for (size_t i = 0; i < NPUB; i++)
|
||||
{
|
||||
for (size_t j = 0; j < NWR_PUB; j++)
|
||||
{
|
||||
dds_publication_matched_status_t st;
|
||||
rc = dds_get_publication_matched_status (wr[i][j], &st);
|
||||
MPT_ASSERT_FATAL_EQ (rc, DDS_RETCODE_OK, "dds_get_matched_publication_status failed for writer %zu %zu: %s\n",
|
||||
i, j, dds_strretcode (rc));
|
||||
if (st.current_count)
|
||||
goto have_matches;
|
||||
}
|
||||
}
|
||||
break;
|
||||
have_matches:
|
||||
;
|
||||
}
|
||||
|
||||
dds_delete_qos (qos);
|
||||
rc = dds_delete (dp);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n");
|
||||
printf ("=== [Publisher(%d)] Done\n", id);
|
||||
}
|
||||
|
||||
MPT_ProcessEntry (rw_subscriber,
|
||||
MPT_Args (dds_domainid_t domainid,
|
||||
const char *topic_name))
|
||||
{
|
||||
dds_entity_t dp;
|
||||
dds_entity_t tp;
|
||||
dds_entity_t sub[NPUB];
|
||||
dds_entity_t rd[NPUB][NWR_PUB];
|
||||
bool chk[NPUB][NWR_PUB] = { { false } };
|
||||
dds_return_t rc;
|
||||
dds_qos_t *qos;
|
||||
int id = (int) ddsrt_getpid ();
|
||||
|
||||
printf ("=== [Subscriber(%d)] Start(%d) ...\n", id, (int) domainid);
|
||||
|
||||
qos = dds_create_qos ();
|
||||
setqos (qos, 0, true, true);
|
||||
dp = dds_create_participant (domainid, NULL, NULL);
|
||||
MPT_ASSERT_FATAL_GT (dp, 0, "Could not create participant: %s\n", dds_strretcode (dp));
|
||||
|
||||
tp = dds_create_topic (dp, &RWData_Msg_desc, topic_name, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (tp, 0, "Could not create topic: %s\n", dds_strretcode (tp));
|
||||
|
||||
for (size_t i = 0; i < NPUB; i++)
|
||||
{
|
||||
setqos (qos, i * NWR_PUB, true, true);
|
||||
sub[i] = dds_create_subscriber (dp, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (sub[i], 0, "Could not create subscriber %zu: %s\n", i, dds_strretcode (sub[i]));
|
||||
for (size_t j = 0; j < NWR_PUB; j++)
|
||||
{
|
||||
setqos (qos, i * NWR_PUB + j, true, true);
|
||||
rd[i][j] = dds_create_reader (sub[i], tp, qos, NULL);
|
||||
MPT_ASSERT_FATAL_GT (rd[i][j], 0, "Could not create reader %zu %zu: %s\n", i, j, dds_strretcode (rd[i][j]));
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < NPUB; i++)
|
||||
{
|
||||
setqos (qos, i * NWR_PUB, true, false);
|
||||
MPT_ASSERT (pubsub_qos_eq_h (qos, sub[i]), "subscriber %zu QoS mismatch\n", i);
|
||||
for (size_t j = 0; j < NWR_PUB; j++)
|
||||
{
|
||||
setqos (qos, i * NWR_PUB + j, true, false);
|
||||
MPT_ASSERT (reader_qos_eq_h (qos, rd[i][j]), "reader %zu %zu QoS mismatch\n", i, j);
|
||||
}
|
||||
}
|
||||
|
||||
/* Each writer should match exactly one reader */
|
||||
uint32_t nchk = 0;
|
||||
while (nchk != NPUB * NWR_PUB)
|
||||
{
|
||||
for (size_t i = 0; i < NPUB; i++)
|
||||
{
|
||||
for (size_t j = 0; j < NWR_PUB; j++)
|
||||
{
|
||||
if (chk[i][j])
|
||||
continue;
|
||||
dds_instance_handle_t ih;
|
||||
dds_builtintopic_endpoint_t *ep;
|
||||
rc = dds_get_matched_publications (rd[i][j], &ih, 1);
|
||||
MPT_ASSERT (rc == 0 || rc == 1, "Unexpected return from get_matched_publications for writer %zu %zu: %s\n",
|
||||
i, j, dds_strretcode (rc));
|
||||
if (rc == 1)
|
||||
{
|
||||
ep = dds_get_matched_publication_data (rd[i][j], ih);
|
||||
MPT_ASSERT (ep != NULL, "Failed to retrieve matched publication data for writer %zu %zu\n", i, j);
|
||||
setqos (qos, i * NWR_PUB + j, false, false);
|
||||
uint64_t delta = writer_qos_delta (qos, ep->qos);
|
||||
if (delta)
|
||||
{
|
||||
DDS_LOG (DDS_LC_ERROR, "matched writer: delta = %"PRIx64"\n", delta);
|
||||
nn_log_xqos (DDS_LC_ERROR, qos); DDS_LOG (DDS_LC_ERROR, "\n");
|
||||
nn_log_xqos (DDS_LC_ERROR, ep->qos); DDS_LOG (DDS_LC_ERROR, "\n");
|
||||
}
|
||||
MPT_ASSERT (delta == 0, "reader %zu %zu matched writer QoS mismatch\n", i, j);
|
||||
dds_delete_qos (ep->qos);
|
||||
dds_free (ep->topic_name);
|
||||
dds_free (ep->type_name);
|
||||
dds_free (ep);
|
||||
chk[i][j] = true;
|
||||
nchk++;
|
||||
}
|
||||
}
|
||||
}
|
||||
dds_sleepfor (DDS_MSECS (100));
|
||||
}
|
||||
|
||||
dds_delete_qos (qos);
|
||||
rc = dds_delete (dp);
|
||||
MPT_ASSERT_EQ (rc, DDS_RETCODE_OK, "teardown failed\n");
|
||||
printf ("=== [Subscriber(%d)] Done\n", id);
|
||||
}
|
41
src/mpt/tests/qos/procs/rw.h
Normal file
41
src/mpt/tests/qos/procs/rw.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright(c) 2019 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
|
||||
*/
|
||||
|
||||
#ifndef MPT_QOSMATCH_PROCS_RW_H
|
||||
#define MPT_QOSMATCH_PROCS_RW_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/dds.h"
|
||||
#include "mpt/mpt.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void rw_init (void);
|
||||
void rw_fini (void);
|
||||
|
||||
MPT_ProcessEntry (rw_publisher,
|
||||
MPT_Args (dds_domainid_t domainid,
|
||||
const char *topic_name));
|
||||
|
||||
MPT_ProcessEntry (rw_subscriber,
|
||||
MPT_Args (dds_domainid_t domainid,
|
||||
const char *topic_name));
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
19
src/mpt/tests/qos/procs/rwdata.idl
Normal file
19
src/mpt/tests/qos/procs/rwdata.idl
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright(c) 2019 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
|
||||
*/
|
||||
module RWData
|
||||
{
|
||||
struct Msg
|
||||
{
|
||||
long k;
|
||||
};
|
||||
#pragma keylist Msg k
|
||||
};
|
21
src/mpt/tests/qos/qosmatch.c
Normal file
21
src/mpt/tests/qos/qosmatch.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright(c) 2019 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 "mpt/mpt.h"
|
||||
#include "procs/rw.h"
|
||||
|
||||
#define TEST_PUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_qosmatch")
|
||||
#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_qosmatch")
|
||||
MPT_TestProcess(qos, qosmatch, pub, rw_publisher, TEST_PUB_ARGS);
|
||||
MPT_TestProcess(qos, qosmatch, sub, rw_subscriber, TEST_SUB_ARGS);
|
||||
MPT_Test(qos, qosmatch, .init=rw_init, .fini=rw_fini);
|
||||
#undef TEST_SUB_ARGS
|
||||
#undef TEST_PUB_ARGS
|
Loading…
Add table
Add a link
Reference in a new issue