check_pubsub_informationmodel.c 17 KB

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