check_pubsub_informationmodel.c 18 KB

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