check_pubsub_informationmodel.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  4. *
  5. * Copyright (c) 2017 - 2018 Fraunhofer IOSB (Author: Andreas Ebner)
  6. */
  7. #include <open62541/plugin/pubsub.h>
  8. #include <open62541/plugin/pubsub_udp.h>
  9. #include <open62541/server_config_default.h>
  10. #include <open62541/server_pubsub.h>
  11. #include <open62541/types.h>
  12. #include <open62541/types_generated.h>
  13. #include "ua_server_internal.h"
  14. #include <math.h>
  15. #include <string.h>
  16. #include "check.h"
  17. UA_Server *server = NULL;
  18. UA_ServerConfig *config = NULL;
  19. UA_NodeId connection1, connection2, writerGroup1, writerGroup2, writerGroup3,
  20. publishedDataSet1, publishedDataSet2, dataSetWriter1, dataSetWriter2, dataSetWriter3;
  21. static void setup(void) {
  22. config = UA_ServerConfig_new_default();
  23. config->pubsubTransportLayers = (UA_PubSubTransportLayer *) UA_malloc(sizeof(UA_PubSubTransportLayer));
  24. if(!config->pubsubTransportLayers) {
  25. UA_ServerConfig_delete(config);
  26. }
  27. config->pubsubTransportLayers[0] = UA_PubSubTransportLayerUDPMP();
  28. config->pubsubTransportLayersSize++;
  29. server = UA_Server_new(config);
  30. UA_Server_run_startup(server);
  31. }
  32. static void teardown(void) {
  33. UA_Server_run_shutdown(server);
  34. UA_Server_delete(server);
  35. UA_ServerConfig_delete(config);
  36. }
  37. static void addPublishedDataSet(UA_String pdsName, UA_NodeId *assignedId){
  38. UA_PublishedDataSetConfig pdsConfig;
  39. memset(&pdsConfig, 0, sizeof(UA_PublishedDataSetConfig));
  40. pdsConfig.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS;
  41. pdsConfig.name = pdsName;
  42. UA_Server_addPublishedDataSet(server, &pdsConfig, assignedId);
  43. }
  44. static void addPubSubConnection(UA_String connectionName, UA_String addressUrl, UA_NodeId *assignedId){
  45. UA_PubSubConnectionConfig connectionConfig;
  46. memset(&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig));
  47. connectionConfig.name = connectionName;
  48. UA_NetworkAddressUrlDataType networkAddressUrl = {UA_STRING_NULL, addressUrl};
  49. UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrl,
  50. &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
  51. connectionConfig.transportProfileUri = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp");
  52. UA_Server_addPubSubConnection(server, &connectionConfig, assignedId);
  53. }
  54. static void addWriterGroup(UA_NodeId parentConnection, UA_String name, UA_Duration interval, UA_NodeId *assignedId){
  55. UA_WriterGroupConfig writerGroupConfig;
  56. memset(&writerGroupConfig, 0, sizeof(writerGroupConfig));
  57. writerGroupConfig.name = name;
  58. writerGroupConfig.publishingInterval = interval;
  59. writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_UADP;
  60. UA_Server_addWriterGroup(server, parentConnection, &writerGroupConfig, assignedId);
  61. }
  62. static void addDataSetWriter(UA_NodeId parentWriterGroup, UA_NodeId connectedPDS, UA_String name, UA_NodeId *assignedId){
  63. UA_DataSetWriterConfig dataSetWriterConfig;
  64. memset(&dataSetWriterConfig, 0, sizeof(dataSetWriterConfig));
  65. dataSetWriterConfig.name = name;
  66. UA_Server_addDataSetWriter(server, parentWriterGroup, connectedPDS, &dataSetWriterConfig, assignedId);
  67. }
  68. static UA_Boolean doubleEqual(UA_Double a, UA_Double b, UA_Double maxAbsDelta){
  69. return fabs(a-b) < maxAbsDelta;
  70. }
  71. static UA_NodeId
  72. findSingleChildNode(UA_Server *server_, UA_QualifiedName targetName, UA_NodeId referenceTypeId, UA_NodeId startingNode){
  73. UA_NodeId resultNodeId;
  74. UA_RelativePathElement rpe;
  75. UA_RelativePathElement_init(&rpe);
  76. rpe.referenceTypeId = referenceTypeId;
  77. rpe.isInverse = false;
  78. rpe.includeSubtypes = false;
  79. rpe.targetName = targetName;
  80. UA_BrowsePath bp;
  81. UA_BrowsePath_init(&bp);
  82. bp.startingNode = startingNode;
  83. bp.relativePath.elementsSize = 1;
  84. bp.relativePath.elements = &rpe;
  85. UA_BrowsePathResult bpr =
  86. UA_Server_translateBrowsePathToNodeIds(server_, &bp);
  87. if(bpr.statusCode != UA_STATUSCODE_GOOD ||
  88. bpr.targetsSize < 1)
  89. return UA_NODEID_NULL;
  90. UA_NodeId_copy(&bpr.targets[0].targetId.nodeId, &resultNodeId);
  91. UA_BrowsePathResult_deleteMembers(&bpr);
  92. return resultNodeId;
  93. }
  94. static void setupBasicPubSubConfiguration(void){
  95. addPubSubConnection(UA_STRING("Connection 1"), UA_STRING("opc.udp://224.0.0.22:4840/"), &connection1);
  96. addPubSubConnection(UA_STRING("Connection 2"), UA_STRING("opc.udp://224.0.0.22:4840/"), &connection2);
  97. addPublishedDataSet(UA_STRING("PublishedDataSet 1"), &publishedDataSet1);
  98. addPublishedDataSet(UA_STRING("PublishedDataSet 2"), &publishedDataSet2);
  99. addWriterGroup(connection1, UA_STRING("WriterGroup 1"), 10, &writerGroup1);
  100. addWriterGroup(connection1, UA_STRING("WriterGroup 2"), 100, &writerGroup2);
  101. addWriterGroup(connection2, UA_STRING("WriterGroup 3"), 1000, &writerGroup3);
  102. addDataSetWriter(writerGroup1, publishedDataSet1, UA_STRING("DataSetWriter 1"), &dataSetWriter1);
  103. addDataSetWriter(writerGroup1, publishedDataSet2, UA_STRING("DataSetWriter 2"), &dataSetWriter2);
  104. addDataSetWriter(writerGroup2, publishedDataSet2, UA_STRING("DataSetWriter 3"), &dataSetWriter3);
  105. }
  106. START_TEST(AddSignlePubSubConnectionAndCheckInformationModelRepresentation){
  107. UA_String connectionName = UA_STRING("Connection 1");
  108. addPubSubConnection(connectionName, UA_STRING("opc.udp://224.0.0.22:4840/"), &connection1);
  109. UA_QualifiedName browseName;
  110. UA_StatusCode retVal = UA_STATUSCODE_GOOD;
  111. retVal |= UA_Server_readBrowseName(server, connection1, &browseName);
  112. ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD);
  113. ck_assert_int_eq(UA_String_equal(&browseName.name, &connectionName), UA_TRUE);
  114. UA_QualifiedName_deleteMembers(&browseName);
  115. } END_TEST
  116. START_TEST(AddRemoveAddSignlePubSubConnectionAndCheckInformationModelRepresentation){
  117. UA_String connectionName = UA_STRING("Connection 1");
  118. addPubSubConnection(connectionName, UA_STRING("opc.udp://224.0.0.22:4840/"), &connection1);
  119. UA_QualifiedName browseName;
  120. UA_StatusCode retVal;
  121. ck_assert_int_eq(UA_Server_removePubSubConnection(server, connection1), UA_STATUSCODE_GOOD);
  122. retVal = UA_Server_readBrowseName(server, connection1, &browseName);
  123. ck_assert_int_eq(retVal, UA_STATUSCODE_BADNODEIDUNKNOWN);
  124. addPubSubConnection(connectionName, UA_STRING("opc.udp://224.0.0.22:4840/"), &connection1);
  125. retVal = UA_Server_readBrowseName(server, connection1, &browseName);
  126. ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD);
  127. ck_assert_int_eq(UA_String_equal(&browseName.name, &connectionName), UA_TRUE);
  128. UA_QualifiedName_deleteMembers(&browseName);
  129. } END_TEST
  130. START_TEST(AddSinglePublishedDataSetAndCheckInformationModelRepresentation){
  131. UA_String pdsName = UA_STRING("PDS 1");
  132. addPublishedDataSet(pdsName, &publishedDataSet1);
  133. UA_QualifiedName browseName;
  134. ck_assert_int_eq(UA_Server_readBrowseName(server, publishedDataSet1, &browseName), UA_STATUSCODE_GOOD);
  135. ck_assert_int_eq(UA_String_equal(&browseName.name, &pdsName), UA_TRUE);
  136. UA_QualifiedName_deleteMembers(&browseName);
  137. } END_TEST
  138. START_TEST(AddRemoveAddSinglePublishedDataSetAndCheckInformationModelRepresentation){
  139. UA_String pdsName = UA_STRING("PDS 1");
  140. addPublishedDataSet(pdsName, &publishedDataSet1);
  141. UA_QualifiedName browseName;
  142. UA_StatusCode retVal;
  143. ck_assert_int_eq(UA_Server_removePublishedDataSet(server, publishedDataSet1), UA_STATUSCODE_GOOD);
  144. retVal = UA_Server_readBrowseName(server, publishedDataSet1, &browseName);
  145. ck_assert_int_eq(retVal, UA_STATUSCODE_BADNODEIDUNKNOWN);
  146. addPublishedDataSet(pdsName, &publishedDataSet1);
  147. retVal = UA_Server_readBrowseName(server, publishedDataSet1, &browseName);
  148. ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD);
  149. ck_assert_int_eq(UA_String_equal(&browseName.name, &pdsName), UA_TRUE);
  150. UA_QualifiedName_deleteMembers(&browseName);
  151. } END_TEST
  152. START_TEST(AddSingleWriterGroupAndCheckInformationModelRepresentation){
  153. UA_String connectionName = UA_STRING("Connection 1");
  154. addPubSubConnection(connectionName, UA_STRING("opc.udp://224.0.0.22:4840/"), &connection1);
  155. UA_String pdsName = UA_STRING("PDS 1");
  156. addPublishedDataSet(pdsName, &publishedDataSet1);
  157. UA_String wgName = UA_STRING("WriterGroup 1");
  158. addWriterGroup(connection1, wgName, 10, &writerGroup1);
  159. UA_QualifiedName browseName;
  160. ck_assert_int_eq(UA_Server_readBrowseName(server, writerGroup1, &browseName), UA_STATUSCODE_GOOD);
  161. ck_assert_int_eq(UA_String_equal(&browseName.name, &wgName), UA_TRUE);
  162. UA_QualifiedName_deleteMembers(&browseName);
  163. } END_TEST
  164. START_TEST(AddRemoveAddSingleWriterGroupAndCheckInformationModelRepresentation){
  165. UA_String connectionName = UA_STRING("Connection 1");
  166. addPubSubConnection(connectionName, UA_STRING("opc.udp://224.0.0.22:4840/"), &connection1);
  167. UA_String pdsName = UA_STRING("PDS 1");
  168. addPublishedDataSet(pdsName, &publishedDataSet1);
  169. UA_String wgName = UA_STRING("WriterGroup 1");
  170. addWriterGroup(connection1, wgName, 10, &writerGroup1);
  171. UA_QualifiedName browseName;
  172. UA_StatusCode retVal;
  173. ck_assert_int_eq(UA_Server_removeWriterGroup(server, writerGroup1), UA_STATUSCODE_GOOD);
  174. retVal = UA_Server_readBrowseName(server, writerGroup1, &browseName);
  175. ck_assert_int_eq(retVal, UA_STATUSCODE_BADNODEIDUNKNOWN);
  176. addWriterGroup(connection1, wgName, 10, &writerGroup1);
  177. retVal = UA_Server_readBrowseName(server, writerGroup1, &browseName);
  178. ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD);
  179. ck_assert_int_eq(UA_String_equal(&browseName.name, &wgName), UA_TRUE);
  180. UA_QualifiedName_deleteMembers(&browseName);
  181. } END_TEST
  182. START_TEST(AddSingleDataSetWriterAndCheckInformationModelRepresentation){
  183. UA_String connectionName = UA_STRING("Connection 1");
  184. addPubSubConnection(connectionName, UA_STRING("opc.udp://224.0.0.22:4840/"), &connection1);
  185. UA_String pdsName = UA_STRING("PDS 1");
  186. addPublishedDataSet(pdsName, &publishedDataSet1);
  187. UA_String wgName = UA_STRING("WriterGroup 1");
  188. addWriterGroup(connection1, wgName, 10, &writerGroup1);
  189. UA_String dswName = UA_STRING("DataSetWriter 1");
  190. addDataSetWriter(writerGroup1, publishedDataSet1, dswName, &dataSetWriter1);
  191. UA_QualifiedName browseName;
  192. ck_assert_int_eq(UA_Server_readBrowseName(server, dataSetWriter1, &browseName), UA_STATUSCODE_GOOD);
  193. ck_assert_int_eq(UA_String_equal(&browseName.name, &dswName), UA_TRUE);
  194. UA_QualifiedName_deleteMembers(&browseName);
  195. } END_TEST
  196. START_TEST(AddRemoveAddSingleDataSetWriterAndCheckInformationModelRepresentation){
  197. UA_String connectionName = UA_STRING("Connection 1");
  198. addPubSubConnection(connectionName, UA_STRING("opc.udp://224.0.0.22:4840/"), &connection1);
  199. UA_String pdsName = UA_STRING("PDS 1");
  200. addPublishedDataSet(pdsName, &publishedDataSet1);
  201. UA_String wgName = UA_STRING("WriterGroup 1");
  202. addWriterGroup(connection1, wgName, 10, &writerGroup1);
  203. UA_String dswName = UA_STRING("DataSetWriter 1");
  204. addDataSetWriter(writerGroup1, publishedDataSet1, dswName, &dataSetWriter1);
  205. UA_QualifiedName browseName;
  206. UA_StatusCode retVal;
  207. ck_assert_int_eq(UA_Server_removeDataSetWriter(server, dataSetWriter1), UA_STATUSCODE_GOOD);
  208. retVal = UA_Server_readBrowseName(server, dataSetWriter1, &browseName);
  209. ck_assert_int_eq(retVal, UA_STATUSCODE_BADNODEIDUNKNOWN);
  210. addDataSetWriter(writerGroup1, publishedDataSet1, dswName, &dataSetWriter1);
  211. retVal = UA_Server_readBrowseName(server, dataSetWriter1, &browseName);
  212. ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD);
  213. ck_assert_int_eq(UA_String_equal(&browseName.name, &dswName), UA_TRUE);
  214. UA_QualifiedName_deleteMembers(&browseName);
  215. } END_TEST
  216. START_TEST(ReadPublishIntervalAndCompareWithInternalValue){
  217. setupBasicPubSubConfiguration();
  218. UA_NodeId publishIntervalId = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishingInterval"),
  219. UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), writerGroup1);
  220. UA_Variant value;
  221. UA_Variant_init(&value);
  222. ck_assert_int_eq(UA_Server_readValue(server, publishIntervalId, &value), UA_STATUSCODE_GOOD);
  223. ck_assert(UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DURATION]));
  224. ck_assert(doubleEqual((UA_Double) *((UA_Duration *) value.data), 10, 0.05));
  225. UA_Variant_deleteMembers(&value);
  226. } END_TEST
  227. START_TEST(WritePublishIntervalAndCompareWithInternalValue){
  228. setupBasicPubSubConfiguration();
  229. UA_NodeId publishIntervalId = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishingInterval"),
  230. UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), writerGroup1);
  231. UA_Variant value;
  232. UA_Variant_init(&value);
  233. UA_Duration interval = 100;
  234. UA_Variant_setScalar(&value, &interval, &UA_TYPES[UA_TYPES_DURATION]);
  235. ck_assert_int_eq(UA_Server_writeValue(server, publishIntervalId, value), UA_STATUSCODE_GOOD);
  236. ck_assert_int_eq(UA_Server_readValue(server, publishIntervalId, &value), UA_STATUSCODE_GOOD);
  237. ck_assert(UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DURATION]));
  238. ck_assert(doubleEqual((UA_Double) *((UA_Duration *) value.data), 100, 0.05));
  239. UA_Variant_deleteMembers(&value);
  240. } END_TEST
  241. START_TEST(ReadAddressAndCompareWithInternalValue){
  242. setupBasicPubSubConfiguration();
  243. UA_NodeId address = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "Address"),
  244. UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), connection1);
  245. UA_NodeId url = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "Url"),
  246. UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), address);
  247. UA_NodeId networkInterface = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "NetworkInterface"),
  248. UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), address);
  249. UA_PubSubConnectionConfig connectionConfig;
  250. memset(&connectionConfig, 0, sizeof(connectionConfig));
  251. UA_Server_getPubSubConnectionConfig(server, connection1, &connectionConfig);
  252. UA_Variant value;
  253. UA_Variant_init(&value);
  254. ck_assert_int_eq(UA_Server_readValue(server, url, &value), UA_STATUSCODE_GOOD);
  255. UA_NetworkAddressUrlDataType *networkAddressUrlDataType = (UA_NetworkAddressUrlDataType *)connectionConfig.address.data;
  256. ck_assert(UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_STRING]));
  257. ck_assert(UA_String_equal(((UA_String *) value.data), &networkAddressUrlDataType->url));
  258. UA_Variant_deleteMembers(&value);
  259. ck_assert_int_eq(UA_Server_readValue(server, networkInterface, &value), UA_STATUSCODE_GOOD);
  260. ck_assert(UA_String_equal(((UA_String *) value.data), &networkAddressUrlDataType->networkInterface));
  261. UA_PubSubConnectionConfig_deleteMembers(&connectionConfig);
  262. UA_Variant_deleteMembers(&value);
  263. } END_TEST
  264. int main(void) {
  265. TCase *tc_add_pubsub_informationmodel = tcase_create("PubSub add single elements and check information model representation");
  266. tcase_add_checked_fixture(tc_add_pubsub_informationmodel, setup, teardown);
  267. tcase_add_test(tc_add_pubsub_informationmodel, AddSignlePubSubConnectionAndCheckInformationModelRepresentation);
  268. tcase_add_test(tc_add_pubsub_informationmodel, AddRemoveAddSignlePubSubConnectionAndCheckInformationModelRepresentation);
  269. tcase_add_test(tc_add_pubsub_informationmodel, AddSinglePublishedDataSetAndCheckInformationModelRepresentation);
  270. tcase_add_test(tc_add_pubsub_informationmodel, AddRemoveAddSinglePublishedDataSetAndCheckInformationModelRepresentation);
  271. tcase_add_test(tc_add_pubsub_informationmodel, AddSingleWriterGroupAndCheckInformationModelRepresentation);
  272. tcase_add_test(tc_add_pubsub_informationmodel, AddRemoveAddSingleWriterGroupAndCheckInformationModelRepresentation);
  273. tcase_add_test(tc_add_pubsub_informationmodel, AddSingleDataSetWriterAndCheckInformationModelRepresentation);
  274. tcase_add_test(tc_add_pubsub_informationmodel, AddRemoveAddSingleDataSetWriterAndCheckInformationModelRepresentation);
  275. TCase *tc_add_pubsub_writergroupelements = tcase_create("PubSub WriterGroup check properties");
  276. tcase_add_checked_fixture(tc_add_pubsub_writergroupelements, setup, teardown);
  277. tcase_add_test(tc_add_pubsub_writergroupelements, ReadPublishIntervalAndCompareWithInternalValue);
  278. tcase_add_test(tc_add_pubsub_writergroupelements, WritePublishIntervalAndCompareWithInternalValue);
  279. TCase *tc_add_pubsub_pubsubconnectionelements = tcase_create("PubSub Connection check properties");
  280. tcase_add_checked_fixture(tc_add_pubsub_pubsubconnectionelements, setup, teardown);
  281. tcase_add_test(tc_add_pubsub_pubsubconnectionelements, ReadAddressAndCompareWithInternalValue);
  282. Suite *s = suite_create("PubSub WriterGroups/Writer/Fields handling and publishing");
  283. suite_add_tcase(s, tc_add_pubsub_informationmodel);
  284. suite_add_tcase(s, tc_add_pubsub_writergroupelements);
  285. suite_add_tcase(s, tc_add_pubsub_pubsubconnectionelements);
  286. SRunner *sr = srunner_create(s);
  287. srunner_set_fork_status(sr, CK_NOFORK);
  288. srunner_run_all(sr,CK_NORMAL);
  289. int number_failed = srunner_ntests_failed(sr);
  290. srunner_free(sr);
  291. return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
  292. }