check_discovery.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <pthread.h>
  4. #include <ua_util.h>
  5. #include <ua_types_generated.h>
  6. #include <server/ua_server_internal.h>
  7. #include <unistd.h>
  8. #include "ua_client.h"
  9. #include "ua_config_standard.h"
  10. #include "ua_network_tcp.h"
  11. #include "check.h"
  12. // set register timeout to 1 second so we are able to test it.
  13. #define registerTimeout 1
  14. // cleanup is only triggered every 10 seconds, thus wait a bit longer to check
  15. #define checkWait registerTimeout + 11
  16. UA_Server *server_lds;
  17. UA_Boolean *running_lds;
  18. UA_ServerNetworkLayer nl_lds;
  19. pthread_t server_thread_lds;
  20. static void * serverloop_lds(void *_) {
  21. while(*running_lds)
  22. UA_Server_run_iterate(server_lds, true);
  23. return NULL;
  24. }
  25. static void setup_lds(void) {
  26. // start LDS server
  27. running_lds = UA_Boolean_new();
  28. *running_lds = true;
  29. UA_ServerConfig config_lds = UA_ServerConfig_standard;
  30. config_lds.applicationDescription.applicationType = UA_APPLICATIONTYPE_DISCOVERYSERVER;
  31. config_lds.applicationDescription.applicationUri = UA_String_fromChars("open62541.test.local_discovery_server");
  32. config_lds.discoveryCleanupTimeout = registerTimeout;
  33. nl_lds = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, 4840);
  34. config_lds.networkLayers = &nl_lds;
  35. config_lds.networkLayersSize = 1;
  36. server_lds = UA_Server_new(config_lds);
  37. UA_Server_run_startup(server_lds);
  38. pthread_create(&server_thread_lds, NULL, serverloop_lds, NULL);
  39. }
  40. static void teardown_lds(void) {
  41. *running_lds = false;
  42. pthread_join(server_thread_lds, NULL);
  43. UA_Server_run_shutdown(server_lds);
  44. UA_Boolean_delete(running_lds);
  45. UA_String_deleteMembers(&server_lds->config.applicationDescription.applicationUri);
  46. UA_Server_delete(server_lds);
  47. nl_lds.deleteMembers(&nl_lds);
  48. }
  49. UA_Server *server_register;
  50. UA_Boolean *running_register;
  51. UA_ServerNetworkLayer nl_register;
  52. pthread_t server_thread_register;
  53. static void * serverloop_register(void *_) {
  54. while(*running_register)
  55. UA_Server_run_iterate(server_register, true);
  56. return NULL;
  57. }
  58. static void setup_register(void) {
  59. // start LDS server
  60. running_register = UA_Boolean_new();
  61. *running_register = true;
  62. UA_ServerConfig config_register = UA_ServerConfig_standard;
  63. config_register.applicationDescription.applicationUri = UA_String_fromChars("open62541.test.server_register");
  64. nl_register = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, 16664);
  65. config_register.networkLayers = &nl_register;
  66. config_register.networkLayersSize = 1;
  67. server_register = UA_Server_new(config_register);
  68. UA_Server_run_startup(server_register);
  69. pthread_create(&server_thread_register, NULL, serverloop_register, NULL);
  70. }
  71. static void teardown_register(void) {
  72. *running_register = false;
  73. pthread_join(server_thread_register, NULL);
  74. UA_Server_run_shutdown(server_register);
  75. UA_Boolean_delete(running_register);
  76. UA_String_deleteMembers(&server_register->config.applicationDescription.applicationUri);
  77. UA_Server_delete(server_register);
  78. nl_register.deleteMembers(&nl_register);
  79. }
  80. START_TEST(Server_register) {
  81. UA_StatusCode retval = UA_Server_register_discovery(server_register, "opc.tcp://localhost:4840", NULL);
  82. ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
  83. }
  84. END_TEST
  85. START_TEST(Server_unregister) {
  86. UA_StatusCode retval = UA_Server_unregister_discovery(server_register, "opc.tcp://localhost:4840");
  87. ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
  88. }
  89. END_TEST
  90. static UA_StatusCode FindServers(const char* discoveryServerUrl, size_t* registeredServerSize, UA_ApplicationDescription** registeredServers, const char* filterUri, const char* filterLocale) {
  91. UA_Client *client = UA_Client_new(UA_ClientConfig_standard);
  92. UA_StatusCode retval = UA_Client_connect(client, discoveryServerUrl);
  93. if(retval != UA_STATUSCODE_GOOD) {
  94. UA_Client_delete(client);
  95. return retval;
  96. }
  97. UA_FindServersRequest request;
  98. UA_FindServersRequest_init(&request);
  99. if (filterUri) {
  100. request.serverUrisSize = 1;
  101. request.serverUris = UA_malloc(sizeof(UA_String));
  102. request.serverUris[0] = UA_String_fromChars(filterUri);
  103. }
  104. if (filterLocale) {
  105. request.localeIdsSize = 1;
  106. request.localeIds = UA_malloc(sizeof(UA_String));
  107. request.localeIds[0] = UA_String_fromChars(filterLocale);
  108. }
  109. // now send the request
  110. UA_FindServersResponse response;
  111. UA_FindServersResponse_init(&response);
  112. __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST],
  113. &response, &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE]);
  114. if (filterUri) {
  115. UA_Array_delete(request.serverUris, request.serverUrisSize, &UA_TYPES[UA_TYPES_STRING]);
  116. }
  117. if (filterLocale) {
  118. UA_Array_delete(request.localeIds, request.localeIdsSize, &UA_TYPES[UA_TYPES_STRING]);
  119. }
  120. if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
  121. UA_FindServersResponse_deleteMembers(&response);
  122. UA_Client_disconnect(client);
  123. UA_Client_delete(client);
  124. ck_abort_msg("FindServers failed with statuscode 0x%08x", response.responseHeader.serviceResult);
  125. }
  126. *registeredServerSize = response.serversSize;
  127. *registeredServers = (UA_ApplicationDescription*)UA_Array_new(response.serversSize, &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]);
  128. for(size_t i=0;i<response.serversSize;i++)
  129. UA_ApplicationDescription_copy(&response.servers[i], &(*registeredServers)[i]);
  130. UA_FindServersResponse_deleteMembers(&response);
  131. UA_Client_disconnect(client);
  132. UA_Client_delete(client);
  133. return (int) UA_STATUSCODE_GOOD;
  134. }
  135. static void FindAndCheck(const char* expectedUris[], size_t expectedUrisSize, const char *filterUri, const char *filterLocale) {
  136. UA_Client *client = UA_Client_new(UA_ClientConfig_standard);
  137. UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840");
  138. ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
  139. UA_ApplicationDescription* applicationDescriptionArray = NULL;
  140. size_t applicationDescriptionArraySize = 0;
  141. retval = FindServers("opc.tcp://localhost:4840", &applicationDescriptionArraySize, &applicationDescriptionArray, filterUri, filterLocale);
  142. ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
  143. // only the discovery server is expected
  144. ck_assert_uint_eq(applicationDescriptionArraySize, expectedUrisSize);
  145. assert(applicationDescriptionArray != NULL);
  146. for(size_t i=0; i < expectedUrisSize; ++i) {
  147. char* serverUri = malloc(sizeof(char)*applicationDescriptionArray[i].applicationUri.length+1);
  148. memcpy(serverUri, applicationDescriptionArray[i].applicationUri.data, applicationDescriptionArray[i].applicationUri.length);
  149. serverUri[applicationDescriptionArray[i].applicationUri.length] = '\0';
  150. ck_assert_str_eq(serverUri, expectedUris[i]);
  151. free(serverUri);
  152. }
  153. UA_Array_delete(applicationDescriptionArray, applicationDescriptionArraySize, &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]);
  154. UA_Client_disconnect(client);
  155. UA_Client_delete(client);
  156. }
  157. // Test if discovery server lists himself as registered server, before any other registration.
  158. START_TEST(Client_find_discovery) {
  159. const char* expectedUris[] ={"open62541.test.local_discovery_server"};
  160. FindAndCheck(expectedUris, 1, NULL, NULL);
  161. }
  162. END_TEST
  163. // Test if discovery server lists himself as registered server if it is filtered by his uri
  164. START_TEST(Client_filter_discovery) {
  165. const char* expectedUris[] ={"open62541.test.local_discovery_server"};
  166. FindAndCheck(expectedUris, 1, "open62541.test.local_discovery_server", "en");
  167. }
  168. END_TEST
  169. // Test if registered server is returned from LDS
  170. START_TEST(Client_find_registered) {
  171. const char* expectedUris[] ={"open62541.test.local_discovery_server", "open62541.test.server_register"};
  172. FindAndCheck(expectedUris, 2, NULL, NULL);
  173. }
  174. END_TEST
  175. // Test if filtering with uris works
  176. START_TEST(Client_find_filter) {
  177. const char* expectedUris[] ={"open62541.test.server_register"};
  178. FindAndCheck(expectedUris, 1, "open62541.test.server_register", NULL);
  179. }
  180. END_TEST
  181. START_TEST(Util_wait_timeout) {
  182. // wait until server is removed by timeout. Additionally wait a few seconds more to be sure.
  183. sleep(checkWait);
  184. }
  185. END_TEST
  186. static Suite* testSuite_Client(void) {
  187. Suite *s = suite_create("Register Server and Client");
  188. TCase *tc_register = tcase_create("RegisterServer");
  189. tcase_add_unchecked_fixture(tc_register, setup_lds, teardown_lds);
  190. tcase_add_unchecked_fixture(tc_register, setup_register, teardown_register);
  191. tcase_add_test(tc_register, Server_register);
  192. // register two times
  193. tcase_add_test(tc_register, Server_register);
  194. tcase_add_test(tc_register, Server_unregister);
  195. suite_add_tcase(s,tc_register);
  196. TCase *tc_register_find = tcase_create("RegisterServer and FindServers");
  197. tcase_add_unchecked_fixture(tc_register_find, setup_lds, teardown_lds);
  198. tcase_add_unchecked_fixture(tc_register_find, setup_register, teardown_register);
  199. tcase_add_test(tc_register_find, Client_find_discovery);
  200. tcase_add_test(tc_register_find, Server_register);
  201. tcase_add_test(tc_register_find, Client_find_registered);
  202. tcase_add_test(tc_register_find, Client_find_filter);
  203. tcase_add_test(tc_register_find, Server_unregister);
  204. tcase_add_test(tc_register_find, Client_find_discovery);
  205. tcase_add_test(tc_register_find, Client_filter_discovery);
  206. suite_add_tcase(s,tc_register_find);
  207. // register server again, then wait for timeout and auto unregister
  208. TCase *tc_register_timeout = tcase_create("RegisterServer timeout");
  209. tcase_add_unchecked_fixture(tc_register_timeout, setup_lds, teardown_lds);
  210. tcase_add_unchecked_fixture(tc_register_timeout, setup_register, teardown_register);
  211. tcase_set_timeout(tc_register_timeout, checkWait+2);
  212. tcase_add_test(tc_register_timeout, Server_register);
  213. tcase_add_test(tc_register_timeout, Client_find_registered);
  214. tcase_add_test(tc_register_timeout, Util_wait_timeout);
  215. tcase_add_test(tc_register_timeout, Client_find_discovery);
  216. suite_add_tcase(s,tc_register_timeout);
  217. return s;
  218. }
  219. int main(void) {
  220. Suite *s = testSuite_Client();
  221. SRunner *sr = srunner_create(s);
  222. srunner_set_fork_status(sr, CK_NOFORK);
  223. srunner_run_all(sr,CK_NORMAL);
  224. int number_failed = srunner_ntests_failed(sr);
  225. srunner_free(sr);
  226. return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
  227. }