#include <stdlib.h>
#include "CUnit/Theory.h"
#include "dds/dds.h"
#include "dds/ddsrt/io.h"
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/string.h"
#include "dds/ddsrt/environ.h"
#include "dds/ddsi/ddsi_iid.h"
#include "dds/ddsi/ddsi_domaingv.h"
#include "dds/ddsi/ddsi_init.h"
#include "ddsi__nwpart.h"
#include "ddsi__udp.h"
#include "ddsi__thread.h"
#include "ddsi__misc.h"
#include "ddsi__addrset.h"
#include "ddsi__discovery.h"
#include "ddsi__discovery_endpoint.h"
#include "ddsi__plist.h"
#include "ddsi__tran.h"
#include "test_util.h"
#ifdef DDS_HAS_NETWORK_PARTITIONS
static int errcount;
static void null_log_sink (void *vcount, const dds_log_data_t *msg)
{
int *count = vcount;
tprintf ("%s", msg->message);
(*count)++;
}
static void intf_init (struct ddsi_network_interface *intf, int index, bool allow_mc, bool weird_extloc)
{
memset (intf, 0, sizeof (*intf));
intf->loc.kind = DDSI_LOCATOR_KIND_UDPv4;
intf->loc.port = 0;
if (index <= 0)
{
intf->loc.address[12] = 127;
intf->loc.address[13] = 0;
intf->loc.address[14] = 0;
intf->loc.address[15] = 1;
intf->netmask.address[12] = 255;
intf->netmask.address[13] = 0;
intf->netmask.address[14] = 0;
intf->netmask.address[15] = 0;
intf->extloc = intf->loc;
}
else
{
intf->loc.address[12] = (index == 1) ? 193 : 192;
intf->loc.address[13] = 168;
intf->loc.address[14] = (index >= 2) ? (unsigned char) (index - 2) : 0;
intf->loc.address[15] = 1;
intf->netmask.address[12] = 255;
intf->netmask.address[13] = 255;
intf->netmask.address[14] = 255;
intf->netmask.address[15] = 0;
intf->extloc = intf->loc;
if (weird_extloc)
intf->extloc.address[13]++;
}
intf->netmask.kind = DDSI_LOCATOR_KIND_UDPv4;
intf->if_index = 1000u + (uint32_t) index;
intf->mc_capable = (!allow_mc || index == 1) ? 0 : 1;
intf->mc_flaky = 0;
intf->allow_multicast = (allow_mc && intf->mc_capable) ? DDSI_AMC_TRUE : DDSI_AMC_FALSE;
intf->point_to_point = 0;
intf->loopback = (index == 0) ? 1 : 0;
intf->prefer_multicast = 0;
intf->priority = 0;
intf->addrset_costs.uc = 2;
intf->addrset_costs.mc = 3;
intf->addrset_costs.ssm = 2;
intf->addrset_costs.delivered = -1;
intf->addrset_costs.discarded = 1;
intf->addrset_costs.redundant_psmx = 0;
switch (index)
{
case 0: (void) ddsrt_asprintf (&intf->name, "lo"); break;
case 1: (void) ddsrt_asprintf (&intf->name, "nomc"); break;
default: (void) ddsrt_asprintf (&intf->name, "eth%d", index - 2); break;
}
}
static void setup (struct ddsi_domaingv *gv, const struct ddsi_config *config, bool allow_mc, bool weird_extloc)
{
ddsi_iid_init ();
ddsi_thread_states_init ();
struct ddsi_thread_state * const thrst = ddsi_lookup_thread_state ();
assert (thrst->state == DDSI_THREAD_STATE_LAZILY_CREATED);
thrst->state = DDSI_THREAD_STATE_ALIVE;
ddsrt_atomic_stvoidp (&thrst->gv, &gv);
memset (gv, 0, sizeof (*gv));
gv->config = *config;
gv->config.publish_uc_locators = 1;
gv->config.enable_uc_locators = 1;
(void) ddsi_udp_init (gv);
gv->m_factory = ddsi_factory_find (gv, "udp");
assert (gv->m_factory != NULL);
DDSRT_STATIC_ASSERT (4 <= MAX_XMIT_CONNS);
gv->extmask.kind = DDSI_LOCATOR_KIND_INVALID;
gv->n_interfaces = 4;
for (int i = 0; i < gv->n_interfaces; i++)
{
intf_init (&gv->interfaces[i], i, allow_mc, weird_extloc);
struct ddsi_tran_conn *fakeconn = ddsrt_malloc (sizeof (*fakeconn));
fakeconn->m_factory = gv->m_factory;
fakeconn->m_base.gv = gv;
fakeconn->m_interf = &gv->interfaces[i];
gv->xmit_conns[i] = fakeconn;
}
ddsi_config_prep (gv, NULL);
dds_set_log_sink (null_log_sink, &errcount);
dds_set_trace_sink (null_log_sink, &errcount);
gv->logconfig.c.tracemask = gv->logconfig.c.mask = UINT32_MAX;
}
static void teardown (struct ddsi_domaingv *gv)
{
#if __GNUC__ >= 12
DDSRT_WARNING_GNUC_OFF(analyzer-use-of-uninitialized-value)
#endif
for (int i = 0; i < gv->n_interfaces; i++)
{
ddsrt_free (gv->xmit_conns[i]);
ddsrt_free (gv->interfaces[i].name);
}
while (gv->ddsi_tran_factories)
{
struct ddsi_tran_factory *f = gv->ddsi_tran_factories;
gv->ddsi_tran_factories = f->m_factory;
ddsi_factory_free (f);
}
#if __GNUC__ >= 12
DDSRT_WARNING_GNUC_ON(analyzer-use-of-uninitialized-value)
#endif
struct ddsi_thread_state * const thrst = ddsi_lookup_thread_state ();
thrst->state = DDSI_THREAD_STATE_LAZILY_CREATED;
ddsi_thread_states_fini ();
ddsi_iid_fini ();
}
static bool check_address_list (const char *expected, struct ddsi_networkpartition_address *as)
{
char *copy = ddsrt_strdup (expected), *cursor = copy, *tok;
while ((tok = ddsrt_strsep (&cursor, ",")) != NULL)
{
if (as == NULL) {
tprintf ("check_address_list: too few addresses\n");
goto err;
}
char buf[DDSI_LOCSTRLEN];
ddsi_locator_to_string (buf, sizeof (buf), &as->loc);
if (strcmp (tok, buf) != 0) {
tprintf ("check_address_list: expected %s, got %s\n", tok, buf);
goto err;
}
as = as->next;
}
if (as != NULL) {
tprintf ("check_address_list: too many addresses\n");
goto err;
}
ddsrt_free (copy);
return true;
err:
ddsrt_free (copy);
return false;
}
CU_TheoryDataPoints(ddsc_nwpart, definition) = {
CU_DataPoints(struct ddsi_config_networkpartition_listelem,
{ .name = "p0", .address_string = "192.168.1.1", .interface_names = "eth1" }, { .name = "p1", .address_string = "", .interface_names = "not_an_interface" }, { .name = "p2", .address_string = "239.255.0.8", .interface_names = "nomc" }, { .name = "p3", .address_string = "239.255.0.8,193.168.0.1", .interface_names = "" }, { .name = "p4", .address_string = "239.255.0.8", .interface_names = "" }, { .name = "p5", .address_string = "7.7.7.7", .interface_names = "" }, { .name = "p6", .address_string = "192.168.1.7", .interface_names = "" }, { .name = "p7", .address_string = "192.168.1.1", .interface_names = "" },
{ .name = "p8", .address_string = "", .interface_names = "lo,eth0" },
{ .name = "p9", .address_string = "239.255.0.8", .interface_names = "eth1,lo,eth0" },
{ .name = "pA", .address_string = "192.169.1.1", .interface_names = "" }, { .name = "pB", .address_string = "192.168.1.0", .interface_names = "" }, { .name = "pC", .address_string = "239.255.0.4,239.255.0.5", .interface_names = "" }),
CU_DataPoints(bool, true, true, true, true, false, true, true,
true, true, true, true, true, true),
CU_DataPoints(const char *, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
"udp/192.169.1.1:31415",
"udp/127.0.0.1:31415,udp/192.169.0.1:31415",
"udp/192.169.1.1:31415,udp/127.0.0.1:31415,udp/192.169.0.1:31415",
"udp/192.169.1.1:31415",
"udp/192.169.1.1:31415",
""),
CU_DataPoints(const char *, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
"",
"",
"udp/239.255.0.8:7401",
"",
"",
"udp/239.255.0.4:7401,udp/239.255.0.5:7401")
};
#endif
CU_Theory ((struct ddsi_config_networkpartition_listelem ps, bool allow_mc, const char *uc, const char *mc), ddsc_nwpart, definition)
{
#ifndef DDS_HAS_NETWORK_PARTITIONS
CU_PASS ("no network partitions in build");
#else
assert ((uc == NULL) == (mc == NULL));
tprintf ("test: %s\n", ps.name);
struct ddsi_domaingv gv;
struct ddsi_config config;
ddsi_config_init_default (&config);
config.networkPartitions = &ps;
errcount = 0;
setup (&gv, &config, allow_mc, true);
int rc = ddsi_convert_nwpart_config (&gv, 31415);
if (uc == NULL) {
CU_ASSERT_LT_FATAL (rc, 0);
CU_ASSERT_GT_FATAL (errcount, 0);
} else {
CU_ASSERT_EQ_FATAL (rc, 0);
CU_ASSERT_EQ_FATAL (errcount, 0);
CU_ASSERT_FATAL (check_address_list (uc, ps.uc_addresses));
CU_ASSERT_FATAL (check_address_list (mc, ps.asm_addresses));
}
ddsi_free_config_nwpart_addresses (&gv);
teardown (&gv);
#endif
}
CU_Test (ddsc_nwpart, duplicate)
{
#ifndef DDS_HAS_NETWORK_PARTITIONS
CU_PASS ("no network partitions in build");
#else
const char *config =
"<Partitioning>"
" <NetworkPartitions>"
" <NetworkPartition name=\"p2\" address=\"239.255.0.13\"/>"
" <NetworkPartition name=\"p1\" address=\"239.255.0.12\"/>"
" <NetworkPartition name=\"P2\" address=\"239.255.0.11\"/>"
" </NetworkPartitions>"
"</Partitioning>";
dds_entity_t eh = dds_create_domain (0, config);
CU_ASSERT_LT_FATAL (eh, 0);
#endif
}
CU_Test (ddsc_nwpart, mapping_undefined)
{
#ifndef DDS_HAS_NETWORK_PARTITIONS
CU_PASS ("no network partitions in build");
#else
const char *config =
"${CYCLONEDDS_URI},<Partitioning>"
" <NetworkPartitions>"
" <NetworkPartition name=\"p2\" address=\"239.255.0.13\"/>"
" <NetworkPartition name=\"p1\" address=\"239.255.0.12\"/>"
" <NetworkPartition name=\"p0\" address=\"239.255.0.11\"/>"
" </NetworkPartitions>"
" <PartitionMappings>"
" <PartitionMapping DCPSPartitionTopic=\"a.b\" networkpartition=\"pX\"/>"
" </PartitionMappings>"
"</Partitioning>";
char *config1 = ddsrt_expand_envvars (config, 0);
dds_entity_t eh = dds_create_domain (0, config1);
ddsrt_free (config1);
CU_ASSERT_LT_FATAL (eh, 0);
#endif
}
CU_Test (ddsc_nwpart, mapping_multiple)
{
#ifndef DDS_HAS_NETWORK_PARTITIONS
CU_PASS ("no network partitions in build");
#else
const char *config =
"${CYCLONEDDS_URI},<Partitioning>"
" <NetworkPartitions>"
" <NetworkPartition name=\"p2\" address=\"239.255.0.13\"/>"
" <NetworkPartition name=\"p1\" address=\"239.255.0.12\"/>"
" <NetworkPartition name=\"p0\" address=\"239.255.0.11\"/>"
" </NetworkPartitions>"
" <PartitionMappings>"
" <PartitionMapping DCPSPartitionTopic=\"a.b\" networkpartition=\"P0\"/>"
" <PartitionMapping DCPSPartitionTopic=\"c.d\" networkpartition=\"p2\"/>"
" </PartitionMappings>"
"</Partitioning>";
char *config1 = ddsrt_expand_envvars (config, 0);
dds_entity_t eh = dds_create_domain (0, config1);
ddsrt_free (config1);
CU_ASSERT_GT_FATAL (eh, 0);
struct ddsi_domaingv * const gv = get_domaingv (eh);
struct ddsi_config_partitionmapping_listelem *m0, *m1;
m0 = gv->config.partitionMappings;
m1 = m0->next;
CU_ASSERT_STREQ_FATAL (m0->networkPartition, "P0");
CU_ASSERT_STREQ_FATAL (m1->networkPartition, "p2");
CU_ASSERT_EQ_FATAL (m1->next, NULL);
struct ddsi_config_networkpartition_listelem *p0, *p1, *p2;
p2 = gv->config.networkPartitions; p1 = p2->next;
p0 = p1->next;
CU_ASSERT_STREQ_FATAL (p2->name, "p2");
CU_ASSERT_STREQ_FATAL (p1->name, "p1");
CU_ASSERT_STREQ_FATAL (p0->name, "p0");
CU_ASSERT_EQ_FATAL (p0->next, NULL);
CU_ASSERT_EQ_FATAL (m0->partition, p0);
CU_ASSERT_EQ_FATAL (m1->partition, p2);
dds_delete (eh);
#endif
}
struct check_address_present_arg {
const char **expected;
bool ok;
};
static void check_address_present (const ddsi_xlocator_t *loc, void *varg)
{
struct check_address_present_arg *arg = varg;
char buf[DDSI_LOCSTRLEN];
ddsi_xlocator_to_string (buf, sizeof (buf), loc);
printf (" %s", buf);
fflush (stdout);
int i = 0;
while (arg->expected[i] && strcmp (arg->expected[i], buf) != 0)
i++;
if (arg->expected[i] == NULL)
arg->ok = false;
}
CU_TheoryDataPoints(ddsc_nwpart, selected_addrs) = {
CU_DataPoints(bool, true, true, false, false,
true, true, false, false,
true, true, false, false,
true, true, false, false,
true, true, false, false),
CU_DataPoints(bool, true, false, true, false,
true, false, true, false,
true, false, true, false,
true, false, true, false,
true, false, true, false),
CU_DataPoints(int, 0, 0, 0, 0,
2, 2, 2, 2,
3, 3, 3, 3,
3, 3, 3, 3,
3, 3, 3, 3),
CU_DataPoints(int, 0, 1, 0, 1,
1, 0, 1, 0,
0, 0, 0, 0,
1, 1, 1, 1,
2, 2, 2, 2),
CU_DataPoints(const char **, (const char *[]){ "udp/127.0.0.1:31416@1000", "udp/193.168.0.1:31416@1001", "udp/192.168.0.1:31416@1002", "udp/192.168.1.1:31416@1003",
"udp/239.255.0.1:7401@1000", "udp/239.255.0.1:7401@1002", "udp/239.255.0.1:7401@1003", NULL },
(const char *[]){ "udp/127.0.0.1:31416@1000", "udp/193.168.0.1:31416@1001", "udp/192.168.0.1:31416@1002", "udp/192.168.1.1:31416@1003",
"udp/239.255.0.2:7401@1000", "udp/239.255.0.2:7401@1002", "udp/239.255.0.2:7401@1003", NULL },
(const char *[]){ "udp/193.168.0.2:31416@1001", "udp/192.168.0.2:31416@1002", "udp/192.168.1.2:31416@1003",
"udp/239.255.0.1:7401@1002", "udp/239.255.0.1:7401@1003", NULL },
(const char *[]){ "udp/193.168.0.2:31416@1001", "udp/192.168.0.2:31416@1002", "udp/192.168.1.2:31416@1003",
"udp/239.255.0.2:7401@1002", "udp/239.255.0.2:7401@1003", NULL },
(const char *[]){ "udp/127.0.0.1:31416@1000", "udp/193.168.0.1:31416@1001",
"udp/239.255.0.2:7401@1000", NULL },
(const char *[]){ "udp/127.0.0.1:31416@1000", "udp/193.168.0.1:31416@1001", NULL },
(const char *[]){ "udp/193.168.0.2:31416@1001", NULL },
(const char *[]){ "udp/193.168.0.2:31416@1001", NULL },
(const char *[]){ "udp/127.0.0.1:31416@1000", "udp/193.168.0.1:31416@1001", "udp/192.168.0.1:31416@1002", NULL },
(const char *[]){ "udp/127.0.0.1:31416@1000", "udp/193.168.0.1:31416@1001", "udp/192.168.0.1:31416@1002", NULL },
(const char *[]){ "udp/193.168.0.2:31416@1001", "udp/192.168.0.2:31416@1002", NULL },
(const char *[]){ "udp/193.168.0.2:31416@1001", "udp/192.168.0.2:31416@1002", NULL },
(const char *[]){ "udp/127.0.0.1:31416@1000", "udp/193.168.0.1:31416@1001", "udp/192.168.0.1:31416@1002",
"udp/239.255.0.2:7401@1000", "udp/239.255.0.2:7401@1002", NULL },
(const char *[]){ "udp/127.0.0.1:31416@1000", "udp/193.168.0.1:31416@1001", "udp/192.168.0.1:31416@1002",
"udp/239.255.0.2:7401@1000", "udp/239.255.0.2:7401@1002", NULL },
(const char *[]){ "udp/193.168.0.2:31416@1001", "udp/192.168.0.2:31416@1002",
"udp/239.255.0.2:7401@1002", NULL },
(const char *[]){ "udp/193.168.0.2:31416@1001", "udp/192.168.0.2:31416@1002",
"udp/239.255.0.2:7401@1002", NULL },
(const char *[]){ "udp/127.0.0.1:31416@1000", "udp/193.168.0.1:31416@1001", "udp/192.168.0.1:31416@1002",
"udp/239.255.0.2:7401@1000", "udp/239.255.0.2:7401@1002",
"udp/239.255.0.3:7401@1000", "udp/239.255.0.3:7401@1002", NULL },
(const char *[]){ "udp/127.0.0.1:31416@1000", "udp/193.168.0.1:31416@1001", "udp/192.168.0.1:31416@1002",
"udp/239.255.0.2:7401@1000", "udp/239.255.0.2:7401@1002",
"udp/239.255.0.3:7401@1000", "udp/239.255.0.3:7401@1002", NULL },
(const char *[]){ "udp/193.168.0.2:31416@1001", "udp/192.168.0.2:31416@1002",
"udp/239.255.0.2:7401@1002",
"udp/239.255.0.3:7401@1002", NULL },
(const char *[]){ "udp/193.168.0.2:31416@1001", "udp/192.168.0.2:31416@1002",
"udp/239.255.0.2:7401@1002",
"udp/239.255.0.3:7401@1002", NULL })
};
CU_Theory ((bool same_machine, bool proxypp_has_defmc, int n_ep_uc, int n_ep_mc, const char **expected), ddsc_nwpart, selected_addrs)
{
tprintf ("---------------\n");
tprintf ("same_machine %d proxypp_has_defmc %d n_ep_uc %d n_ep_mc %d\n", same_machine, proxypp_has_defmc, n_ep_uc, n_ep_mc);
struct ddsi_domaingv gv;
struct ddsi_config config;
ddsi_config_init_default (&config);
config.transport_selector = DDSI_TRANS_UDP;
config.allowMulticast = DDSI_AMC_DEFAULT;
errcount = 0;
memset (&gv, 0, sizeof (gv)); setup (&gv, &config, true, false);
tprintf ("interfaces =\n");
for (int i = 0; i < gv.n_interfaces; i++)
{
char buf[DDSI_LOCSTRLEN];
tprintf (" %s", ddsi_locator_to_string_no_port (buf, sizeof (buf), &gv.interfaces[i].loc));
printf (" extern: %s", ddsi_locator_to_string_no_port (buf, sizeof (buf), &gv.interfaces[i].extloc));
printf (" (%smc)\n", gv.interfaces[i].mc_capable ? "" : "no-");
fflush (stdout);
}
tprintf ("as_default =\n");
struct ddsi_addrset *as_default = ddsi_new_addrset ();
for (int i = (same_machine ? 0 : 1); i < gv.n_interfaces; i++)
{
ddsi_xlocator_t xloc = {
.conn = gv.xmit_conns[i],
.c = gv.interfaces[i].extloc
};
xloc.c.port = 31416;
if (!same_machine && i > 0) xloc.c.address[15]++;
char buf[DDSI_LOCSTRLEN];
tprintf (" %s\n", ddsi_xlocator_to_string (buf, sizeof (buf), &xloc));
ddsi_add_xlocator_to_addrset (&gv, as_default, &xloc);
}
const ddsi_locator_t defmcloc = {
.kind = DDSI_LOCATOR_KIND_UDPv4,
.port = 7401,
.address = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 239,255,0,1 }
};
if (proxypp_has_defmc)
{
for (int i = (same_machine ? 0 : 1); i < gv.n_interfaces; i++)
{
if (gv.interfaces[i].mc_capable)
{
ddsi_xlocator_t xloc = { .conn = gv.xmit_conns[i], .c = defmcloc };
char buf[DDSI_LOCSTRLEN];
tprintf (" %s\n", ddsi_xlocator_to_string (buf, sizeof (buf), &xloc));
ddsi_add_xlocator_to_addrset (&gv, as_default, &xloc);
}
}
}
ddsi_plist_t plist;
ddsi_plist_init_empty (&plist);
struct ddsi_locators_one uc[MAX_XMIT_CONNS];
assert (n_ep_uc <= gv.n_interfaces);
for (int i = 0; i < n_ep_uc; i++)
{
uc[i].next = &uc[i+1];
uc[i].loc = gv.interfaces[i].extloc;
uc[i].loc.port = 31416;
if (!same_machine && i > 0) uc[i].loc.address[15]++; }
if (n_ep_uc > 0)
{
uc[n_ep_uc-1].next = NULL;
plist.unicast_locators = (ddsi_locators_t){ .n = (uint32_t)n_ep_uc, .first = &uc[0], .last = &uc[n_ep_uc-1] };
plist.present |= PP_UNICAST_LOCATOR;
}
struct ddsi_locators_one mc[2] = {
{ .next = &mc[1],
.loc = {
.kind = DDSI_LOCATOR_KIND_UDPv4,
.port = 7401,
.address = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 239,255,0,2 }
}
},
{ .next = NULL,
.loc = {
.kind = DDSI_LOCATOR_KIND_UDPv4,
.port = 7401,
.address = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 239,255,0,3 }
}
}
};
assert (n_ep_mc <= (int) (sizeof (mc) / sizeof (mc[0])));
if (n_ep_mc > 0)
{
mc[n_ep_mc-1].next = NULL;
plist.multicast_locators = (ddsi_locators_t){ .n = (uint32_t)n_ep_mc, .first = &mc[0], .last = &mc[n_ep_mc-1] };
plist.present |= PP_MULTICAST_LOCATOR;
}
{
char buf[1024];
ddsi_plist_print (buf, sizeof (buf), &plist);
tprintf ("advertised plist: %s\n", buf);
}
struct ddsi_network_packet_info pktinfo;
ddsi_set_unspec_locator (&pktinfo.src);
pktinfo.if_index = 0;
pktinfo.dst.kind = DDSI_LOCATOR_KIND_INVALID;
struct ddsi_addrset *as = ddsi_get_endpoint_addrset (&gv, &plist, as_default, &pktinfo, false, false);
int n = 0;
while (expected[n])
n++;
struct check_address_present_arg arg = {
.expected = expected,
.ok = (ddsi_addrset_count (as) == (size_t) n)
};
tprintf ("addrset =");
ddsi_addrset_forall (as, check_address_present, &arg);
printf ("\n");
if (arg.ok)
tprintf ("OK\n");
else
{
tprintf ("expected =");
for (int i = 0; expected[i]; i++)
printf (" %s", expected[i]);
printf ("\n");
tprintf ("(in any order)\n");
}
CU_ASSERT_NEQ (arg.ok, 0);
ddsi_unref_addrset (as);
ddsi_unref_addrset (as_default);
teardown (&gv);
}
CU_TheoryDataPoints(ddsc_nwpart, full_stack_init) = {
CU_DataPoints(const char *, "none", "auto", "none"), CU_DataPoints(const char *, "single", "single", "none") };
CU_Theory ((const char *pistr, const char *msmstr), ddsc_nwpart, full_stack_init)
{
#ifndef DDS_HAS_NETWORK_PARTITIONS
CU_PASS ("no network partitions in build");
#else
dds_return_t rc;
dds_entity_t eh = dds_create_domain (0, NULL);
CU_ASSERT_GT_FATAL (eh, 0);
const struct ddsi_domaingv *gv = get_domaingv (eh);
CU_ASSERT_NEQ_FATAL (gv, NULL);
char *config = NULL;
(void) ddsrt_asprintf (&config,
"<General>"
" <Interfaces>"
" <NetworkInterface name=\"%s\"/>"
" </Interfaces>"
"</General>"
"<Discovery>"
" <MaxAutoParticipantIndex>100</MaxAutoParticipantIndex>"
" <ParticipantIndex>%s</ParticipantIndex>"
"</Discovery>"
"<Compatibility>"
" <ManySocketsMode>%s</ManySocketsMode>"
"</Compatibility>"
"<Partitioning>"
" <NetworkPartitions>"
" <NetworkPartition name=\"part\" address=\"239.255.0.13\" interface=\"%s\"/>"
" </NetworkPartitions>"
"</Partitioning>",
gv->interfaces[0].name,
pistr,
msmstr,
gv->interfaces[0].name);
rc = dds_delete (eh);
CU_ASSERT_EQ_FATAL (rc, 0);
eh = dds_create_domain (0, config);
ddsrt_free (config);
CU_ASSERT_GT_FATAL (eh, 0);
gv = get_domaingv (eh);
CU_ASSERT_NEQ_FATAL (gv, NULL);
struct ddsi_config_networkpartition_listelem const * const np = gv->config.networkPartitions;
struct ddsi_locator const * const nploc = &np->uc_addresses->loc;
CU_ASSERT_MEMEQ (gv->interfaces[0].loc.address, sizeof (gv->interfaces[0].loc.address), nploc->address, sizeof (nploc->address));
CU_ASSERT_MEMEQ (gv->loc_default_uc.address, sizeof (gv->loc_default_uc.address), nploc->address, sizeof (nploc->address));
CU_ASSERT_EQ_FATAL (gv->loc_default_uc.port, nploc->port);
rc = dds_delete (eh);
CU_ASSERT_EQ_FATAL (rc, 0);
#endif
}