#include #include #include #include "testing_clock.h" #include "ua_server_internal.h" #include "ua_pubsub.h" #ifdef UA_ENABLE_PUBSUB_FILE_CONFIG #include "ua_util_internal.h" #endif /* UA_ENABLE_PUBSUB_FILE_CONFIG */ #include #include static UA_Server *server = NULL; /* global variables for test configuration */ static UA_Boolean UseFastPath = UA_FALSE; static UA_Boolean UseRawEncoding = UA_FALSE; /***************************************************************************************************/ /***************************************************************************************************/ static void setup(void) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "setup"); server = UA_Server_new(); ck_assert(server != NULL); UA_ServerConfig *config = UA_Server_getConfig(server); ck_assert(config != 0); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_ServerConfig_setDefault(config)); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_run_startup(server)); } /***************************************************************************************************/ static void teardown(void) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "teardown"); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_run_shutdown(server)); UA_Server_delete(server); } /***************************************************************************************************/ /***************************************************************************************************/ /***************************************************************************************************/ /***************************************************************************************************/ /* utility functions to setup the PubSub configuration */ /***************************************************************************************************/ static void AddConnection( char *pName, UA_PublisherIdType publisherIdType, UA_PublisherId publisherId, UA_NodeId *opConnectionId) { ck_assert(pName != 0); ck_assert(opConnectionId != 0); UA_PubSubConnectionConfig connectionConfig; memset(&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig)); connectionConfig.name = UA_STRING(pName); connectionConfig.enabled = UA_TRUE; connectionConfig.transportProfileUri = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp"); UA_NetworkAddressUrlDataType networkAddressUrl = {UA_STRING_NULL, UA_STRING("opc.udp://224.0.0.22:4840/")}; UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrl, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); connectionConfig.publisherIdType = publisherIdType; /* deep copy is not needed (not even for string) because UA_Server_addPubSubConnection performs deep copy */ connectionConfig.publisherId = publisherId; ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_addPubSubConnection(server, &connectionConfig, opConnectionId)); } /***************************************************************************************************/ static void AddWriterGroup( UA_NodeId *pConnectionId, char *pName, UA_UInt32 WriterGroupId, UA_NodeId *opWriterGroupId) { ck_assert(pConnectionId != 0); ck_assert(pName != 0); ck_assert(opWriterGroupId != 0); UA_WriterGroupConfig writerGroupConfig; memset(&writerGroupConfig, 0, sizeof(UA_WriterGroupConfig)); writerGroupConfig.name = UA_STRING(pName); writerGroupConfig.publishingInterval = 50.0; writerGroupConfig.enabled = UA_FALSE; writerGroupConfig.writerGroupId = (UA_UInt16) WriterGroupId; writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_UADP; writerGroupConfig.messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED; writerGroupConfig.messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]; UA_UadpWriterGroupMessageDataType *writerGroupMessage = UA_UadpWriterGroupMessageDataType_new(); writerGroupMessage->networkMessageContentMask = (UA_UadpNetworkMessageContentMask)(UA_UADPNETWORKMESSAGECONTENTMASK_PUBLISHERID | (UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPHEADER | (UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_WRITERGROUPID | (UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_PAYLOADHEADER); writerGroupConfig.messageSettings.content.decoded.data = writerGroupMessage; if (UseFastPath) { writerGroupConfig.rtLevel = UA_PUBSUB_RT_FIXED_SIZE; } ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_addWriterGroup(server, *pConnectionId, &writerGroupConfig, opWriterGroupId)); UA_UadpWriterGroupMessageDataType_delete(writerGroupMessage); } /***************************************************************************************************/ static void AddPublishedDataSet( UA_NodeId *pWriterGroupId, char *pPublishedDataSetName, char *pDataSetWriterName, UA_UInt32 DataSetWriterId, UA_NodeId *opPublishedDataSetId, UA_NodeId *opPublishedVarId, UA_DataValue **oppFastPathPublisherDataValue, UA_NodeId *opDataSetWriterId) { ck_assert(pWriterGroupId != 0); ck_assert(pPublishedDataSetName != 0); ck_assert(pDataSetWriterName != 0); ck_assert(opPublishedDataSetId != 0); ck_assert(opPublishedVarId != 0); ck_assert(oppFastPathPublisherDataValue != 0); ck_assert(opDataSetWriterId != 0); UA_PublishedDataSetConfig pdsConfig; memset(&pdsConfig, 0, sizeof(UA_PublishedDataSetConfig)); pdsConfig.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS; pdsConfig.name = UA_STRING(pPublishedDataSetName); UA_AddPublishedDataSetResult result = UA_Server_addPublishedDataSet(server, &pdsConfig, opPublishedDataSetId); ck_assert_int_eq(UA_STATUSCODE_GOOD, result.addResult); /* Create variable to publish integer data */ UA_VariableAttributes attr = UA_VariableAttributes_default; attr.description = UA_LOCALIZEDTEXT("en-US","Published Int32"); attr.displayName = UA_LOCALIZEDTEXT("en-US","Published Int32"); attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId; UA_Int32 publisherData = 42; UA_Variant_setScalar(&attr.value, &publisherData, &UA_TYPES[UA_TYPES_INT32]); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_addVariableNode(server, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "Published Int32"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr, NULL, opPublishedVarId)); UA_NodeId dataSetFieldId; UA_DataSetFieldConfig dataSetFieldConfig; memset(&dataSetFieldConfig, 0, sizeof(UA_DataSetFieldConfig)); dataSetFieldConfig.dataSetFieldType = UA_PUBSUB_DATASETFIELD_VARIABLE; dataSetFieldConfig.field.variable.fieldNameAlias = UA_STRING("Int32 Publish var"); dataSetFieldConfig.field.variable.promotedField = UA_FALSE; dataSetFieldConfig.field.variable.publishParameters.publishedVariable = *opPublishedVarId; dataSetFieldConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE; if (UseFastPath) { dataSetFieldConfig.field.variable.rtValueSource.rtInformationModelNode = UA_TRUE; *oppFastPathPublisherDataValue = UA_DataValue_new(); ck_assert(*oppFastPathPublisherDataValue != 0); UA_Int32 *pPublisherData = UA_Int32_new(); ck_assert(pPublisherData != 0); *pPublisherData = 42; UA_Variant_setScalar(&((**oppFastPathPublisherDataValue).value), pPublisherData, &UA_TYPES[UA_TYPES_INT32]); /* add external value backend for fast-path */ UA_ValueBackend valueBackend; memset(&valueBackend, 0, sizeof(valueBackend)); valueBackend.backendType = UA_VALUEBACKENDTYPE_EXTERNAL; valueBackend.backend.external.value = oppFastPathPublisherDataValue; ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setVariableNode_valueBackend(server, *opPublishedVarId, valueBackend)); } UA_DataSetFieldResult PdsFieldResult = UA_Server_addDataSetField(server, *opPublishedDataSetId, &dataSetFieldConfig, &dataSetFieldId); ck_assert_int_eq(UA_STATUSCODE_GOOD, PdsFieldResult.result); UA_DataSetWriterConfig dataSetWriterConfig; memset(&dataSetWriterConfig, 0, sizeof(dataSetWriterConfig)); dataSetWriterConfig.name = UA_STRING(pDataSetWriterName); dataSetWriterConfig.dataSetWriterId = (UA_UInt16) DataSetWriterId; dataSetWriterConfig.keyFrameCount = 10; if (UseRawEncoding) { dataSetWriterConfig.dataSetFieldContentMask = UA_DATASETFIELDCONTENTMASK_RAWDATA; } else { dataSetWriterConfig.dataSetFieldContentMask = UA_DATASETFIELDCONTENTMASK_NONE; } ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_addDataSetWriter(server, *pWriterGroupId, *opPublishedDataSetId, &dataSetWriterConfig, opDataSetWriterId)); } /***************************************************************************************************/ static void AddReaderGroup( UA_NodeId *pConnectionId, char *pName, UA_NodeId *opReaderGroupId) { ck_assert(pConnectionId != 0); ck_assert(pName != 0); ck_assert(opReaderGroupId != 0); UA_ReaderGroupConfig readerGroupConfig; memset (&readerGroupConfig, 0, sizeof(UA_ReaderGroupConfig)); readerGroupConfig.name = UA_STRING(pName); if (UseFastPath) { readerGroupConfig.rtLevel = UA_PUBSUB_RT_FIXED_SIZE; } ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_addReaderGroup(server, *pConnectionId, &readerGroupConfig, opReaderGroupId)); } /***************************************************************************************************/ static void AddDataSetReader( UA_NodeId *pReaderGroupId, char *pName, UA_PublisherIdType publisherIdType, UA_PublisherId publisherId, UA_UInt32 WriterGroupId, UA_UInt32 DataSetWriterId, UA_NodeId *opSubscriberVarId, UA_DataValue **oppFastPathSubscriberDataValue, UA_NodeId *opDataSetReaderId) { ck_assert(pReaderGroupId != 0); ck_assert(pName != 0); ck_assert(opSubscriberVarId != 0); ck_assert(oppFastPathSubscriberDataValue != 0); ck_assert(opDataSetReaderId != 0); UA_DataSetReaderConfig readerConfig; memset (&readerConfig, 0, sizeof(UA_DataSetReaderConfig)); readerConfig.name = UA_STRING(pName); switch (publisherIdType) { case UA_PUBLISHERIDTYPE_BYTE: UA_Variant_setScalar(&readerConfig.publisherId, &publisherId.byte, &UA_TYPES[UA_TYPES_BYTE]); break; case UA_PUBLISHERIDTYPE_UINT16: UA_Variant_setScalar(&readerConfig.publisherId, &publisherId.uint16, &UA_TYPES[UA_TYPES_UINT16]); break; case UA_PUBLISHERIDTYPE_UINT32: UA_Variant_setScalar(&readerConfig.publisherId, &publisherId.uint32, &UA_TYPES[UA_TYPES_UINT32]); break; case UA_PUBLISHERIDTYPE_UINT64: UA_Variant_setScalar(&readerConfig.publisherId, &publisherId.uint64, &UA_TYPES[UA_TYPES_UINT64]); break; case UA_PUBLISHERIDTYPE_STRING: UA_Variant_setScalar(&readerConfig.publisherId, &publisherId.string, &UA_TYPES[UA_TYPES_STRING]); break; default: ck_assert(UA_FALSE); break; } readerConfig.writerGroupId = (UA_UInt16) WriterGroupId; readerConfig.dataSetWriterId = (UA_UInt16) DataSetWriterId; readerConfig.messageReceiveTimeout = 200.0; readerConfig.messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED; readerConfig.messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_UADPDATASETREADERMESSAGEDATATYPE]; UA_UadpDataSetReaderMessageDataType *dsReaderMessage = UA_UadpDataSetReaderMessageDataType_new(); dsReaderMessage->networkMessageContentMask = (UA_UadpNetworkMessageContentMask)(UA_UADPNETWORKMESSAGECONTENTMASK_PUBLISHERID | (UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPHEADER | (UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_WRITERGROUPID | (UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_PAYLOADHEADER); readerConfig.messageSettings.content.decoded.data = dsReaderMessage; if (UseRawEncoding) { readerConfig.dataSetFieldContentMask = UA_DATASETFIELDCONTENTMASK_RAWDATA; readerConfig.expectedEncoding = UA_PUBSUB_RT_RAW; } else { readerConfig.dataSetFieldContentMask = UA_DATASETFIELDCONTENTMASK_NONE; } UA_DataSetMetaDataType_init(&readerConfig.dataSetMetaData); UA_DataSetMetaDataType *pDataSetMetaData = &readerConfig.dataSetMetaData; pDataSetMetaData->name = UA_STRING (pName); pDataSetMetaData->fieldsSize = 1; pDataSetMetaData->fields = (UA_FieldMetaData*) UA_Array_new (pDataSetMetaData->fieldsSize, &UA_TYPES[UA_TYPES_FIELDMETADATA]); UA_FieldMetaData_init (&pDataSetMetaData->fields[0]); UA_NodeId_copy (&UA_TYPES[UA_TYPES_INT32].typeId, &pDataSetMetaData->fields[0].dataType); pDataSetMetaData->fields[0].builtInType = UA_NS0ID_INT32; pDataSetMetaData->fields[0].name = UA_STRING ("Int32 Var"); pDataSetMetaData->fields[0].valueRank = -1; ck_assert(UA_Server_addDataSetReader(server, *pReaderGroupId, &readerConfig, opDataSetReaderId) == UA_STATUSCODE_GOOD); UA_UadpDataSetReaderMessageDataType_delete(dsReaderMessage); dsReaderMessage = 0; /* Variable to subscribe data */ UA_VariableAttributes attr = UA_VariableAttributes_default; attr.description = UA_LOCALIZEDTEXT ("en-US", "Subscribed Int32"); attr.displayName = UA_LOCALIZEDTEXT ("en-US", "Subscribed Int32"); attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId; UA_Int32 subscriberData = 0; UA_Variant_setScalar(&attr.value, &subscriberData, &UA_TYPES[UA_TYPES_INT32]); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_addVariableNode(server, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "Subscribed Int32"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr, NULL, opSubscriberVarId)); if (UseFastPath) { *oppFastPathSubscriberDataValue = UA_DataValue_new(); ck_assert(*oppFastPathSubscriberDataValue != 0); UA_Int32 *pSubscriberData = UA_Int32_new(); ck_assert(pSubscriberData != 0); *pSubscriberData = 0; UA_Variant_setScalar(&((**oppFastPathSubscriberDataValue).value), pSubscriberData, &UA_TYPES[UA_TYPES_INT32]); /* add external value backend for fast-path */ UA_ValueBackend valueBackend; memset(&valueBackend, 0, sizeof(valueBackend)); valueBackend.backendType = UA_VALUEBACKENDTYPE_EXTERNAL; valueBackend.backend.external.value = oppFastPathSubscriberDataValue; ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setVariableNode_valueBackend(server, *opSubscriberVarId, valueBackend)); } UA_FieldTargetVariable *pTargetVariables = (UA_FieldTargetVariable *) UA_calloc(readerConfig.dataSetMetaData.fieldsSize, sizeof(UA_FieldTargetVariable)); ck_assert(pTargetVariables != 0); UA_FieldTargetDataType_init(&pTargetVariables[0].targetVariable); pTargetVariables[0].targetVariable.attributeId = UA_ATTRIBUTEID_VALUE; pTargetVariables[0].targetVariable.targetNodeId = *opSubscriberVarId; ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_DataSetReader_createTargetVariables(server, *opDataSetReaderId, readerConfig.dataSetMetaData.fieldsSize, pTargetVariables)); UA_FieldTargetDataType_clear(&pTargetVariables[0].targetVariable); UA_free(pTargetVariables); pTargetVariables = 0; UA_free(pDataSetMetaData->fields); pDataSetMetaData->fields = 0; } /***************************************************************************************************/ /* utility function to check working pubsub operation */ static void ValidatePublishSubscribe( const UA_UInt32 NoOfTestVars, UA_NodeId *publisherVarIds, UA_NodeId *subscriberVarIds, UA_DataValue **fastPathPublisherValues, /* fast-path publisher DataValue */ UA_DataValue **fastPathSubscriberValues, /* fast-path subscriber DataValue */ const UA_Int32 TestValue, const UA_UInt32 Sleep_ms, /* use at least publishing interval */ const UA_UInt32 NoOfRunIterateCycles) { ck_assert(publisherVarIds != 0); ck_assert(subscriberVarIds != 0); ck_assert(fastPathPublisherValues != 0); ck_assert(fastPathSubscriberValues != 0); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "ValidatePublishSubscribe(): set variable to publish"); /* set variable value to publish */ UA_Int32 tmpValue = TestValue; for (UA_UInt32 i = 0; i < NoOfTestVars; i++) { tmpValue = TestValue + (UA_Int32) i; if (UseFastPath) { ck_assert((fastPathPublisherValues != 0) && (fastPathPublisherValues[i] != 0)); *((UA_Int32 *) (fastPathPublisherValues[i]->value.data)) = tmpValue; } else { UA_Variant writeValue; UA_Variant_init(&writeValue); UA_Variant_setScalarCopy(&writeValue, &tmpValue, &UA_TYPES[UA_TYPES_INT32]); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_writeValue(server, publisherVarIds[i], writeValue)); UA_Variant_clear(&writeValue); } } UA_Boolean done = false; while(!done) { UA_fakeSleep(Sleep_ms); UA_Server_run_iterate(server, true); done = true; for(UA_UInt32 i = 0; i < NoOfTestVars; i++) { tmpValue = TestValue + (UA_Int32)i; if(UseFastPath) { ck_assert(fastPathSubscriberValues[i] != 0); if(tmpValue != *(UA_Int32 *)fastPathSubscriberValues[i]->value.data) { done = false; break; } } else { UA_Variant SubscribedNodeData; UA_Variant_init(&SubscribedNodeData); UA_Server_readValue(server, subscriberVarIds[i], &SubscribedNodeData); if(tmpValue != *(UA_Int32 *)SubscribedNodeData.data) done = false; UA_Variant_clear(&SubscribedNodeData); } } } } /***************************************************************************************************/ static void DoTest_1_Connection( UA_PublisherIdType publisherIdType, UA_PublisherId publisherId) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "DoTest_1_Connection() begin"); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "fast-path = %s", (UseFastPath) ? "enabled" : "disabled"); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "raw encoding = %s", (UseRawEncoding) ? "enabled" : "disabled"); #define DOTEST_1_CONNECTION_MAX_VARS 1 UA_NodeId publisherVarIds[DOTEST_1_CONNECTION_MAX_VARS]; UA_NodeId subscriberVarIds[DOTEST_1_CONNECTION_MAX_VARS]; /* Attention: Publisher and corresponding Subscriber DataValue must have the same index */ UA_DataValue *fastPathPublisherDataValues[DOTEST_1_CONNECTION_MAX_VARS]; UA_DataValue *fastPathSubscriberDataValues[DOTEST_1_CONNECTION_MAX_VARS]; for (UA_UInt32 i = 0; i < DOTEST_1_CONNECTION_MAX_VARS; i++) { fastPathPublisherDataValues[i] = 0; fastPathSubscriberDataValues[i] = 0; } /* setup Connection 1: */ UA_NodeId ConnId_1; UA_NodeId_init(&ConnId_1); AddConnection("Conn1", publisherIdType, publisherId, &ConnId_1); UA_NodeId WGId_Conn1_WG1; UA_NodeId_init(&WGId_Conn1_WG1); AddWriterGroup(&ConnId_1, "Conn1_WG1", 1, &WGId_Conn1_WG1); UA_NodeId DsWId_Conn1_WG1_DS1; UA_NodeId_init(&DsWId_Conn1_WG1_DS1); UA_NodeId PDSId_Conn1_WG1_PDS1; UA_NodeId_init(&PDSId_Conn1_WG1_PDS1); AddPublishedDataSet(&WGId_Conn1_WG1, "Conn1_WG1_PDS1", "Conn1_WG1_DS1", 1, &PDSId_Conn1_WG1_PDS1, &publisherVarIds[0], &fastPathPublisherDataValues[0], &DsWId_Conn1_WG1_DS1); UA_NodeId RGId_Conn1_RG1; UA_NodeId_init(&RGId_Conn1_RG1); AddReaderGroup(&ConnId_1, "Conn1_RG1", &RGId_Conn1_RG1); UA_NodeId DSRId_Conn1_RG1_DSR1; UA_NodeId_init(&DSRId_Conn1_RG1_DSR1); AddDataSetReader(&RGId_Conn1_RG1, "Conn1_RG1_DSR1", publisherIdType, publisherId, 1, 1, &subscriberVarIds[0], &fastPathSubscriberDataValues[0], &DSRId_Conn1_RG1_DSR1); /* freeze groups if fast-path is enabled */ if (UseFastPath) { if (publisherIdType != UA_PUBLISHERIDTYPE_STRING) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_freezeWriterGroupConfiguration(server, WGId_Conn1_WG1)); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_freezeReaderGroupConfiguration(server, RGId_Conn1_RG1)); } else { /* string PublisherId is not supported with fast-path */ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "test case: STRING publisherId with fast-path"); /* TODO: UA_Server_freezeWriterGroupConfiguration() accepts publisherId of type STRING, but UA_Server_freezeReaderGroupConfiguration() returns an error -> what is correct? */ ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_freezeWriterGroupConfiguration(server, WGId_Conn1_WG1)); ck_assert_int_eq(UA_STATUSCODE_BADNOTSUPPORTED, UA_Server_freezeReaderGroupConfiguration(server, RGId_Conn1_RG1)); /* cleanup and continue with other tests */ ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_unfreezeWriterGroupConfiguration(server, WGId_Conn1_WG1)); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_unfreezeReaderGroupConfiguration(server, RGId_Conn1_RG1)); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_removePublishedDataSet(server, PDSId_Conn1_WG1_PDS1)); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_removePubSubConnection(server, ConnId_1)); for (UA_UInt32 i = 0; i < DOTEST_1_CONNECTION_MAX_VARS; i++) { UA_DataValue_clear(fastPathPublisherDataValues[i]); UA_DataValue_delete(fastPathPublisherDataValues[i]); UA_DataValue_clear(fastPathSubscriberDataValues[i]); UA_DataValue_delete(fastPathSubscriberDataValues[i]); } return; } } /* set groups operational */ ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setWriterGroupOperational(server, WGId_Conn1_WG1)); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setReaderGroupOperational(server, RGId_Conn1_RG1)); /* check that publish/subscribe works -> set some test values */ ValidatePublishSubscribe(DOTEST_1_CONNECTION_MAX_VARS, &publisherVarIds[0], &subscriberVarIds[0], &fastPathPublisherDataValues[0], &fastPathSubscriberDataValues[0], 10, (UA_UInt32) 100, 3); ValidatePublishSubscribe(DOTEST_1_CONNECTION_MAX_VARS, &publisherVarIds[0], &subscriberVarIds[0], &fastPathPublisherDataValues[0], &fastPathSubscriberDataValues[0], 33, (UA_UInt32) 100, 3); ValidatePublishSubscribe(DOTEST_1_CONNECTION_MAX_VARS, &publisherVarIds[0], &subscriberVarIds[0], &fastPathPublisherDataValues[0], &fastPathSubscriberDataValues[0], 44, (UA_UInt32) 100, 3); /* set groups to disabled */ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "disable groups"); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setWriterGroupDisabled(server, WGId_Conn1_WG1)); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setReaderGroupDisabled(server, RGId_Conn1_RG1)); /* unfreeze groups if fast-path is enabled */ if (UseFastPath) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "unfreeze groups"); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_unfreezeWriterGroupConfiguration(server, WGId_Conn1_WG1)); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_unfreezeReaderGroupConfiguration(server, RGId_Conn1_RG1)); } UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "remove PDS"); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_removePublishedDataSet(server, PDSId_Conn1_WG1_PDS1)); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "remove Connection"); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_removePubSubConnection(server, ConnId_1)); if (UseFastPath) { for (UA_UInt32 i = 0; i < DOTEST_1_CONNECTION_MAX_VARS; i++) { UA_DataValue_clear(fastPathPublisherDataValues[i]); UA_DataValue_delete(fastPathPublisherDataValues[i]); UA_DataValue_clear(fastPathSubscriberDataValues[i]); UA_DataValue_delete(fastPathSubscriberDataValues[i]); } } UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "DoTest_1_Connection() end"); } /***************************************************************************************************/ /* simple test with 1 connection */ START_TEST(Test_1_connection) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "START: Test_1_connection"); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Test PublisherId BYTE with all combinations"); UA_PublisherIdType publisherIdType = UA_PUBLISHERIDTYPE_BYTE; UA_PublisherId publisherId; publisherId.byte = 2; UseFastPath = UA_FALSE; UseRawEncoding = UA_FALSE; DoTest_1_Connection(publisherIdType, publisherId); UseFastPath = UA_FALSE; UseRawEncoding = UA_TRUE; DoTest_1_Connection(publisherIdType, publisherId); UseFastPath = UA_TRUE; UseRawEncoding = UA_FALSE; DoTest_1_Connection(publisherIdType, publisherId); UseFastPath = UA_TRUE; UseRawEncoding = UA_TRUE; DoTest_1_Connection(publisherIdType, publisherId); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Test PublisherId UINT16 with all combinations"); publisherIdType = UA_PUBLISHERIDTYPE_UINT16; publisherId.uint16 = 3; UseFastPath = UA_FALSE; UseRawEncoding = UA_FALSE; DoTest_1_Connection(publisherIdType, publisherId); UseFastPath = UA_FALSE; UseRawEncoding = UA_TRUE; DoTest_1_Connection(publisherIdType, publisherId); UseFastPath = UA_TRUE; UseRawEncoding = UA_FALSE; DoTest_1_Connection(publisherIdType, publisherId); UseFastPath = UA_TRUE; UseRawEncoding = UA_TRUE; DoTest_1_Connection(publisherIdType, publisherId); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Test PublisherId UINT32 with all combinations"); publisherIdType = UA_PUBLISHERIDTYPE_UINT32; publisherId.uint32 = 5; UseFastPath = UA_FALSE; UseRawEncoding = UA_FALSE; DoTest_1_Connection(publisherIdType, publisherId); UseFastPath = UA_FALSE; UseRawEncoding = UA_TRUE; DoTest_1_Connection(publisherIdType, publisherId); UseFastPath = UA_TRUE; UseRawEncoding = UA_FALSE; DoTest_1_Connection(publisherIdType, publisherId); UseFastPath = UA_TRUE; UseRawEncoding = UA_TRUE; DoTest_1_Connection(publisherIdType, publisherId); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Test PublisherId UINT64 with all combinations"); publisherIdType = UA_PUBLISHERIDTYPE_UINT64; publisherId.uint64 = 6; UseFastPath = UA_FALSE; UseRawEncoding = UA_FALSE; DoTest_1_Connection(publisherIdType, publisherId); UseFastPath = UA_FALSE; UseRawEncoding = UA_TRUE; DoTest_1_Connection(publisherIdType, publisherId); UseFastPath = UA_TRUE; UseRawEncoding = UA_FALSE; DoTest_1_Connection(publisherIdType, publisherId); UseFastPath = UA_TRUE; UseRawEncoding = UA_TRUE; DoTest_1_Connection(publisherIdType, publisherId); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Test PublisherId STRING with all combinations"); publisherIdType = UA_PUBLISHERIDTYPE_STRING; publisherId.string = UA_STRING("My PublisherId"); UseFastPath = UA_FALSE; UseRawEncoding = UA_FALSE; DoTest_1_Connection(publisherIdType, publisherId); UseFastPath = UA_FALSE; UseRawEncoding = UA_TRUE; DoTest_1_Connection(publisherIdType, publisherId); /* Note: STRING publisherId is not supported with fast-path */ UseFastPath = UA_TRUE; UseRawEncoding = UA_FALSE; DoTest_1_Connection(publisherIdType, publisherId); UseFastPath = UA_TRUE; UseRawEncoding = UA_TRUE; DoTest_1_Connection(publisherIdType, publisherId); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "END: Test_1_connection"); } END_TEST /***************************************************************************************************/ static void DoTest_multiple_Connections(void) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "DoTest_multiple_Connections() begin"); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "fast-path = %s", (UseFastPath) ? "enabled" : "disabled"); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "raw encoding = %s", (UseRawEncoding) ? "enabled" : "disabled"); /* Writers -> Readers ---------------------------------------------------------------------------------- Conn1 BYTE Id, WG 1, DSW 1 -> Conn2, RG 1, DSR 1 Conn2 BYTE Id, WG 1, DSW 1 -> Conn1, RG 1, DSR 1 Conn3 UINT16 Id, WG 1, DSW 1 -> Conn4, RG 1, DSR 1 Conn4 UINT32 Id, WG 1, DSW 1 -> Conn3, RG 1, DSR 1 Conn5 UINT64 Id, WG 1, DSW 1 -> Conn6, RG 1, DSR 1 Conn6 UINT16 Id, WG 1, DSW 1 -> Conn5, RG 1, DSR 1 */ /* note: PublisherId BYTE 1 is different than UINT16 1 */ /* every connection has exactly 1 Writer- and ReaderGroup, 1 DataSetWriter and -reader, and 1 publish/subscribe variable */ #define DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS 6 UA_NodeId ConnectionIds[DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS]; UA_NodeId WriterGroupIds[DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS]; UA_NodeId PublishedDataSetIds[DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS]; UA_NodeId ReaderGroupIds[DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS]; /* Attention: Publisher and corresponding Subscriber NodeId and DataValue must have the same index e.g. publisherVarIds[0] value is set and subscriberVarIds[0] value is checked at ValidatePublishSubscribe() function */ UA_NodeId publisherVarIds[DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS]; UA_NodeId subscriberVarIds[DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS]; UA_DataValue *fastPathPublisherDataValues[DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS]; UA_DataValue *fastPathSubscriberDataValues[DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS]; for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS; i++) { fastPathPublisherDataValues[i] = 0; fastPathSubscriberDataValues[i] = 0; } const UA_UInt32 WG_Id = 1; const UA_UInt32 DSW_Id = 1; /* setup all Publishers */ /* setup Connection 1: */ UA_NodeId ConnId_1; UA_NodeId_init(&ConnId_1); UA_PublisherIdType Conn1_PublisherIdType = UA_PUBLISHERIDTYPE_BYTE; UA_PublisherId Conn1_PublisherId; Conn1_PublisherId.byte = 1; AddConnection("Conn1", Conn1_PublisherIdType, Conn1_PublisherId, &ConnId_1); ConnectionIds[0] = ConnId_1; UA_NodeId WGId_Conn1_WG1; UA_NodeId_init(&WGId_Conn1_WG1); AddWriterGroup(&ConnId_1, "Conn1_WG1", WG_Id, &WGId_Conn1_WG1); WriterGroupIds[0] = WGId_Conn1_WG1; UA_NodeId DsWId_Conn1_WG1_DS1; UA_NodeId_init(&DsWId_Conn1_WG1_DS1); UA_NodeId PDSId_Conn1_WG1_PDS1; UA_NodeId_init(&PDSId_Conn1_WG1_PDS1); AddPublishedDataSet(&WGId_Conn1_WG1, "Conn1_WG1_PDS1", "Conn1_WG1_DS1", DSW_Id, &PDSId_Conn1_WG1_PDS1, &publisherVarIds[0], &fastPathPublisherDataValues[0], &DsWId_Conn1_WG1_DS1); PublishedDataSetIds[0] = PDSId_Conn1_WG1_PDS1; /* setup Connection 2: */ UA_NodeId ConnId_2; UA_NodeId_init(&ConnId_2); UA_PublisherIdType Conn2_PublisherIdType = UA_PUBLISHERIDTYPE_BYTE; UA_PublisherId Conn2_PublisherId; Conn2_PublisherId.byte = 2; AddConnection("Conn2", Conn2_PublisherIdType, Conn2_PublisherId, &ConnId_2); ConnectionIds[1] = ConnId_2; UA_NodeId WGId_Conn2_WG1; UA_NodeId_init(&WGId_Conn2_WG1); AddWriterGroup(&ConnId_2, "Conn2_WG1", WG_Id, &WGId_Conn2_WG1); WriterGroupIds[1] = WGId_Conn2_WG1; UA_NodeId DsWId_Conn2_WG1_DS1; UA_NodeId_init(&DsWId_Conn2_WG1_DS1); UA_NodeId PDSId_Conn2_WG1_PDS1; UA_NodeId_init(&PDSId_Conn2_WG1_PDS1); AddPublishedDataSet(&WGId_Conn2_WG1, "Conn2_WG1_PDS1", "Conn2_WG1_DS1", DSW_Id, &PDSId_Conn2_WG1_PDS1, &publisherVarIds[1], &fastPathPublisherDataValues[1], &DsWId_Conn2_WG1_DS1); PublishedDataSetIds[1] = PDSId_Conn2_WG1_PDS1; /* setup Connection 3: */ UA_NodeId ConnId_3; UA_NodeId_init(&ConnId_3); UA_PublisherIdType Conn3_PublisherIdType = UA_PUBLISHERIDTYPE_UINT16; UA_PublisherId Conn3_PublisherId; Conn3_PublisherId.uint16 = 1; AddConnection("Conn3", Conn3_PublisherIdType, Conn3_PublisherId, &ConnId_3); ConnectionIds[2] = ConnId_3; UA_NodeId WGId_Conn3_WG1; UA_NodeId_init(&WGId_Conn3_WG1); AddWriterGroup(&ConnId_3, "Conn3_WG1", WG_Id, &WGId_Conn3_WG1); WriterGroupIds[2] = WGId_Conn3_WG1; UA_NodeId DsWId_Conn3_WG1_DS1; UA_NodeId_init(&DsWId_Conn3_WG1_DS1); UA_NodeId PDSId_Conn3_WG1_PDS1; UA_NodeId_init(&PDSId_Conn3_WG1_PDS1); AddPublishedDataSet(&WGId_Conn3_WG1, "Conn3_WG1_PDS1", "Conn3_WG1_DS1", DSW_Id, &PDSId_Conn3_WG1_PDS1, &publisherVarIds[2], &fastPathPublisherDataValues[2], &DsWId_Conn3_WG1_DS1); PublishedDataSetIds[2] = PDSId_Conn3_WG1_PDS1; /* setup Connection 4 */ UA_NodeId ConnId_4; UA_NodeId_init(&ConnId_4); UA_PublisherIdType Conn4_PublisherIdType = UA_PUBLISHERIDTYPE_UINT32; UA_PublisherId Conn4_PublisherId; Conn4_PublisherId.uint32 = 15; AddConnection("Conn4", Conn4_PublisherIdType, Conn4_PublisherId, &ConnId_4); ConnectionIds[3] = ConnId_4; UA_NodeId WGId_Conn4_WG1; UA_NodeId_init(&WGId_Conn4_WG1); AddWriterGroup(&ConnId_4, "Conn4_WG1", WG_Id, &WGId_Conn4_WG1); WriterGroupIds[3] = WGId_Conn4_WG1; UA_NodeId DsWId_Conn4_WG1_DS1; UA_NodeId_init(&DsWId_Conn4_WG1_DS1); UA_NodeId PDSId_Conn4_WG1_PDS1; UA_NodeId_init(&PDSId_Conn4_WG1_PDS1); AddPublishedDataSet(&WGId_Conn4_WG1, "Conn4_WG1_PDS1", "Conn4_WG1_DS1", DSW_Id, &PDSId_Conn4_WG1_PDS1, &publisherVarIds[3], &fastPathPublisherDataValues[3], &DsWId_Conn4_WG1_DS1); PublishedDataSetIds[3] = PDSId_Conn4_WG1_PDS1; /* setup Connection 5 */ UA_NodeId ConnId_5; UA_NodeId_init(&ConnId_5); UA_PublisherIdType Conn5_PublisherIdType = UA_PUBLISHERIDTYPE_UINT64; UA_PublisherId Conn5_PublisherId; Conn5_PublisherId.uint64 = 33; AddConnection("Conn5", Conn5_PublisherIdType, Conn5_PublisherId, &ConnId_5); ConnectionIds[4] = ConnId_5; UA_NodeId WGId_Conn5_WG1; UA_NodeId_init(&WGId_Conn5_WG1); AddWriterGroup(&ConnId_5, "Conn5_WG1", WG_Id, &WGId_Conn5_WG1); WriterGroupIds[4] = WGId_Conn5_WG1; UA_NodeId DsWId_Conn5_WG1_DS1; UA_NodeId_init(&DsWId_Conn5_WG1_DS1); UA_NodeId PDSId_Conn5_WG1_PDS1; UA_NodeId_init(&PDSId_Conn5_WG1_PDS1); AddPublishedDataSet(&WGId_Conn5_WG1, "Conn5_WG1_PDS1", "Conn5_WG1_DS1", DSW_Id, &PDSId_Conn5_WG1_PDS1, &publisherVarIds[4], &fastPathPublisherDataValues[4], &DsWId_Conn5_WG1_DS1); PublishedDataSetIds[4] = PDSId_Conn5_WG1_PDS1; /* setup Connection 6: */ UA_NodeId ConnId_6; UA_NodeId_init(&ConnId_6); UA_PublisherIdType Conn6_PublisherIdType = UA_PUBLISHERIDTYPE_UINT16; UA_PublisherId Conn6_PublisherId; Conn6_PublisherId.uint16 = 2; AddConnection("Conn6", Conn6_PublisherIdType, Conn6_PublisherId, &ConnId_6); ConnectionIds[5] = ConnId_6; UA_NodeId WGId_Conn6_WG1; UA_NodeId_init(&WGId_Conn6_WG1); AddWriterGroup(&ConnId_6, "Conn6_WG1", WG_Id, &WGId_Conn6_WG1); WriterGroupIds[5] = WGId_Conn6_WG1; UA_NodeId DsWId_Conn6_WG1_DS1; UA_NodeId_init(&DsWId_Conn6_WG1_DS1); UA_NodeId PDSId_Conn6_WG1_PDS1; UA_NodeId_init(&PDSId_Conn6_WG1_PDS1); AddPublishedDataSet(&WGId_Conn6_WG1, "Conn6_WG1_PDS1", "Conn6_WG1_DS1", DSW_Id, &PDSId_Conn6_WG1_PDS1, &publisherVarIds[5], &fastPathPublisherDataValues[5], &DsWId_Conn6_WG1_DS1); PublishedDataSetIds[5] = PDSId_Conn6_WG1_PDS1; /* setup all Subscribers */ /* setup Connection 1: */ UA_NodeId RGId_Conn1_RG1; UA_NodeId_init(&RGId_Conn1_RG1); AddReaderGroup(&ConnId_1, "Conn1_RG1", &RGId_Conn1_RG1); UA_NodeId DSRId_Conn1_RG1_DSR1; UA_NodeId_init(&DSRId_Conn1_RG1_DSR1); AddDataSetReader(&RGId_Conn1_RG1, "Conn1_RG1_DSR1", Conn2_PublisherIdType, Conn2_PublisherId, WG_Id, DSW_Id, &subscriberVarIds[1], &fastPathSubscriberDataValues[1], &DSRId_Conn1_RG1_DSR1); ReaderGroupIds[0] = RGId_Conn1_RG1; /* setup Connection 2: */ UA_NodeId RGId_Conn2_RG1; UA_NodeId_init(&RGId_Conn2_RG1); AddReaderGroup(&ConnId_2, "Conn2_RG1", &RGId_Conn2_RG1); UA_NodeId DSRId_Conn2_RG1_DSR1; UA_NodeId_init(&DSRId_Conn2_RG1_DSR1); AddDataSetReader(&RGId_Conn2_RG1, "Conn2_RG1_DSR1", Conn1_PublisherIdType, Conn1_PublisherId, WG_Id, DSW_Id, &subscriberVarIds[0], &fastPathSubscriberDataValues[0], &DSRId_Conn2_RG1_DSR1); ReaderGroupIds[1] = RGId_Conn2_RG1; /* setup Connection 3: */ UA_NodeId RGId_Conn3_RG1; UA_NodeId_init(&RGId_Conn3_RG1); AddReaderGroup(&ConnId_3, "Conn3_RG1", &RGId_Conn3_RG1); UA_NodeId DSRId_Conn3_RG1_DSR1; UA_NodeId_init(&DSRId_Conn3_RG1_DSR1); AddDataSetReader(&RGId_Conn3_RG1, "Conn3_RG1_DSR1", Conn4_PublisherIdType, Conn4_PublisherId, WG_Id, DSW_Id, &subscriberVarIds[3], &fastPathSubscriberDataValues[3], &DSRId_Conn3_RG1_DSR1); ReaderGroupIds[2] = RGId_Conn3_RG1; /* setup Connection 4: */ UA_NodeId RGId_Conn4_RG1; UA_NodeId_init(&RGId_Conn4_RG1); AddReaderGroup(&ConnId_4, "Conn4_RG1", &RGId_Conn4_RG1); UA_NodeId DSRId_Conn4_RG1_DSR1; UA_NodeId_init(&DSRId_Conn4_RG1_DSR1); AddDataSetReader(&RGId_Conn4_RG1, "Conn4_RG1_DSR1", Conn3_PublisherIdType, Conn3_PublisherId, WG_Id, DSW_Id, &subscriberVarIds[2], &fastPathSubscriberDataValues[2], &DSRId_Conn4_RG1_DSR1); ReaderGroupIds[3] = RGId_Conn4_RG1; /* setup Connection 5: */ UA_NodeId RGId_Conn5_RG1; UA_NodeId_init(&RGId_Conn5_RG1); AddReaderGroup(&ConnId_5, "Conn5_RG1", &RGId_Conn5_RG1); UA_NodeId DSRId_Conn5_RG1_DSR1; UA_NodeId_init(&DSRId_Conn5_RG1_DSR1); AddDataSetReader(&RGId_Conn5_RG1, "Conn5_RG1_DSR1", Conn6_PublisherIdType, Conn6_PublisherId, WG_Id, DSW_Id, &subscriberVarIds[5], &fastPathSubscriberDataValues[5], &DSRId_Conn5_RG1_DSR1); ReaderGroupIds[4] = RGId_Conn5_RG1; /* setup Connection 6: */ UA_NodeId RGId_Conn6_RG1; UA_NodeId_init(&RGId_Conn6_RG1); AddReaderGroup(&ConnId_6, "Conn6_RG1", &RGId_Conn6_RG1); UA_NodeId DSRId_Conn6_RG1_DSR1; UA_NodeId_init(&DSRId_Conn6_RG1_DSR1); AddDataSetReader(&RGId_Conn6_RG1, "Conn6_RG1_DSR1", Conn5_PublisherIdType, Conn5_PublisherId, WG_Id, DSW_Id, &subscriberVarIds[4], &fastPathSubscriberDataValues[4], &DSRId_Conn6_RG1_DSR1); ReaderGroupIds[5] = RGId_Conn6_RG1; /* freeze all Groups */ for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_freezeWriterGroupConfiguration(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_freezeReaderGroupConfiguration(server, ReaderGroupIds[i])); } /* set groups operational */ for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setWriterGroupOperational(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setReaderGroupOperational(server, ReaderGroupIds[i])); } /* check that publish/subscribe works -> set some test values */ ValidatePublishSubscribe(DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS, publisherVarIds, subscriberVarIds, fastPathPublisherDataValues, fastPathSubscriberDataValues, 10, (UA_UInt32) 100, 3); ValidatePublishSubscribe(DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS, publisherVarIds, subscriberVarIds, fastPathPublisherDataValues, fastPathSubscriberDataValues, 50, (UA_UInt32) 100, 3); ValidatePublishSubscribe(DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS, publisherVarIds, subscriberVarIds, fastPathPublisherDataValues, fastPathSubscriberDataValues, 100, (UA_UInt32) 100, 3); /* set groups to disabled */ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "disable groups"); for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setWriterGroupDisabled(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setReaderGroupDisabled(server, ReaderGroupIds[i])); } /* unfreeze groups */ for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_unfreezeWriterGroupConfiguration(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_unfreezeReaderGroupConfiguration(server, ReaderGroupIds[i])); } UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "remove PublishedDataSets"); for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_removePublishedDataSet(server, PublishedDataSetIds[i])); } UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "remove Connection"); for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_removePubSubConnection(server, ConnectionIds[i])); } if (UseFastPath) { for (size_t i = 0; i < DOTEST_MULTIPLE_CONNECTIONS_MAX_COMPONENTS; i++) { UA_DataValue_clear(fastPathPublisherDataValues[i]); UA_DataValue_delete(fastPathPublisherDataValues[i]); UA_DataValue_clear(fastPathSubscriberDataValues[i]); UA_DataValue_delete(fastPathSubscriberDataValues[i]); } } UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "DoTest_multiple_Connections() end"); } /***************************************************************************************************/ /* test with multiple connections */ START_TEST(Test_multiple_connections) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "START: Test_multiple_connections"); /* note: fast-path does not support - multiple groups and/or DataSets yet, therefore we only test multiple connections - STRING publisherIds */ UseFastPath = UA_FALSE; UseRawEncoding = UA_FALSE; DoTest_multiple_Connections(); UseFastPath = UA_FALSE; UseRawEncoding = UA_TRUE; DoTest_multiple_Connections(); UseFastPath = UA_TRUE; UseRawEncoding = UA_FALSE; DoTest_multiple_Connections(); UseFastPath = UA_TRUE; UseRawEncoding = UA_TRUE; DoTest_multiple_Connections(); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "END: Test_multiple_connections"); } END_TEST /***************************************************************************************************/ #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL /* Read PublisherId value of PubSub information model -> check that string read works correctly */ static void Test_string_PublisherId_InformationModel(const UA_NodeId connectionId, const UA_String expectedStringIdValue) { /* Get PublisherId node */ UA_RelativePathElement rpe; UA_RelativePathElement_init(&rpe); rpe.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES);; rpe.isInverse = false; rpe.includeSubtypes = true; rpe.targetName = UA_QUALIFIEDNAME(0, "PublisherId"); UA_BrowsePath bp; UA_BrowsePath_init(&bp); bp.startingNode = connectionId; bp.relativePath.elementsSize = 1; bp.relativePath.elements = &rpe; UA_BrowsePathResult bpr; UA_BrowsePathResult_init(&bpr); bpr = UA_Server_translateBrowsePathToNodeIds(server, &bp); ck_assert_int_eq(UA_STATUSCODE_GOOD, bpr.statusCode); ck_assert_uint_eq(1, bpr.targetsSize); UA_NodeId PublisherIdNode = bpr.targets[0].targetId.nodeId; /* Read value */ UA_Variant PublisherIdValue; UA_Variant_init(&PublisherIdValue); UA_StatusCode res = UA_Server_readValue(server, PublisherIdNode, &PublisherIdValue); ck_assert_int_eq(UA_STATUSCODE_GOOD, res); ck_assert(true == UA_Variant_hasScalarType(&PublisherIdValue, &UA_TYPES[UA_TYPES_STRING])); ck_assert(true == UA_String_equal(&expectedStringIdValue, (UA_String*) PublisherIdValue.data)); UA_Variant_clear(&PublisherIdValue); UA_BrowsePathResult_clear(&bpr); } #endif /***************************************************************************************************/ static void DoTest_string_PublisherId(void) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "DoTest_string_PublisherId() begin"); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "fast-path = %s", (UseFastPath) ? "enabled" : "disabled"); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "raw encoding = %s", (UseRawEncoding) ? "enabled" : "disabled"); /* Writers -> Readers ---------------------------------------------------------------------------------- Conn1 STRING Id "H" WG 1 DSW 1 -> Conn2, RG 1, DSR 1 Conn2 STRING Id "h" WG 1 DSW 1 -> Conn1, RG 1, DSR 1 Conn3 STRING Id "hallo" WG 1 DSW 1 -> Conn5, RG 1, DSR 1 Conn4 STRING Id "hallo1" WG 1 DSW 1 -> Conn3, RG 1, DSR 1 Conn5 STRING Id "Hallo" WG 1 DSW 1 -> Conn4, RG 1, DSR 1 */ /* every connection has exactly 1 Writer- and ReaderGroup, 1 DataSetWriter and -reader, and 1 publish/subscribe variable */ #define DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS 5 UA_NodeId ConnectionIds[DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS]; UA_NodeId WriterGroupIds[DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS]; UA_NodeId PublishedDataSetIds[DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS]; UA_NodeId ReaderGroupIds[DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS]; /* Attention: Publisher and corresponding Subscriber NodeId and DataValue must have the same index e.g. publisherVarIds[0] value is set and subscriberVarIds[0] value is checked at ValidatePublishSubscribe() function */ UA_NodeId publisherVarIds[DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS]; UA_NodeId subscriberVarIds[DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS]; UA_DataValue *fastPathPublisherDataValues[DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS]; UA_DataValue *fastPathSubscriberDataValues[DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS]; for (UA_UInt32 i = 0; i < DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS; i++) { fastPathPublisherDataValues[i] = 0; fastPathSubscriberDataValues[i] = 0; } const UA_UInt32 WG_Id = 1; const UA_UInt32 DSW_Id = 1; /* setup all Publishers */ { /* create a local scope and allocate string PublisherIds on stack to check that there are no memory issues with strings (deep copy of strings is done etc.) */ /* setup Connection 1: */ UA_NodeId ConnId_1; UA_NodeId_init(&ConnId_1); UA_PublisherIdType Conn1_PublisherIdType = UA_PUBLISHERIDTYPE_STRING; UA_PublisherId Conn1_PublisherId; Conn1_PublisherId.string = UA_STRING("H"); // allocate string on stack AddConnection("Conn1", Conn1_PublisherIdType, Conn1_PublisherId, &ConnId_1); ConnectionIds[0] = ConnId_1; UA_NodeId WGId_Conn1_WG1; UA_NodeId_init(&WGId_Conn1_WG1); AddWriterGroup(&ConnId_1, "Conn1_WG1", WG_Id, &WGId_Conn1_WG1); WriterGroupIds[0] = WGId_Conn1_WG1; UA_NodeId DsWId_Conn1_WG1_DS1; UA_NodeId_init(&DsWId_Conn1_WG1_DS1); UA_NodeId PDSId_Conn1_WG1_PDS1; UA_NodeId_init(&PDSId_Conn1_WG1_PDS1); AddPublishedDataSet(&WGId_Conn1_WG1, "Conn1_WG1_PDS1", "Conn1_WG1_DS1", DSW_Id, &PDSId_Conn1_WG1_PDS1, &publisherVarIds[0], &fastPathPublisherDataValues[0], &DsWId_Conn1_WG1_DS1); PublishedDataSetIds[0] = PDSId_Conn1_WG1_PDS1; /* setup Connection 2: */ UA_NodeId ConnId_2; UA_NodeId_init(&ConnId_2); UA_PublisherIdType Conn2_PublisherIdType = UA_PUBLISHERIDTYPE_STRING; UA_PublisherId Conn2_PublisherId; Conn2_PublisherId.string = UA_STRING("h"); AddConnection("Conn2", Conn2_PublisherIdType, Conn2_PublisherId, &ConnId_2); ConnectionIds[1] = ConnId_2; UA_NodeId WGId_Conn2_WG1; UA_NodeId_init(&WGId_Conn2_WG1); AddWriterGroup(&ConnId_2, "Conn2_WG1", WG_Id, &WGId_Conn2_WG1); WriterGroupIds[1] = WGId_Conn2_WG1; UA_NodeId DsWId_Conn2_WG1_DS1; UA_NodeId_init(&DsWId_Conn2_WG1_DS1); UA_NodeId PDSId_Conn2_WG1_PDS1; UA_NodeId_init(&PDSId_Conn2_WG1_PDS1); AddPublishedDataSet(&WGId_Conn2_WG1, "Conn2_WG1_PDS1", "Conn2_WG1_DS1", DSW_Id, &PDSId_Conn2_WG1_PDS1, &publisherVarIds[1], &fastPathPublisherDataValues[1], &DsWId_Conn2_WG1_DS1); PublishedDataSetIds[1] = PDSId_Conn2_WG1_PDS1; /* setup Connection 3: */ UA_NodeId ConnId_3; UA_NodeId_init(&ConnId_3); UA_PublisherIdType Conn3_PublisherIdType = UA_PUBLISHERIDTYPE_STRING; UA_PublisherId Conn3_PublisherId; Conn3_PublisherId.string = UA_STRING("hallo"); AddConnection("Conn3", Conn3_PublisherIdType, Conn3_PublisherId, &ConnId_3); ConnectionIds[2] = ConnId_3; UA_NodeId WGId_Conn3_WG1; UA_NodeId_init(&WGId_Conn3_WG1); AddWriterGroup(&ConnId_3, "Conn3_WG1", WG_Id, &WGId_Conn3_WG1); WriterGroupIds[2] = WGId_Conn3_WG1; UA_NodeId DsWId_Conn3_WG1_DS1; UA_NodeId_init(&DsWId_Conn3_WG1_DS1); UA_NodeId PDSId_Conn3_WG1_PDS1; UA_NodeId_init(&PDSId_Conn3_WG1_PDS1); AddPublishedDataSet(&WGId_Conn3_WG1, "Conn3_WG1_PDS1", "Conn3_WG1_DS1", DSW_Id, &PDSId_Conn3_WG1_PDS1, &publisherVarIds[2], &fastPathPublisherDataValues[2], &DsWId_Conn3_WG1_DS1); PublishedDataSetIds[2] = PDSId_Conn3_WG1_PDS1; /* setup Connection 4 */ UA_NodeId ConnId_4; UA_NodeId_init(&ConnId_4); UA_PublisherIdType Conn4_PublisherIdType = UA_PUBLISHERIDTYPE_STRING; UA_PublisherId Conn4_PublisherId; Conn4_PublisherId.string = UA_STRING("hallo1"); AddConnection("Conn4", Conn4_PublisherIdType, Conn4_PublisherId, &ConnId_4); ConnectionIds[3] = ConnId_4; UA_NodeId WGId_Conn4_WG1; UA_NodeId_init(&WGId_Conn4_WG1); AddWriterGroup(&ConnId_4, "Conn4_WG1", WG_Id, &WGId_Conn4_WG1); WriterGroupIds[3] = WGId_Conn4_WG1; UA_NodeId DsWId_Conn4_WG1_DS1; UA_NodeId_init(&DsWId_Conn4_WG1_DS1); UA_NodeId PDSId_Conn4_WG1_PDS1; UA_NodeId_init(&PDSId_Conn4_WG1_PDS1); AddPublishedDataSet(&WGId_Conn4_WG1, "Conn4_WG1_PDS1", "Conn4_WG1_DS1", DSW_Id, &PDSId_Conn4_WG1_PDS1, &publisherVarIds[3], &fastPathPublisherDataValues[3], &DsWId_Conn4_WG1_DS1); PublishedDataSetIds[3] = PDSId_Conn4_WG1_PDS1; /* setup Connection 5 */ UA_NodeId ConnId_5; UA_NodeId_init(&ConnId_5); UA_PublisherIdType Conn5_PublisherIdType = UA_PUBLISHERIDTYPE_STRING; UA_PublisherId Conn5_PublisherId; Conn5_PublisherId.string = UA_STRING("Hallo"); AddConnection("Conn5", Conn5_PublisherIdType, Conn5_PublisherId, &ConnId_5); ConnectionIds[4] = ConnId_5; UA_NodeId WGId_Conn5_WG1; UA_NodeId_init(&WGId_Conn5_WG1); AddWriterGroup(&ConnId_5, "Conn5_WG1", WG_Id, &WGId_Conn5_WG1); WriterGroupIds[4] = WGId_Conn5_WG1; UA_NodeId DsWId_Conn5_WG1_DS1; UA_NodeId_init(&DsWId_Conn5_WG1_DS1); UA_NodeId PDSId_Conn5_WG1_PDS1; UA_NodeId_init(&PDSId_Conn5_WG1_PDS1); AddPublishedDataSet(&WGId_Conn5_WG1, "Conn5_WG1_PDS1", "Conn5_WG1_DS1", DSW_Id, &PDSId_Conn5_WG1_PDS1, &publisherVarIds[4], &fastPathPublisherDataValues[4], &DsWId_Conn5_WG1_DS1); PublishedDataSetIds[4] = PDSId_Conn5_WG1_PDS1; /* setup all Subscribers */ /* setup Connection 1: */ UA_NodeId RGId_Conn1_RG1; UA_NodeId_init(&RGId_Conn1_RG1); AddReaderGroup(&ConnId_1, "Conn1_RG1", &RGId_Conn1_RG1); UA_NodeId DSRId_Conn1_RG1_DSR1; UA_NodeId_init(&DSRId_Conn1_RG1_DSR1); AddDataSetReader(&RGId_Conn1_RG1, "Conn1_RG1_DSR1", Conn2_PublisherIdType, Conn2_PublisherId, WG_Id, DSW_Id, &subscriberVarIds[1], &fastPathSubscriberDataValues[1], &DSRId_Conn1_RG1_DSR1); ReaderGroupIds[0] = RGId_Conn1_RG1; /* setup Connection 2: */ UA_NodeId RGId_Conn2_RG1; UA_NodeId_init(&RGId_Conn2_RG1); AddReaderGroup(&ConnId_2, "Conn2_RG1", &RGId_Conn2_RG1); UA_NodeId DSRId_Conn2_RG1_DSR1; UA_NodeId_init(&DSRId_Conn2_RG1_DSR1); AddDataSetReader(&RGId_Conn2_RG1, "Conn2_RG1_DSR1", Conn1_PublisherIdType, Conn1_PublisherId, WG_Id, DSW_Id, &subscriberVarIds[0], &fastPathSubscriberDataValues[0], &DSRId_Conn2_RG1_DSR1); ReaderGroupIds[1] = RGId_Conn2_RG1; /* setup Connection 3: */ UA_NodeId RGId_Conn3_RG1; UA_NodeId_init(&RGId_Conn3_RG1); AddReaderGroup(&ConnId_3, "Conn3_RG1", &RGId_Conn3_RG1); UA_NodeId DSRId_Conn3_RG1_DSR1; UA_NodeId_init(&DSRId_Conn3_RG1_DSR1); AddDataSetReader(&RGId_Conn3_RG1, "Conn3_RG1_DSR1", Conn5_PublisherIdType, Conn5_PublisherId, WG_Id, DSW_Id, &subscriberVarIds[4], &fastPathSubscriberDataValues[4], &DSRId_Conn3_RG1_DSR1); ReaderGroupIds[2] = RGId_Conn3_RG1; /* setup Connection 4: */ UA_NodeId RGId_Conn4_RG1; UA_NodeId_init(&RGId_Conn4_RG1); AddReaderGroup(&ConnId_4, "Conn4_RG1", &RGId_Conn4_RG1); UA_NodeId DSRId_Conn4_RG1_DSR1; UA_NodeId_init(&DSRId_Conn4_RG1_DSR1); AddDataSetReader(&RGId_Conn4_RG1, "Conn4_RG1_DSR1", Conn3_PublisherIdType, Conn3_PublisherId, WG_Id, DSW_Id, &subscriberVarIds[2], &fastPathSubscriberDataValues[2], &DSRId_Conn4_RG1_DSR1); ReaderGroupIds[3] = RGId_Conn4_RG1; /* setup Connection 5: */ UA_NodeId RGId_Conn5_RG1; UA_NodeId_init(&RGId_Conn5_RG1); AddReaderGroup(&ConnId_5, "Conn5_RG1", &RGId_Conn5_RG1); UA_NodeId DSRId_Conn5_RG1_DSR1; UA_NodeId_init(&DSRId_Conn5_RG1_DSR1); AddDataSetReader(&RGId_Conn5_RG1, "Conn5_RG1_DSR1", Conn4_PublisherIdType, Conn4_PublisherId, WG_Id, DSW_Id, &subscriberVarIds[3], &fastPathSubscriberDataValues[3], &DSRId_Conn5_RG1_DSR1); ReaderGroupIds[4] = RGId_Conn5_RG1; } /* end of configuration scope -> string PublisherIds are deallocated from stack deep copy of string PublisherId is done by UA_Server_addPubSubConnection() */ /* freeze all Groups */ for (UA_UInt32 i = 0; i < DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_freezeWriterGroupConfiguration(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_freezeReaderGroupConfiguration(server, ReaderGroupIds[i])); } /* set groups operational */ for (UA_UInt32 i = 0; i < DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setWriterGroupOperational(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setReaderGroupOperational(server, ReaderGroupIds[i])); } /* check that publish/subscribe works -> set some test values */ ValidatePublishSubscribe(DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS, publisherVarIds, subscriberVarIds, fastPathPublisherDataValues, fastPathSubscriberDataValues, 10, (UA_UInt32) 100, 3); ValidatePublishSubscribe(DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS, publisherVarIds, subscriberVarIds, fastPathPublisherDataValues, fastPathSubscriberDataValues, 50, (UA_UInt32) 100, 3); ValidatePublishSubscribe(DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS, publisherVarIds, subscriberVarIds, fastPathPublisherDataValues, fastPathSubscriberDataValues, 100, (UA_UInt32) 100, 3); /* check PubSub information model - string Ids */ #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL char *expectedPublisherIds[] = { "H", "h", "hallo", "hallo1", "Hallo" }; for (UA_UInt32 i = 0; i < DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS; i++) { Test_string_PublisherId_InformationModel(ConnectionIds[i], UA_STRING(expectedPublisherIds[i])); } #endif /* set groups to disabled */ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "disable groups"); for (UA_UInt32 i = 0; i < DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setWriterGroupDisabled(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setReaderGroupDisabled(server, ReaderGroupIds[i])); } /* unfreeze groups */ for (UA_UInt32 i = 0; i < DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_unfreezeWriterGroupConfiguration(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_unfreezeReaderGroupConfiguration(server, ReaderGroupIds[i])); } UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "remove PublishedDataSets"); for (UA_UInt32 i = 0; i < DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_removePublishedDataSet(server, PublishedDataSetIds[i])); } UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "remove Connection"); for (UA_UInt32 i = 0; i < DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_removePubSubConnection(server, ConnectionIds[i])); } if (UseFastPath) { for (size_t i = 0; i < DOTEST_STRING_PUBLISHERID_MAX_COMPONENTS; i++) { UA_DataValue_clear(fastPathPublisherDataValues[i]); UA_DataValue_delete(fastPathPublisherDataValues[i]); UA_DataValue_clear(fastPathSubscriberDataValues[i]); UA_DataValue_delete(fastPathSubscriberDataValues[i]); } } UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "DoTest_string_PublisherId() end"); } /***************************************************************************************************/ /* test string PublisherId */ START_TEST(Test_string_publisherId) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "START: Test_string_publisherId"); /* note: fast-path does not support STRING publisherIds */ UseFastPath = UA_FALSE; UseRawEncoding = UA_FALSE; DoTest_string_PublisherId(); UseRawEncoding = UA_TRUE; DoTest_string_PublisherId(); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "END: Test_string_publisherId"); } END_TEST #ifdef UA_ENABLE_PUBSUB_FILE_CONFIG /***************************************************************************************************/ START_TEST(Test_string_publisherId_file_config) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "START: Test_string_publisherId_file_config"); UseRawEncoding = UA_FALSE; UseFastPath = UA_FALSE; #define STRING_PUBLISHERID_FILE_MAX_COMPONENTS 1 /* Attention: Publisher and corresponding Subscriber NodeId and DataValue must have the same index e.g. publisherVarIds[0] value is set and subscriberVarIds[0] value is checked at ValidatePublishSubscribe() function */ UA_NodeId publisherVarIds[STRING_PUBLISHERID_FILE_MAX_COMPONENTS]; UA_NodeId subscriberVarIds[STRING_PUBLISHERID_FILE_MAX_COMPONENTS]; UA_DataValue *fastPathPublisherDataValues[STRING_PUBLISHERID_FILE_MAX_COMPONENTS]; UA_DataValue *fastPathSubscriberDataValues[STRING_PUBLISHERID_FILE_MAX_COMPONENTS]; for (UA_UInt32 i = 0; i < STRING_PUBLISHERID_FILE_MAX_COMPONENTS; i++) { fastPathPublisherDataValues[i] = 0; fastPathSubscriberDataValues[i] = 0; } /* we do not use a file, but setup PubSubConfigurationDataType structure and encode it to a bytestring to simulate file read */ UA_ByteString encodedConfigDataBuffer; UA_ByteString_init(&encodedConfigDataBuffer); /* constants for configuration */ #define DS_MESSAGECONTENT_MASK (UA_UADPDATASETMESSAGECONTENTMASK_STATUS | \ UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP) #define MAX_NETWORKMESSAGE_SIZE 1400 #define UADP_NETWORKMESSAGE_CONTENT_MASK \ (UA_UADPNETWORKMESSAGECONTENTMASK_PUBLISHERID | UA_UADPNETWORKMESSAGECONTENTMASK_GROUPHEADER | \ UA_UADPNETWORKMESSAGECONTENTMASK_WRITERGROUPID | UA_UADPNETWORKMESSAGECONTENTMASK_PAYLOADHEADER) { /* we use a local scope to make sure that string PublisherId configuration works correctly -> e.g. deep copy of Id */ UA_PubSubConfigurationDataType config; UA_PubSubConfigurationDataType_init(&config); config.enabled = UA_TRUE; /* PublishedDataSet config */ config.publishedDataSetsSize = 1; config.publishedDataSets = UA_PublishedDataSetDataType_new(); ck_assert(config.publishedDataSets != 0); UA_PublishedDataSetDataType *pds = config.publishedDataSets; UA_PublishedDataSetDataType_init(pds); pds->name = UA_STRING_ALLOC("PublishedDataSet 1"); UA_DataSetMetaDataType dataSetMetaData; UA_DataSetMetaDataType_init(&dataSetMetaData); dataSetMetaData.name = UA_STRING_ALLOC("PublishedDataSet 1"); dataSetMetaData.fieldsSize = 1; dataSetMetaData.fields = UA_FieldMetaData_new(); ck_assert(dataSetMetaData.fields != 0); UA_FieldMetaData_init(dataSetMetaData.fields); dataSetMetaData.fields->name = UA_STRING_ALLOC("Field 0"); dataSetMetaData.fields->fieldFlags = UA_DATASETFIELDFLAGS_NONE; dataSetMetaData.fields->builtInType = UA_TYPES_INT32; dataSetMetaData.fields->dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_INT32); dataSetMetaData.fields->valueRank = UA_VALUERANK_SCALAR; pds->dataSetMetaData = dataSetMetaData; UA_PublishedDataItemsDataType *pdsDataItems = UA_PublishedDataItemsDataType_new(); ck_assert(pdsDataItems != 0); UA_PublishedDataItemsDataType_init(pdsDataItems); pdsDataItems->publishedDataSize = 1; pdsDataItems->publishedData = UA_PublishedVariableDataType_new(); ck_assert(pdsDataItems->publishedData != 0); UA_PublishedVariableDataType_init(pdsDataItems->publishedData); pdsDataItems->publishedData->attributeId = UA_ATTRIBUTEID_VALUE; /* Create variable to publish integer data */ UA_VariableAttributes attr = UA_VariableAttributes_default; attr.description = UA_LOCALIZEDTEXT("en-US","Published Int32"); attr.displayName = UA_LOCALIZEDTEXT("en-US","Published Int32"); attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId; UA_Int32 publisherData = 42; UA_Variant_setScalar(&attr.value, &publisherData, &UA_TYPES[UA_TYPES_INT32]); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_addVariableNode(server, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "Published Int32"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr, NULL, &(publisherVarIds[0]))); UA_NodeId_copy(&(publisherVarIds[0]), &(pdsDataItems->publishedData->publishedVariable)); pds->dataSetSource.encoding = UA_EXTENSIONOBJECT_DECODED; pds->dataSetSource.content.decoded.type = &UA_TYPES[UA_TYPES_PUBLISHEDDATAITEMSDATATYPE]; pds->dataSetSource.content.decoded.data = pdsDataItems; /* connection config */ config.connectionsSize = 1; config.connections = UA_PubSubConnectionDataType_new(); ck_assert(config.connections != 0); UA_PubSubConnectionDataType *connection = config.connections; UA_PubSubConnectionDataType_init(connection); connection->name = UA_STRING_ALLOC("My Connection"); connection->enabled = true; UA_String publisherIdString = UA_STRING("Publisher 1"); UA_Variant_setScalarCopy(&connection->publisherId, &publisherIdString, &UA_TYPES[UA_TYPES_STRING]); // TODO? connection->transportProfileUri = UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp"); UA_NetworkAddressUrlDataType *addr = UA_NetworkAddressUrlDataType_new(); ck_assert(addr != 0); UA_NetworkAddressUrlDataType_init(addr); addr->url = UA_STRING_ALLOC("opc.udp://224.0.0.22:4840/"); connection->address.encoding = UA_EXTENSIONOBJECT_DECODED; connection->address.content.decoded.type = &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]; connection->address.content.decoded.data = addr; /* WriterGroup config */ connection->writerGroupsSize = 1; connection->writerGroups = UA_WriterGroupDataType_new(); ck_assert(connection->writerGroups != 0); UA_WriterGroupDataType *wg = connection->writerGroups; UA_WriterGroupDataType_init(wg); wg->enabled = true; wg->name = UA_STRING_ALLOC("WriterGroup 1"); wg->maxNetworkMessageSize = MAX_NETWORKMESSAGE_SIZE; wg->writerGroupId = 1; wg->publishingInterval = 50; wg->keepAliveTime = 1000.00; UA_UadpWriterGroupMessageDataType *wgMessageSettings = UA_UadpWriterGroupMessageDataType_new(); ck_assert(wgMessageSettings != 0); UA_UadpWriterGroupMessageDataType_init(wgMessageSettings); wgMessageSettings->networkMessageContentMask = UADP_NETWORKMESSAGE_CONTENT_MASK; wg->messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED; wg->messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]; wg->messageSettings.content.decoded.data = wgMessageSettings; /* DataSetWriter config */ wg->dataSetWritersSize = 1; wg->dataSetWriters = UA_DataSetWriterDataType_new(); ck_assert(wg->dataSetWriters != 0); UA_DataSetWriterDataType *dsw = &wg->dataSetWriters[0]; dsw->enabled = UA_TRUE; dsw->name = UA_STRING_ALLOC("DataSetWriter 1"); dsw->dataSetWriterId = 1; dsw->dataSetFieldContentMask = UA_DATASETFIELDCONTENTMASK_NONE; dsw->keyFrameCount = 1; dsw->dataSetName = UA_STRING_ALLOC("PublishedDataSet 1"); UA_UadpDataSetWriterMessageDataType *dswMessageSettings = UA_UadpDataSetWriterMessageDataType_new(); ck_assert(dswMessageSettings != 0); UA_UadpDataSetWriterMessageDataType_init(dswMessageSettings); dswMessageSettings->dataSetMessageContentMask = DS_MESSAGECONTENT_MASK; dsw->messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED; dsw->messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_UADPDATASETWRITERMESSAGEDATATYPE]; dsw->messageSettings.content.decoded.data = dswMessageSettings; // ReaderGroup connection->readerGroupsSize = 1; connection->readerGroups = UA_ReaderGroupDataType_new(); ck_assert(connection->readerGroups != 0); UA_ReaderGroupDataType *rg = &connection->readerGroups[0]; UA_ReaderGroupDataType_init(rg); rg->enabled = UA_TRUE; rg->name = UA_STRING_ALLOC("ReaderGroup 1"); rg->maxNetworkMessageSize = MAX_NETWORKMESSAGE_SIZE; // DataSetReader rg->dataSetReadersSize = 1; rg->dataSetReaders = UA_DataSetReaderDataType_new(); ck_assert(rg->dataSetReaders != 0); UA_DataSetReaderDataType *dsr = &rg->dataSetReaders[0]; UA_DataSetReaderDataType_init(dsr); dsr->name = UA_STRING_ALLOC("DataSetReader 1"); dsr->enabled = true; UA_Variant_setScalarCopy(&dsr->publisherId, &publisherIdString, &UA_TYPES[UA_TYPES_STRING]); dsr->writerGroupId = 1; dsr->dataSetWriterId = 1; UA_DataSetMetaDataType dsrDataSetMetaData; UA_DataSetMetaDataType_init(&dsrDataSetMetaData); dsrDataSetMetaData.name = UA_STRING_ALLOC("PublishedDataSet 1"); dsrDataSetMetaData.fieldsSize = 1; dsrDataSetMetaData.fields = UA_FieldMetaData_new(); ck_assert(dsrDataSetMetaData.fields != 0); dsrDataSetMetaData.fields->name = UA_STRING_ALLOC("Field_0"); dsrDataSetMetaData.fields->builtInType = UA_TYPES_INT32; dsrDataSetMetaData.fields->dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_INT32); dsrDataSetMetaData.fields->valueRank = UA_VALUERANK_SCALAR; dsr->dataSetMetaData = dsrDataSetMetaData; UA_TargetVariablesDataType *targetVars = UA_TargetVariablesDataType_new(); ck_assert(targetVars != 0); UA_TargetVariablesDataType_init(targetVars); targetVars->targetVariablesSize = 1; targetVars->targetVariables = UA_FieldTargetDataType_new(); ck_assert(targetVars->targetVariables != 0); targetVars->targetVariables->attributeId = UA_ATTRIBUTEID_VALUE; /* Variable to subscribe data */ attr = UA_VariableAttributes_default; attr.description = UA_LOCALIZEDTEXT("en-US", "Subscribed Int32"); attr.displayName = UA_LOCALIZEDTEXT("en-US", "Subscribed Int32"); attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId; UA_Int32 subscriberData = 0; UA_Variant_setScalar(&attr.value, &subscriberData, &UA_TYPES[UA_TYPES_INT32]); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_addVariableNode(server, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "Subscribed Int32"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr, NULL, &(subscriberVarIds[0]))); UA_NodeId_copy(&(subscriberVarIds[0]), &(targetVars->targetVariables->targetNodeId)); dsr->subscribedDataSet.encoding = UA_EXTENSIONOBJECT_DECODED; dsr->subscribedDataSet.content.decoded.type = &UA_TYPES[UA_TYPES_TARGETVARIABLESDATATYPE]; dsr->subscribedDataSet.content.decoded.data = targetVars; dsr->dataSetFieldContentMask = UA_DATASETFIELDCONTENTMASK_NONE; dsr->messageReceiveTimeout = 400.0; dsr->keyFrameCount = 1; UA_UadpDataSetReaderMessageDataType *dsrMessageSettings = UA_UadpDataSetReaderMessageDataType_new(); ck_assert(dsrMessageSettings != 0); UA_UadpDataSetReaderMessageDataType_init(dsrMessageSettings); dsrMessageSettings->dataSetMessageContentMask = DS_MESSAGECONTENT_MASK; dsrMessageSettings->networkMessageContentMask = UADP_NETWORKMESSAGE_CONTENT_MASK; dsrMessageSettings->publishingInterval = 50; dsr->messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED; dsr->messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_UADPDATASETREADERMESSAGEDATATYPE]; dsr->messageSettings.content.decoded.data = dsrMessageSettings; /* encode to bytestring to simulate PubSub file config read */ UA_UABinaryFileDataType BinaryFileData; UA_UABinaryFileDataType_init(&BinaryFileData); UA_Variant_setScalar(&BinaryFileData.body, (void*) &config, &UA_TYPES[UA_TYPES_PUBSUBCONFIGURATIONDATATYPE]); UA_ExtensionObject extObj; UA_ExtensionObject_init(&extObj); extObj.encoding = UA_EXTENSIONOBJECT_DECODED; extObj.content.decoded.type = &UA_TYPES[UA_TYPES_UABINARYFILEDATATYPE]; extObj.content.decoded.data = &BinaryFileData; size_t fileSize = UA_ExtensionObject_calcSizeBinary(&extObj); encodedConfigDataBuffer.data = (UA_Byte*)UA_calloc(fileSize, sizeof(UA_Byte)); ck_assert(encodedConfigDataBuffer.data != 0); encodedConfigDataBuffer.length = fileSize; UA_Byte *bufferPos = encodedConfigDataBuffer.data; ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_ExtensionObject_encodeBinary(&extObj, &bufferPos, bufferPos + fileSize)); UA_PubSubConfigurationDataType_clear(&config); } /* load and apply config from ByteString buffer */ UA_LOCK(&server->serviceMutex); ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_PubSubManager_loadPubSubConfigFromByteString(server, encodedConfigDataBuffer)); UA_UNLOCK(&server->serviceMutex); /* groups are already operational */ /* check that publish/subscribe works -> set some test values */ ValidatePublishSubscribe(STRING_PUBLISHERID_FILE_MAX_COMPONENTS, &publisherVarIds[0], &subscriberVarIds[0], &fastPathPublisherDataValues[0], &fastPathSubscriberDataValues[0], 10, (UA_UInt32) 100, 3); ValidatePublishSubscribe(STRING_PUBLISHERID_FILE_MAX_COMPONENTS, &publisherVarIds[0], &subscriberVarIds[0], &fastPathPublisherDataValues[0], &fastPathSubscriberDataValues[0], 33, (UA_UInt32) 100, 3); ValidatePublishSubscribe(STRING_PUBLISHERID_FILE_MAX_COMPONENTS, &publisherVarIds[0], &subscriberVarIds[0], &fastPathPublisherDataValues[0], &fastPathSubscriberDataValues[0], 44, (UA_UInt32) 100, 3); UA_ByteString_clear(&encodedConfigDataBuffer); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "END: Test_string_publisherId_file_config"); } END_TEST #endif /* UA_ENABLE_PUBSUB_FILE_CONFIG */ /***************************************************************************************************/ static void DoTest_multiple_Groups(void) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "DoTest_multiple_Groups() begin"); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "fast-path = %s", (UseFastPath) ? "enabled" : "disabled"); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "raw encoding = %s", (UseRawEncoding) ? "enabled" : "disabled"); /* Writers -> Readers -> Var Index ---------------------------------------------------------------------------------- Conn1 BYTE Id WG 1, DSW 1 -> Conn2, RG 2, DSR 1 0 WG 2, DSW 1 -> Conn2, RG 1, DSR 1 1 WG 3, DSW 1 -> Conn3, RG 1, DSR 1 2 WG 4, DSW 1 -> Conn1, RG 1, DSR 1 3 Conn2 BYTE Id WG 1, DSW 1 -> Conn1, RG 3, DSR 1 4 WG 2, DSW 1 -> Conn3, RG 2, DSR 1 5 Conn3 UINT16 Id WG 1, DSW 1 -> Conn1, RG 2, DSR 1 6 WG 2, DSW 1 -> Conn1, RG 4, DSR 1 7 */ #define DOTEST_MULTIPLE_GROUPS_MAX_CONNECTIONS 3 UA_NodeId ConnectionIds[DOTEST_MULTIPLE_GROUPS_MAX_CONNECTIONS]; #define DOTEST_MULTIPLE_GROUPS_MAX_WRITERGROUPS 8 UA_NodeId WriterGroupIds[DOTEST_MULTIPLE_GROUPS_MAX_WRITERGROUPS]; #define DOTEST_MULTIPLE_GROUPS_MAX_PDS 8 UA_NodeId PublishedDataSetIds[DOTEST_MULTIPLE_GROUPS_MAX_PDS]; #define DOTEST_MULTIPLE_GROUPS_MAX_READERGROUPS 8 UA_NodeId ReaderGroupIds[DOTEST_MULTIPLE_GROUPS_MAX_READERGROUPS]; /* Attention: Publisher and corresponding Subscriber NodeId and DataValue must have the same index e.g. publisherVarIds[0] value is set and subscriberVarIds[0] value is checked at ValidatePublishSubscribe() function see table "Var Index" entry above */ #define DOTEST_MULTIPLE_GROUPS_MAX_VARS 8 UA_NodeId publisherVarIds[DOTEST_MULTIPLE_GROUPS_MAX_VARS]; UA_NodeId subscriberVarIds[DOTEST_MULTIPLE_GROUPS_MAX_VARS]; UA_DataValue *fastPathPublisherDataValues[DOTEST_MULTIPLE_GROUPS_MAX_VARS]; UA_DataValue *fastPathSubscriberDataValues[DOTEST_MULTIPLE_GROUPS_MAX_VARS]; for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_GROUPS_MAX_VARS; i++) { fastPathPublisherDataValues[i] = 0; fastPathSubscriberDataValues[i] = 0; } const UA_UInt32 DSW_Id = 1; /* setup all Publishers */ /* setup Connection 1: */ UA_NodeId ConnId_1; UA_NodeId_init(&ConnId_1); UA_PublisherIdType Conn1_PublisherIdType = UA_PUBLISHERIDTYPE_BYTE; UA_PublisherId Conn1_PublisherId; Conn1_PublisherId.byte = 1; AddConnection("Conn1", Conn1_PublisherIdType, Conn1_PublisherId, &ConnId_1); ConnectionIds[0] = ConnId_1; /* WriterGroup 1 */ UA_NodeId WGId_Conn1_WG1; UA_NodeId_init(&WGId_Conn1_WG1); const UA_UInt32 Conn1_WG1_Id = 1; AddWriterGroup(&ConnId_1, "Conn1_WG1", Conn1_WG1_Id, &WGId_Conn1_WG1); WriterGroupIds[0] = WGId_Conn1_WG1; UA_NodeId DsWId_Conn1_WG1_DS1; UA_NodeId_init(&DsWId_Conn1_WG1_DS1); UA_NodeId PDSId_Conn1_WG1_PDS1; UA_NodeId_init(&PDSId_Conn1_WG1_PDS1); AddPublishedDataSet(&WGId_Conn1_WG1, "Conn1_WG1_PDS1", "Conn1_WG1_DS1", DSW_Id, &PDSId_Conn1_WG1_PDS1, &publisherVarIds[0], &fastPathPublisherDataValues[0], &DsWId_Conn1_WG1_DS1); PublishedDataSetIds[0] = PDSId_Conn1_WG1_PDS1; /* WriterGroup 2 */ UA_NodeId WGId_Conn1_WG2; UA_NodeId_init(&WGId_Conn1_WG2); const UA_UInt32 Conn1_WG2_Id = 2; AddWriterGroup(&ConnId_1, "Conn1_WG2", Conn1_WG2_Id, &WGId_Conn1_WG2); WriterGroupIds[1] = WGId_Conn1_WG2; UA_NodeId DsWId_Conn1_WG2_DS1; UA_NodeId_init(&DsWId_Conn1_WG2_DS1); UA_NodeId PDSId_Conn1_WG2_PDS1; UA_NodeId_init(&PDSId_Conn1_WG2_PDS1); AddPublishedDataSet(&WGId_Conn1_WG2, "Conn1_WG2_PDS1", "Conn1_WG2_DS1", DSW_Id, &PDSId_Conn1_WG2_PDS1, &publisherVarIds[1], &fastPathPublisherDataValues[1], &DsWId_Conn1_WG2_DS1); PublishedDataSetIds[1] = PDSId_Conn1_WG2_PDS1; /* WriterGroup 3 */ UA_NodeId WGId_Conn1_WG3; UA_NodeId_init(&WGId_Conn1_WG3); const UA_UInt32 Conn1_WG3_Id = 3; AddWriterGroup(&ConnId_1, "Conn1_WG3", Conn1_WG3_Id, &WGId_Conn1_WG3); WriterGroupIds[2] = WGId_Conn1_WG3; UA_NodeId DsWId_Conn1_WG3_DS1; UA_NodeId_init(&DsWId_Conn1_WG3_DS1); UA_NodeId PDSId_Conn1_WG3_PDS1; UA_NodeId_init(&PDSId_Conn1_WG3_PDS1); AddPublishedDataSet(&WGId_Conn1_WG3, "Conn1_WG3_PDS1", "Conn1_WG3_DS1", DSW_Id, &PDSId_Conn1_WG3_PDS1, &publisherVarIds[2], &fastPathPublisherDataValues[2], &DsWId_Conn1_WG3_DS1); PublishedDataSetIds[2] = PDSId_Conn1_WG3_PDS1; /* WriterGroup 4 */ UA_NodeId WGId_Conn1_WG4; UA_NodeId_init(&WGId_Conn1_WG4); const UA_UInt32 Conn1_WG4_Id = 4; AddWriterGroup(&ConnId_1, "Conn1_WG4", Conn1_WG4_Id, &WGId_Conn1_WG4); WriterGroupIds[3] = WGId_Conn1_WG4; UA_NodeId DsWId_Conn1_WG4_DS1; UA_NodeId_init(&DsWId_Conn1_WG4_DS1); UA_NodeId PDSId_Conn1_WG4_PDS1; UA_NodeId_init(&PDSId_Conn1_WG4_PDS1); AddPublishedDataSet(&WGId_Conn1_WG4, "Conn1_WG4_PDS1", "Conn1_WG4_DS1", DSW_Id, &PDSId_Conn1_WG4_PDS1, &publisherVarIds[3], &fastPathPublisherDataValues[3], &DsWId_Conn1_WG4_DS1); PublishedDataSetIds[3] = PDSId_Conn1_WG4_PDS1; /* setup Connection 2: */ UA_NodeId ConnId_2; UA_NodeId_init(&ConnId_2); UA_PublisherIdType Conn2_PublisherIdType = UA_PUBLISHERIDTYPE_BYTE; UA_PublisherId Conn2_PublisherId; Conn2_PublisherId.byte = 2; AddConnection("Conn2", Conn2_PublisherIdType, Conn2_PublisherId, &ConnId_2); ConnectionIds[1] = ConnId_2; /* WriterGroup 1 */ UA_NodeId WGId_Conn2_WG1; UA_NodeId_init(&WGId_Conn2_WG1); const UA_UInt32 Conn2_WG1_Id = 1; AddWriterGroup(&ConnId_2, "Conn2_WG1", Conn2_WG1_Id, &WGId_Conn2_WG1); WriterGroupIds[4] = WGId_Conn2_WG1; UA_NodeId DsWId_Conn2_WG1_DS1; UA_NodeId_init(&DsWId_Conn2_WG1_DS1); UA_NodeId PDSId_Conn2_WG1_PDS1; UA_NodeId_init(&PDSId_Conn2_WG1_PDS1); AddPublishedDataSet(&WGId_Conn2_WG1, "Conn2_WG1_PDS1", "Conn2_WG1_DS1", DSW_Id, &PDSId_Conn2_WG1_PDS1, &publisherVarIds[4], &fastPathPublisherDataValues[4], &DsWId_Conn2_WG1_DS1); PublishedDataSetIds[4] = PDSId_Conn2_WG1_PDS1; /* WriterGroup 2 */ UA_NodeId WGId_Conn2_WG2; UA_NodeId_init(&WGId_Conn2_WG2); const UA_UInt32 Conn2_WG2_Id = 2; AddWriterGroup(&ConnId_2, "Conn2_WG2", Conn2_WG2_Id, &WGId_Conn2_WG2); WriterGroupIds[5] = WGId_Conn2_WG2; UA_NodeId DsWId_Conn2_WG2_DS1; UA_NodeId_init(&DsWId_Conn2_WG2_DS1); UA_NodeId PDSId_Conn2_WG2_PDS1; UA_NodeId_init(&PDSId_Conn2_WG2_PDS1); AddPublishedDataSet(&WGId_Conn2_WG2, "Conn2_WG2_PDS1", "Conn2_WG2_DS1", DSW_Id, &PDSId_Conn2_WG2_PDS1, &publisherVarIds[5], &fastPathPublisherDataValues[5], &DsWId_Conn2_WG2_DS1); PublishedDataSetIds[5] = PDSId_Conn2_WG2_PDS1; /* setup Connection 3: */ UA_NodeId ConnId_3; UA_NodeId_init(&ConnId_3); UA_PublisherIdType Conn3_PublisherIdType = UA_PUBLISHERIDTYPE_UINT16; UA_PublisherId Conn3_PublisherId; Conn3_PublisherId.uint16 = 1; AddConnection("Conn3", Conn3_PublisherIdType, Conn3_PublisherId, &ConnId_3); ConnectionIds[2] = ConnId_3; /* WriterGroup 1 */ UA_NodeId WGId_Conn3_WG1; UA_NodeId_init(&WGId_Conn3_WG1); const UA_UInt32 Conn3_WG1_Id = 1; AddWriterGroup(&ConnId_3, "Conn3_WG1", Conn3_WG1_Id, &WGId_Conn3_WG1); WriterGroupIds[6] = WGId_Conn3_WG1; UA_NodeId DsWId_Conn3_WG1_DS1; UA_NodeId_init(&DsWId_Conn3_WG1_DS1); UA_NodeId PDSId_Conn3_WG1_PDS1; UA_NodeId_init(&PDSId_Conn3_WG1_PDS1); AddPublishedDataSet(&WGId_Conn3_WG1, "Conn3_WG1_PDS1", "Conn3_WG1_DS1", DSW_Id, &PDSId_Conn3_WG1_PDS1, &publisherVarIds[6], &fastPathPublisherDataValues[6], &DsWId_Conn3_WG1_DS1); PublishedDataSetIds[6] = PDSId_Conn3_WG1_PDS1; /* WriterGroup 2 */ UA_NodeId WGId_Conn3_WG2; UA_NodeId_init(&WGId_Conn3_WG2); const UA_UInt32 Conn3_WG2_Id = 2; AddWriterGroup(&ConnId_3, "Conn3_WG2", Conn3_WG2_Id, &WGId_Conn3_WG2); WriterGroupIds[7] = WGId_Conn3_WG2; UA_NodeId DsWId_Conn3_WG2_DS1; UA_NodeId_init(&DsWId_Conn3_WG2_DS1); UA_NodeId PDSId_Conn3_WG2_PDS1; UA_NodeId_init(&PDSId_Conn3_WG2_PDS1); AddPublishedDataSet(&WGId_Conn3_WG2, "Conn3_WG2_PDS1", "Conn3_WG2_DS1", DSW_Id, &PDSId_Conn3_WG2_PDS1, &publisherVarIds[7], &fastPathPublisherDataValues[7], &DsWId_Conn3_WG2_DS1); PublishedDataSetIds[7] = PDSId_Conn3_WG2_PDS1; /* setup all Subscribers */ /* setup Connection 1: */ /* ReaderGroup 1 */ UA_NodeId RGId_Conn1_RG1; UA_NodeId_init(&RGId_Conn1_RG1); AddReaderGroup(&ConnId_1, "Conn1_RG1", &RGId_Conn1_RG1); UA_NodeId DSRId_Conn1_RG1_DSR1; UA_NodeId_init(&DSRId_Conn1_RG1_DSR1); AddDataSetReader(&RGId_Conn1_RG1, "Conn1_RG1_DSR1", Conn1_PublisherIdType, Conn1_PublisherId, Conn1_WG4_Id, DSW_Id, &subscriberVarIds[3], &fastPathSubscriberDataValues[3], &DSRId_Conn1_RG1_DSR1); ReaderGroupIds[0] = RGId_Conn1_RG1; /* ReaderGroup 2 */ UA_NodeId RGId_Conn1_RG2; UA_NodeId_init(&RGId_Conn1_RG2); AddReaderGroup(&ConnId_1, "Conn1_RG2", &RGId_Conn1_RG2); UA_NodeId DSRId_Conn1_RG2_DSR1; UA_NodeId_init(&DSRId_Conn1_RG2_DSR1); AddDataSetReader(&RGId_Conn1_RG2, "Conn1_RG2_DSR1", Conn3_PublisherIdType, Conn3_PublisherId, Conn3_WG1_Id, DSW_Id, &subscriberVarIds[6], &fastPathSubscriberDataValues[6], &DSRId_Conn1_RG2_DSR1); ReaderGroupIds[1] = RGId_Conn1_RG2; /* ReaderGroup 3 */ UA_NodeId RGId_Conn1_RG3; UA_NodeId_init(&RGId_Conn1_RG3); AddReaderGroup(&ConnId_1, "Conn1_RG3", &RGId_Conn1_RG3); UA_NodeId DSRId_Conn1_RG3_DSR1; UA_NodeId_init(&DSRId_Conn1_RG3_DSR1); AddDataSetReader(&RGId_Conn1_RG3, "Conn1_RG3_DSR1", Conn2_PublisherIdType, Conn2_PublisherId, Conn2_WG1_Id, DSW_Id, &subscriberVarIds[4], &fastPathSubscriberDataValues[4], &DSRId_Conn1_RG3_DSR1); ReaderGroupIds[2] = RGId_Conn1_RG3; /* ReaderGroup 4 */ UA_NodeId RGId_Conn1_RG4; UA_NodeId_init(&RGId_Conn1_RG4); AddReaderGroup(&ConnId_1, "Conn1_RG4", &RGId_Conn1_RG4); UA_NodeId DSRId_Conn1_RG4_DSR1; UA_NodeId_init(&DSRId_Conn1_RG4_DSR1); AddDataSetReader(&RGId_Conn1_RG4, "Conn1_RG4_DSR1", Conn3_PublisherIdType, Conn3_PublisherId, Conn3_WG2_Id, DSW_Id, &subscriberVarIds[7], &fastPathSubscriberDataValues[7], &DSRId_Conn1_RG4_DSR1); ReaderGroupIds[3] = RGId_Conn1_RG4; /* setup Connection 2: */ /* ReaderGroup 1 */ UA_NodeId RGId_Conn2_RG1; UA_NodeId_init(&RGId_Conn2_RG1); AddReaderGroup(&ConnId_2, "Conn2_RG1", &RGId_Conn2_RG1); UA_NodeId DSRId_Conn2_RG1_DSR1; UA_NodeId_init(&DSRId_Conn2_RG1_DSR1); AddDataSetReader(&RGId_Conn2_RG1, "Conn2_RG1_DSR1", Conn1_PublisherIdType, Conn1_PublisherId, Conn1_WG2_Id, DSW_Id, &subscriberVarIds[1], &fastPathSubscriberDataValues[1], &DSRId_Conn2_RG1_DSR1); ReaderGroupIds[4] = RGId_Conn2_RG1; /* ReaderGroup 2 */ UA_NodeId RGId_Conn2_RG2; UA_NodeId_init(&RGId_Conn2_RG2); AddReaderGroup(&ConnId_2, "Conn2_RG2", &RGId_Conn2_RG2); UA_NodeId DSRId_Conn2_RG2_DSR1; UA_NodeId_init(&DSRId_Conn2_RG2_DSR1); AddDataSetReader(&RGId_Conn2_RG2, "Conn2_RG2_DSR1", Conn1_PublisherIdType, Conn1_PublisherId, Conn1_WG1_Id, DSW_Id, &subscriberVarIds[0], &fastPathSubscriberDataValues[0], &DSRId_Conn2_RG2_DSR1); ReaderGroupIds[5] = RGId_Conn2_RG2; /* setup Connection 3: */ /* ReaderGroup 1 */ UA_NodeId RGId_Conn3_RG1; UA_NodeId_init(&RGId_Conn3_RG1); AddReaderGroup(&ConnId_3, "Conn3_RG1", &RGId_Conn3_RG1); UA_NodeId DSRId_Conn3_RG1_DSR1; UA_NodeId_init(&DSRId_Conn3_RG1_DSR1); AddDataSetReader(&RGId_Conn3_RG1, "Conn3_RG1_DSR1", Conn1_PublisherIdType, Conn1_PublisherId, Conn1_WG3_Id, DSW_Id, &subscriberVarIds[2], &fastPathSubscriberDataValues[2], &DSRId_Conn3_RG1_DSR1); ReaderGroupIds[6] = RGId_Conn3_RG1; /* ReaderGroup 2 */ UA_NodeId RGId_Conn3_RG2; UA_NodeId_init(&RGId_Conn3_RG2); AddReaderGroup(&ConnId_3, "Conn3_RG2", &RGId_Conn3_RG2); UA_NodeId DSRId_Conn3_RG2_DSR1; UA_NodeId_init(&DSRId_Conn3_RG2_DSR1); AddDataSetReader(&RGId_Conn3_RG2, "Conn3_RG2_DSR1", Conn2_PublisherIdType, Conn2_PublisherId, Conn2_WG2_Id, DSW_Id, &subscriberVarIds[5], &fastPathSubscriberDataValues[5], &DSRId_Conn3_RG2_DSR1); ReaderGroupIds[7] = RGId_Conn3_RG2; /* freeze all Groups */ for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_GROUPS_MAX_WRITERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_freezeWriterGroupConfiguration(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_GROUPS_MAX_READERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_freezeReaderGroupConfiguration(server, ReaderGroupIds[i])); } /* set groups operational */ for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_GROUPS_MAX_WRITERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setWriterGroupOperational(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_GROUPS_MAX_READERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setReaderGroupOperational(server, ReaderGroupIds[i])); } /* check that publish/subscribe works -> set some test values */ ValidatePublishSubscribe(DOTEST_MULTIPLE_GROUPS_MAX_VARS, publisherVarIds, subscriberVarIds, fastPathPublisherDataValues, fastPathSubscriberDataValues, 10, (UA_UInt32) 100, 3); ValidatePublishSubscribe(DOTEST_MULTIPLE_GROUPS_MAX_VARS, publisherVarIds, subscriberVarIds, fastPathPublisherDataValues, fastPathSubscriberDataValues, 50, (UA_UInt32) 100, 3); ValidatePublishSubscribe(DOTEST_MULTIPLE_GROUPS_MAX_VARS, publisherVarIds, subscriberVarIds, fastPathPublisherDataValues, fastPathSubscriberDataValues, 100, (UA_UInt32) 100, 3); /* set groups to disabled */ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "disable groups"); for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_GROUPS_MAX_WRITERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setWriterGroupDisabled(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_GROUPS_MAX_READERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setReaderGroupDisabled(server, ReaderGroupIds[i])); } /* unfreeze groups */ for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_GROUPS_MAX_WRITERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_unfreezeWriterGroupConfiguration(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_GROUPS_MAX_READERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_unfreezeReaderGroupConfiguration(server, ReaderGroupIds[i])); } UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "remove PublishedDataSets"); for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_GROUPS_MAX_PDS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_removePublishedDataSet(server, PublishedDataSetIds[i])); } UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "remove Connections"); for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_GROUPS_MAX_CONNECTIONS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_removePubSubConnection(server, ConnectionIds[i])); } if (UseFastPath) { for (size_t i = 0; i < DOTEST_MULTIPLE_GROUPS_MAX_VARS; i++) { UA_DataValue_clear(fastPathPublisherDataValues[i]); UA_DataValue_delete(fastPathPublisherDataValues[i]); UA_DataValue_clear(fastPathSubscriberDataValues[i]); UA_DataValue_delete(fastPathSubscriberDataValues[i]); } } UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "DoTest_multiple_Groups() end"); } /***************************************************************************************************/ START_TEST(Test_multiple_groups) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "START: Test_multiple_groups"); /* note: fast-path does not multiple groups/datasets/string publisher Ids therefore fast-path is not enabled at this test */ UseFastPath = UA_FALSE; UseRawEncoding = UA_FALSE; DoTest_multiple_Groups(); UseRawEncoding = UA_TRUE; DoTest_multiple_Groups(); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "END: Test_multiple_groups"); } END_TEST /***************************************************************************************************/ static void DoTest_multiple_DataSets(void) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "DoTest_multiple_DataSets() begin"); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "fast-path = %s", (UseFastPath) ? "enabled" : "disabled"); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "raw encoding = %s", (UseRawEncoding) ? "enabled" : "disabled"); /* Writers -> Readers -> Var Index ---------------------------------------------------------------------------------- Conn1 BYTE Id WG 1, DSW 1 -> Conn2, RG 1, DSR 1 0 WG 1, DSW 2 -> Conn2, RG 1, DSR 3 1 WG 1, DSW 3 -> Conn2, RG 1, DSR 2 2 WG 1, DSW 4 -> Conn1, RG 1, DSR 1 3 Conn2 UINT16 Id WG 1, DSW 1 -> Conn1, RG 1, DSR 2 4 WG 1, DSW 2 -> Conn2, RG 1, DSR 4 5 */ #define DOTEST_MULTIPLE_DATASETS_MAX_CONNECTIONS 2 UA_NodeId ConnectionIds[DOTEST_MULTIPLE_DATASETS_MAX_CONNECTIONS]; #define DOTEST_MULTIPLE_DATASETS_MAX_WRITERGROUPS 2 UA_NodeId WriterGroupIds[DOTEST_MULTIPLE_DATASETS_MAX_WRITERGROUPS]; #define DOTEST_MULTIPLE_DATASETS_MAX_PDS 6 UA_NodeId PublishedDataSetIds[DOTEST_MULTIPLE_DATASETS_MAX_PDS]; #define DOTEST_MULTIPLE_DATASETS_MAX_READERGROUPS 2 UA_NodeId ReaderGroupIds[DOTEST_MULTIPLE_DATASETS_MAX_READERGROUPS]; /* Attention: Publisher and corresponding Subscriber NodeId and DataValue must have the same index e.g. publisherVarIds[0] value is set and subscriberVarIds[0] value is checked at ValidatePublishSubscribe() function see table "Var Index" entry above */ #define DOTEST_MULTIPLE_DATASETS_MAX_VARS 6 UA_NodeId publisherVarIds[DOTEST_MULTIPLE_DATASETS_MAX_VARS]; UA_NodeId subscriberVarIds[DOTEST_MULTIPLE_DATASETS_MAX_VARS]; UA_DataValue *fastPathPublisherDataValues[DOTEST_MULTIPLE_DATASETS_MAX_VARS]; UA_DataValue *fastPathSubscriberDataValues[DOTEST_MULTIPLE_DATASETS_MAX_VARS]; for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_DATASETS_MAX_VARS; i++) { fastPathPublisherDataValues[i] = 0; fastPathSubscriberDataValues[i] = 0; } const UA_UInt32 WG_Id = 1; /* setup all Publishers */ /* setup Connection 1: */ UA_NodeId ConnId_1; UA_NodeId_init(&ConnId_1); UA_PublisherIdType Conn1_PublisherIdType = UA_PUBLISHERIDTYPE_BYTE; UA_PublisherId Conn1_PublisherId; Conn1_PublisherId.byte = 1; AddConnection("Conn1", Conn1_PublisherIdType, Conn1_PublisherId, &ConnId_1); ConnectionIds[0] = ConnId_1; /* WriterGroup 1 */ UA_NodeId WGId_Conn1_WG1; UA_NodeId_init(&WGId_Conn1_WG1); AddWriterGroup(&ConnId_1, "Conn1_WG1", WG_Id, &WGId_Conn1_WG1); WriterGroupIds[0] = WGId_Conn1_WG1; /* DataSetWriter 1 */ UA_NodeId DsWId_Conn1_WG1_DS1; UA_NodeId_init(&DsWId_Conn1_WG1_DS1); UA_NodeId PDSId_Conn1_WG1_PDS1; UA_NodeId_init(&PDSId_Conn1_WG1_PDS1); const UA_UInt32 Conn1_WG1_DSW1_Id = 1; AddPublishedDataSet(&WGId_Conn1_WG1, "Conn1_WG1_PDS1", "Conn1_WG1_DS1", Conn1_WG1_DSW1_Id, &PDSId_Conn1_WG1_PDS1, &publisherVarIds[0], &fastPathPublisherDataValues[0], &DsWId_Conn1_WG1_DS1); PublishedDataSetIds[0] = PDSId_Conn1_WG1_PDS1; /* DataSetWriter 2 */ UA_NodeId DsWId_Conn1_WG1_DS2; UA_NodeId_init(&DsWId_Conn1_WG1_DS2); UA_NodeId PDSId_Conn1_WG1_PDS2; UA_NodeId_init(&PDSId_Conn1_WG1_PDS2); const UA_UInt32 Conn1_WG1_DSW2_Id = 2; AddPublishedDataSet(&WGId_Conn1_WG1, "Conn1_WG2_PDS1", "Conn1_WG2_DS1", Conn1_WG1_DSW2_Id, &PDSId_Conn1_WG1_PDS2, &publisherVarIds[1], &fastPathPublisherDataValues[1], &DsWId_Conn1_WG1_DS2); PublishedDataSetIds[1] = PDSId_Conn1_WG1_PDS2; /* DataSetWriter 3 */ UA_NodeId DsWId_Conn1_WG1_DS3; UA_NodeId_init(&DsWId_Conn1_WG1_DS3); UA_NodeId PDSId_Conn1_WG1_PDS3; UA_NodeId_init(&PDSId_Conn1_WG1_PDS3); const UA_UInt32 Conn1_WG1_DSW3_Id = 3; AddPublishedDataSet(&WGId_Conn1_WG1, "Conn1_WG2_PDS3", "Conn1_WG2_DS3", Conn1_WG1_DSW3_Id, &PDSId_Conn1_WG1_PDS3, &publisherVarIds[2], &fastPathPublisherDataValues[2], &DsWId_Conn1_WG1_DS3); PublishedDataSetIds[2] = PDSId_Conn1_WG1_PDS3; /* DataSetWriter 4 */ UA_NodeId DsWId_Conn1_WG1_DS4; UA_NodeId_init(&DsWId_Conn1_WG1_DS4); UA_NodeId PDSId_Conn1_WG1_PDS4; UA_NodeId_init(&PDSId_Conn1_WG1_PDS4); const UA_UInt32 Conn1_WG1_DSW4_Id = 4; AddPublishedDataSet(&WGId_Conn1_WG1, "Conn1_WG2_PDS4", "Conn1_WG2_DS4", Conn1_WG1_DSW4_Id, &PDSId_Conn1_WG1_PDS4, &publisherVarIds[3], &fastPathPublisherDataValues[3], &DsWId_Conn1_WG1_DS4); PublishedDataSetIds[3] = PDSId_Conn1_WG1_PDS4; /* setup Connection 2: */ UA_NodeId ConnId_2; UA_NodeId_init(&ConnId_2); UA_PublisherIdType Conn2_PublisherIdType = UA_PUBLISHERIDTYPE_BYTE; UA_PublisherId Conn2_PublisherId; Conn2_PublisherId.byte = 2; AddConnection("Conn2", Conn2_PublisherIdType, Conn2_PublisherId, &ConnId_2); ConnectionIds[1] = ConnId_2; /* WriterGroup 1 */ UA_NodeId WGId_Conn2_WG1; UA_NodeId_init(&WGId_Conn2_WG1); AddWriterGroup(&ConnId_2, "Conn2_WG1", WG_Id, &WGId_Conn2_WG1); WriterGroupIds[1] = WGId_Conn2_WG1; /* DataSetWriter 1 */ UA_NodeId DsWId_Conn2_WG1_DS1; UA_NodeId_init(&DsWId_Conn2_WG1_DS1); UA_NodeId PDSId_Conn2_WG1_PDS1; UA_NodeId_init(&PDSId_Conn2_WG1_PDS1); const UA_UInt32 Conn2_WG1_DSW1_Id = 1; AddPublishedDataSet(&WGId_Conn2_WG1, "Conn2_WG1_PDS1", "Conn2_WG1_DS1", Conn2_WG1_DSW1_Id, &PDSId_Conn2_WG1_PDS1, &publisherVarIds[4], &fastPathPublisherDataValues[4], &DsWId_Conn2_WG1_DS1); PublishedDataSetIds[4] = PDSId_Conn2_WG1_PDS1; /* DataSetWriter 2 */ UA_NodeId DsWId_Conn2_WG1_DS2; UA_NodeId_init(&DsWId_Conn2_WG1_DS2); UA_NodeId PDSId_Conn2_WG1_PDS2; UA_NodeId_init(&PDSId_Conn2_WG1_PDS2); const UA_UInt32 Conn2_WG1_DSW2_Id = 2; AddPublishedDataSet(&WGId_Conn2_WG1, "Conn2_WG1_PDS2", "Conn2_WG1_DS2", Conn2_WG1_DSW2_Id, &PDSId_Conn2_WG1_PDS2, &publisherVarIds[5], &fastPathPublisherDataValues[5], &DsWId_Conn2_WG1_DS2); PublishedDataSetIds[5] = PDSId_Conn2_WG1_PDS2; /* setup all Subscribers */ /* setup Connection 1: */ /* ReaderGroup 1 */ UA_NodeId RGId_Conn1_RG1; UA_NodeId_init(&RGId_Conn1_RG1); AddReaderGroup(&ConnId_1, "Conn1_RG1", &RGId_Conn1_RG1); ReaderGroupIds[0] = RGId_Conn1_RG1; /* DataSetReader 1 */ UA_NodeId DSRId_Conn1_RG1_DSR1; UA_NodeId_init(&DSRId_Conn1_RG1_DSR1); AddDataSetReader(&RGId_Conn1_RG1, "Conn1_RG1_DSR1", Conn1_PublisherIdType, Conn1_PublisherId, WG_Id, Conn1_WG1_DSW4_Id, &subscriberVarIds[3], &fastPathSubscriberDataValues[3], &DSRId_Conn1_RG1_DSR1); /* DataSetReader 2 */ UA_NodeId DSRId_Conn1_RG1_DSR2; UA_NodeId_init(&DSRId_Conn1_RG1_DSR2); AddDataSetReader(&RGId_Conn1_RG1, "Conn1_RG1_DSR2", Conn2_PublisherIdType, Conn2_PublisherId, WG_Id, Conn1_WG1_DSW1_Id, &subscriberVarIds[4], &fastPathSubscriberDataValues[4], &DSRId_Conn1_RG1_DSR2); /* setup Connection 2: */ /* ReaderGroup 1 */ UA_NodeId RGId_Conn2_RG1; UA_NodeId_init(&RGId_Conn2_RG1); AddReaderGroup(&ConnId_2, "Conn2_RG1", &RGId_Conn2_RG1); ReaderGroupIds[1] = RGId_Conn2_RG1; /* DataSetReader 1 */ UA_NodeId DSRId_Conn2_RG1_DSR1; UA_NodeId_init(&DSRId_Conn2_RG1_DSR1); AddDataSetReader(&RGId_Conn2_RG1, "Conn2_RG1_DSR1", Conn1_PublisherIdType, Conn1_PublisherId, WG_Id, Conn1_WG1_DSW1_Id, &subscriberVarIds[0], &fastPathSubscriberDataValues[0], &DSRId_Conn2_RG1_DSR1); /* DataSetReader 2 */ UA_NodeId DSRId_Conn2_RG1_DSR2; UA_NodeId_init(&DSRId_Conn2_RG1_DSR2); AddDataSetReader(&RGId_Conn2_RG1, "Conn2_RG1_DSR2", Conn1_PublisherIdType, Conn1_PublisherId, WG_Id, Conn1_WG1_DSW3_Id, &subscriberVarIds[2], &fastPathSubscriberDataValues[2], &DSRId_Conn2_RG1_DSR2); /* DataSetReader 3 */ UA_NodeId DSRId_Conn2_RG1_DSR3; UA_NodeId_init(&DSRId_Conn2_RG1_DSR3); AddDataSetReader(&RGId_Conn2_RG1, "Conn2_RG1_DSR3", Conn1_PublisherIdType, Conn1_PublisherId, WG_Id, Conn1_WG1_DSW2_Id, &subscriberVarIds[1], &fastPathSubscriberDataValues[1], &DSRId_Conn2_RG1_DSR3); /* DataSetReader 4 */ UA_NodeId DSRId_Conn2_RG1_DSR4; UA_NodeId_init(&DSRId_Conn2_RG1_DSR4); AddDataSetReader(&RGId_Conn2_RG1, "Conn2_RG1_DSR4", Conn2_PublisherIdType, Conn2_PublisherId, WG_Id, Conn1_WG1_DSW2_Id, &subscriberVarIds[5], &fastPathSubscriberDataValues[5], &DSRId_Conn2_RG1_DSR4); /* freeze all Groups */ for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_DATASETS_MAX_WRITERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_freezeWriterGroupConfiguration(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_DATASETS_MAX_READERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_freezeReaderGroupConfiguration(server, ReaderGroupIds[i])); } /* set groups operational */ for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_DATASETS_MAX_WRITERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setWriterGroupOperational(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_DATASETS_MAX_READERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setReaderGroupOperational(server, ReaderGroupIds[i])); } /* check that publish/subscribe works -> set some test values */ ValidatePublishSubscribe(DOTEST_MULTIPLE_DATASETS_MAX_VARS, publisherVarIds, subscriberVarIds, fastPathPublisherDataValues, fastPathSubscriberDataValues, 10, (UA_UInt32) 100, 3); ValidatePublishSubscribe(DOTEST_MULTIPLE_DATASETS_MAX_VARS, publisherVarIds, subscriberVarIds, fastPathPublisherDataValues, fastPathSubscriberDataValues, 50, (UA_UInt32) 100, 3); ValidatePublishSubscribe(DOTEST_MULTIPLE_DATASETS_MAX_VARS, publisherVarIds, subscriberVarIds, fastPathPublisherDataValues, fastPathSubscriberDataValues, 100, (UA_UInt32) 100, 3); /* set groups to disabled */ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "disable groups"); for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_DATASETS_MAX_WRITERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setWriterGroupDisabled(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_DATASETS_MAX_READERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_setReaderGroupDisabled(server, ReaderGroupIds[i])); } /* unfreeze groups */ for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_DATASETS_MAX_WRITERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_unfreezeWriterGroupConfiguration(server, WriterGroupIds[i])); } for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_DATASETS_MAX_READERGROUPS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_unfreezeReaderGroupConfiguration(server, ReaderGroupIds[i])); } UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "remove PublishedDataSets"); for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_DATASETS_MAX_PDS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_removePublishedDataSet(server, PublishedDataSetIds[i])); } UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "remove Connections"); for (UA_UInt32 i = 0; i < DOTEST_MULTIPLE_DATASETS_MAX_CONNECTIONS; i++) { ck_assert_int_eq(UA_STATUSCODE_GOOD, UA_Server_removePubSubConnection(server, ConnectionIds[i])); } if (UseFastPath) { for (size_t i = 0; i < DOTEST_MULTIPLE_DATASETS_MAX_VARS; i++) { UA_DataValue_clear(fastPathPublisherDataValues[i]); UA_DataValue_delete(fastPathPublisherDataValues[i]); UA_DataValue_clear(fastPathSubscriberDataValues[i]); UA_DataValue_delete(fastPathSubscriberDataValues[i]); } } UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "DoTest_multiple_DataSets() end"); } /***************************************************************************************************/ START_TEST(Test_multiple_datasets) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "START: Test_multiple_datasets"); /* note: fast-path does not multiple groups/datasets/string publisher Ids therefore fast-path is not enabled at this test */ UseFastPath = UA_FALSE; UseRawEncoding = UA_FALSE; DoTest_multiple_DataSets(); UseRawEncoding = UA_TRUE; DoTest_multiple_DataSets(); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "END: Test_multiple_datasets"); } END_TEST /***************************************************************************************************/ int main(void) { TCase *tc_basic = tcase_create("PublisherId"); tcase_add_checked_fixture(tc_basic, setup, teardown); /* test case description: - test 1 connection with 1 WriterGroup, 1 DatasetWriter, 1 ReaderGroup and 1 DataSetReader - test all possible publisherId types - test with all combinations of fast-path and raw-encoding */ tcase_add_test(tc_basic, Test_1_connection); /* test case description: - setup a PubSub configuration with multiple Connections - all WriterGroup Ids and DataSetWriter Ids are equal, because we want to test the publisherId check - use the same publishing interval for all groups to ensure that the Readers receive multiple messages at the same time - set different publishing values to ensure that PublisherId check works and every DataSetReader receives the correct message - test all different publisherId types - test with all combinations of fast-path and raw-encoding - TODO: fast-path does not support multiple groups and datasets, therefore we only test multiple connections with fast-path here - TODO: fast-path does not support STRING publisherIds */ tcase_add_test(tc_basic, Test_multiple_connections); /* test case description: - setup a PubSub configuration with multiple Connections - all connections have a STRING PublisherId - all WriterGroup Ids and DataSetWriter Ids are equal, because we want to test the publisherId check - use the same publishing interval for all groups to ensure that the Readers receive multiple messages at the same time - set different publishing values to ensure that PublisherId check works and every DataSetReader receives the correct message - test with and without raw-encoding - TODO: fast-path does not support string PublisherIds at the moment */ tcase_add_test(tc_basic, Test_string_publisherId); #ifdef UA_ENABLE_PUBSUB_FILE_CONFIG /* test case description: - test pubsub file config with string PublisherId */ tcase_add_test(tc_basic, Test_string_publisherId_file_config); #endif /* UA_ENABLE_PUBSUB_FILE_CONFIG */ /* test case description: - setup a PubSub configuration with multiple Groups - use the same publishing interval for all groups to ensure that the Readers receive multiple messages at the same time - set different publishing values to ensure that PublisherId check works and every DataSetReader receives the correct message - test with with and without raw-encoding */ tcase_add_test(tc_basic, Test_multiple_groups); /* test case description: - setup a PubSub configuration with multiple DataSets - use the same publishing interval for all groups to ensure that the Readers receive multiple messages at the same time - set different publishing values to ensure that PublisherId check works and every DataSetReader receives the correct message - test with with and without raw-encoding */ tcase_add_test(tc_basic, Test_multiple_datasets); Suite *s = suite_create("PubSub publisherId tests"); suite_add_tcase(s, tc_basic); SRunner *sr = srunner_create(s); srunner_set_fork_status(sr, CK_NOFORK); srunner_run_all(sr,CK_NORMAL); int number_failed = srunner_ntests_failed(sr); srunner_free(sr); return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; }