check_nodestore.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #include "ua_types.h"
  5. #include "server/ua_nodestore.h"
  6. #include "ua_util.h"
  7. #include "check.h"
  8. #ifdef MULTITHREADING
  9. #include <pthread.h>
  10. #include <urcu.h>
  11. #endif
  12. int zeroCnt = 0;
  13. int visitCnt = 0;
  14. void checkZeroVisitor(const UA_Node* node) {
  15. visitCnt++;
  16. if (node == UA_NULL) zeroCnt++;
  17. }
  18. void printVisitor(const UA_Node* node) {
  19. printf("%d\n", node->nodeId.identifier.numeric);
  20. }
  21. START_TEST(test_UA_NodeStore) {
  22. UA_NodeStore *ns = UA_NULL;
  23. UA_NodeStore_new(&ns);
  24. UA_NodeStore_delete(ns);
  25. }
  26. END_TEST
  27. UA_Int32 createNode(UA_Node** p, UA_Int16 nsid, UA_Int32 id) {
  28. UA_VariableNode_new((UA_VariableNode **)p);
  29. (*p)->nodeId.identifierType = UA_NODEIDTYPE_NUMERIC;
  30. (*p)->nodeId.namespaceIndex = nsid;
  31. (*p)->nodeId.identifier.numeric = id;
  32. (*p)->nodeClass = UA_NODECLASS_VARIABLE;
  33. return UA_SUCCESS;
  34. }
  35. START_TEST(findNodeInUA_NodeStoreWithSingleEntry) {
  36. #ifdef MULTITHREADING
  37. rcu_register_thread();
  38. #endif
  39. // given
  40. UA_NodeStore *ns;
  41. UA_NodeStore_new(&ns);
  42. UA_Node* n1; createNode(&n1,0,2253);
  43. UA_NodeStore_insert(ns, &n1, UA_NODESTORE_INSERT_UNIQUE | UA_NODESTORE_INSERT_GETMANAGED);
  44. const UA_Node* nr = UA_NULL;
  45. UA_Int32 retval;
  46. // when
  47. retval = UA_NodeStore_get(ns,&n1->nodeId,&nr);
  48. // then
  49. ck_assert_int_eq(retval, UA_SUCCESS);
  50. ck_assert_ptr_eq(nr,n1);
  51. // finally
  52. UA_NodeStore_releaseManagedNode(n1);
  53. UA_NodeStore_releaseManagedNode(nr);
  54. UA_NodeStore_delete(ns);
  55. #ifdef MULTITHREADING
  56. rcu_unregister_thread();
  57. #endif
  58. }
  59. END_TEST
  60. START_TEST(failToFindNodeInOtherUA_NodeStore) {
  61. #ifdef MULTITHREADING
  62. rcu_register_thread();
  63. #endif
  64. // given
  65. UA_NodeStore *ns = UA_NULL;
  66. UA_NodeStore_new(&ns);
  67. UA_Node* n1; createNode(&n1,0,2253); UA_NodeStore_insert(ns, &n1, 0);
  68. UA_Node* n2; createNode(&n2,0,2253); UA_NodeStore_insert(ns, &n2, 0);
  69. const UA_Node* nr = UA_NULL;
  70. // when
  71. UA_Node* n; createNode(&n,1,2255);
  72. UA_Int32 retval = UA_NodeStore_get(ns,&n->nodeId, &nr);
  73. // then
  74. ck_assert_int_ne(retval, UA_SUCCESS);
  75. // finally
  76. UA_Node_delete(n);
  77. UA_NodeStore_releaseManagedNode(nr);
  78. UA_NodeStore_delete(ns);
  79. #ifdef MULTITHREADING
  80. rcu_unregister_thread();
  81. #endif
  82. }
  83. END_TEST
  84. START_TEST(findNodeInUA_NodeStoreWithSeveralEntries) {
  85. #ifdef MULTITHREADING
  86. rcu_register_thread();
  87. #endif
  88. // given
  89. UA_NodeStore *ns;
  90. UA_NodeStore_new(&ns);
  91. UA_Node* n1; createNode(&n1,0,2253); UA_NodeStore_insert(ns, &n1, 0);
  92. UA_Node* n2; createNode(&n2,0,2255); UA_NodeStore_insert(ns, &n2, 0);
  93. UA_Node* n3; createNode(&n3,0,2257); UA_NodeStore_insert(ns, &n3, UA_NODESTORE_INSERT_GETMANAGED);
  94. UA_Node* n4; createNode(&n4,0,2200); UA_NodeStore_insert(ns, &n4, 0);
  95. UA_Node* n5; createNode(&n5,0,1); UA_NodeStore_insert(ns, &n5, 0);
  96. UA_Node* n6; createNode(&n6,0,12); UA_NodeStore_insert(ns, &n6, 0);
  97. const UA_Node* nr = UA_NULL;
  98. UA_Int32 retval;
  99. // when
  100. retval = UA_NodeStore_get(ns,&(n3->nodeId),&nr);
  101. // then
  102. ck_assert_int_eq(retval, UA_SUCCESS);
  103. ck_assert_ptr_eq(nr,n3);
  104. // finally
  105. UA_NodeStore_releaseManagedNode(n3);
  106. UA_NodeStore_releaseManagedNode(nr);
  107. UA_NodeStore_delete(ns);
  108. #ifdef MULTITHREADING
  109. rcu_unregister_thread();
  110. #endif
  111. }
  112. END_TEST
  113. START_TEST(iterateOverUA_NodeStoreShallNotVisitEmptyNodes) {
  114. #ifdef MULTITHREADING
  115. rcu_register_thread();
  116. #endif
  117. // given
  118. UA_NodeStore *ns;
  119. UA_NodeStore_new(&ns);
  120. UA_Node* n1; createNode(&n1,0,2253); UA_NodeStore_insert(ns, &n1, 0);
  121. UA_Node* n2; createNode(&n2,0,2255); UA_NodeStore_insert(ns, &n2, 0);
  122. UA_Node* n3; createNode(&n3,0,2257); UA_NodeStore_insert(ns, &n3, 0);
  123. UA_Node* n4; createNode(&n4,0,2200); UA_NodeStore_insert(ns, &n4, 0);
  124. UA_Node* n5; createNode(&n5,0,1); UA_NodeStore_insert(ns, &n5, 0);
  125. UA_Node* n6; createNode(&n6,0,12); UA_NodeStore_insert(ns, &n6, 0);
  126. UA_Int32 retval;
  127. // when
  128. zeroCnt = 0;
  129. visitCnt = 0;
  130. retval = UA_NodeStore_iterate(ns,checkZeroVisitor);
  131. // then
  132. ck_assert_int_eq(retval, UA_SUCCESS);
  133. ck_assert_int_eq(zeroCnt, 0);
  134. ck_assert_int_eq(visitCnt, 6);
  135. // finally
  136. UA_NodeStore_delete(ns);
  137. #ifdef MULTITHREADING
  138. rcu_unregister_thread();
  139. #endif
  140. }
  141. END_TEST
  142. START_TEST(findNodeInExpandedNamespace) {
  143. #ifdef MULTITHREADING
  144. rcu_register_thread();
  145. #endif
  146. // given
  147. UA_NodeStore *ns;
  148. UA_NodeStore_new(&ns);
  149. UA_Node* n;
  150. UA_Int32 i=0;
  151. for (; i<200; i++) {
  152. createNode(&n,0,i); UA_NodeStore_insert(ns, &n, 0);
  153. }
  154. const UA_Node* nr = UA_NULL;
  155. UA_Int32 retval;
  156. // when
  157. createNode(&n,0,25);
  158. retval = UA_NodeStore_get(ns,&(n->nodeId),&nr);
  159. // then
  160. ck_assert_int_eq(retval, UA_SUCCESS);
  161. ck_assert_int_eq(nr->nodeId.identifier.numeric,n->nodeId.identifier.numeric);
  162. // finally
  163. UA_free((void*)n);
  164. UA_NodeStore_releaseManagedNode(nr);
  165. UA_NodeStore_delete(ns);
  166. #ifdef MULTITHREADING
  167. rcu_unregister_thread();
  168. #endif
  169. }
  170. END_TEST
  171. START_TEST(iterateOverExpandedNamespaceShallNotVisitEmptyNodes) {
  172. #ifdef MULTITHREADING
  173. rcu_register_thread();
  174. #endif
  175. // given
  176. UA_NodeStore *ns;
  177. UA_NodeStore_new(&ns);
  178. UA_Node* n;
  179. UA_Int32 i=0;
  180. for (; i<200; i++) {
  181. createNode(&n,0,i); UA_NodeStore_insert(ns, &n, 0);
  182. }
  183. // when
  184. UA_Int32 retval;
  185. zeroCnt = 0;
  186. visitCnt = 0;
  187. retval = UA_NodeStore_iterate(ns,checkZeroVisitor);
  188. // then
  189. ck_assert_int_eq(retval, UA_SUCCESS);
  190. ck_assert_int_eq(zeroCnt, 0);
  191. ck_assert_int_eq(visitCnt, 200);
  192. // finally
  193. UA_NodeStore_delete(ns);
  194. #ifdef MULTITHREADING
  195. rcu_unregister_thread();
  196. #endif
  197. }
  198. END_TEST
  199. START_TEST(failToFindNonExistantNodeInUA_NodeStoreWithSeveralEntries) {
  200. #ifdef MULTITHREADING
  201. rcu_register_thread();
  202. #endif
  203. // given
  204. UA_NodeStore *ns;
  205. UA_NodeStore_new(&ns);
  206. UA_Node* n1; createNode(&n1,0,2253); UA_NodeStore_insert(ns, &n1, 0);
  207. UA_Node* n2; createNode(&n2,0,2255); UA_NodeStore_insert(ns, &n2, 0);
  208. UA_Node* n3; createNode(&n3,0,2257); UA_NodeStore_insert(ns, &n3, 0);
  209. UA_Node* n4; createNode(&n4,0,2200); UA_NodeStore_insert(ns, &n4, 0);
  210. UA_Node* n5; createNode(&n5,0,1); UA_NodeStore_insert(ns, &n5, 0);
  211. UA_Node* n6; createNode(&n6,0,12);
  212. const UA_Node* nr = UA_NULL;
  213. UA_Int32 retval;
  214. // when
  215. retval = UA_NodeStore_get(ns, &(n6->nodeId), &nr);
  216. // then
  217. ck_assert_int_ne(retval, UA_SUCCESS);
  218. // finally
  219. UA_free((void *)n6);
  220. UA_NodeStore_delete(ns);
  221. #ifdef MULTITHREADING
  222. rcu_unregister_thread();
  223. #endif
  224. }
  225. END_TEST
  226. /************************************/
  227. /* Performance Profiling Test Cases */
  228. /************************************/
  229. #ifdef MULTITHREADING
  230. struct UA_NodeStoreProfileTest {
  231. UA_NodeStore *ns;
  232. UA_Int32 min_val;
  233. UA_Int32 max_val;
  234. UA_Int32 rounds;
  235. };
  236. void *profileGetThread(void *arg) {
  237. rcu_register_thread();
  238. struct UA_NodeStoreProfileTest *test = (struct UA_NodeStoreProfileTest*) arg;
  239. UA_NodeId id = NS0NODEID(0);
  240. const UA_Node *cn;
  241. UA_Int32 max_val = test->max_val;
  242. UA_NodeStore *ns = test->ns;
  243. for(UA_Int32 x = 0; x<test->rounds; x++) {
  244. for (UA_Int32 i=test->min_val; i<max_val; i++) {
  245. id.identifier.numeric = i;
  246. UA_NodeStore_get(ns,&id, &cn);
  247. UA_NodeStore_releaseManagedNode(cn);
  248. }
  249. }
  250. rcu_unregister_thread();
  251. return UA_NULL;
  252. }
  253. #endif
  254. START_TEST(profileGetDelete) {
  255. #ifdef MULTITHREADING
  256. rcu_register_thread();
  257. #endif
  258. #define N 1000000
  259. UA_NodeStore *ns;
  260. UA_NodeStore_new(&ns);
  261. UA_Int32 i=0;
  262. UA_Node *n;
  263. for (; i<N; i++) {
  264. createNode(&n,0,i); UA_NodeStore_insert(ns, &n, 0);
  265. }
  266. clock_t begin, end;
  267. begin = clock();
  268. #ifdef MULTITHREADING
  269. #define THREADS 4
  270. pthread_t t[THREADS];
  271. struct UA_NodeStoreProfileTest p[THREADS];
  272. for (int i = 0; i < THREADS; i++) {
  273. p[i] = (struct UA_NodeStoreProfileTest){ns, i*(N/THREADS), (i+1)*(N/THREADS), 50};
  274. pthread_create(&t[i], NULL, profileGetThread, &p[i]);
  275. }
  276. for (int i = 0; i < THREADS; i++)
  277. pthread_join(t[i], NULL);
  278. end = clock();
  279. printf("Time for %d create/get/delete on %d threads in a namespace: %fs.\n", N, THREADS, (double)(end - begin) / CLOCKS_PER_SEC);
  280. #else
  281. const UA_Node *cn;
  282. UA_NodeId id = NS0NODEID(0);
  283. for(UA_Int32 x = 0; x<50; x++) {
  284. for(i=0; i<N; i++) {
  285. id.identifier.numeric = i;
  286. UA_NodeStore_get(ns,&id, &cn);
  287. UA_NodeStore_releaseManagedNode(cn);
  288. }
  289. }
  290. end = clock();
  291. printf("Time for single-threaded %d create/get/delete in a namespace: %fs.\n", N, (double)(end - begin) / CLOCKS_PER_SEC);
  292. #endif
  293. UA_NodeStore_delete(ns);
  294. #ifdef MULTITHREADING
  295. rcu_unregister_thread();
  296. #endif
  297. }
  298. END_TEST
  299. Suite * namespace_suite (void) {
  300. Suite *s = suite_create ("UA_NodeStore");
  301. TCase *tc_cd = tcase_create ("Create/Delete");
  302. tcase_add_test (tc_cd, test_UA_NodeStore);
  303. suite_add_tcase (s, tc_cd);
  304. TCase* tc_find = tcase_create ("Find");
  305. tcase_add_test (tc_find, findNodeInUA_NodeStoreWithSingleEntry);
  306. tcase_add_test (tc_find, findNodeInUA_NodeStoreWithSeveralEntries);
  307. tcase_add_test (tc_find, findNodeInExpandedNamespace);
  308. tcase_add_test (tc_find, failToFindNonExistantNodeInUA_NodeStoreWithSeveralEntries);
  309. tcase_add_test (tc_find, failToFindNodeInOtherUA_NodeStore);
  310. suite_add_tcase (s, tc_find);
  311. TCase* tc_iterate = tcase_create ("Iterate");
  312. tcase_add_test (tc_iterate, iterateOverUA_NodeStoreShallNotVisitEmptyNodes);
  313. tcase_add_test (tc_iterate, iterateOverExpandedNamespaceShallNotVisitEmptyNodes);
  314. suite_add_tcase (s, tc_iterate);
  315. /* TCase* tc_profile = tcase_create ("Profile"); */
  316. /* tcase_add_test (tc_profile, profileGetDelete); */
  317. /* suite_add_tcase (s, tc_profile); */
  318. return s;
  319. }
  320. int main (void) {
  321. int number_failed =0;
  322. Suite *s = namespace_suite ();
  323. SRunner *sr = srunner_create (s);
  324. //srunner_set_fork_status(sr,CK_NOFORK);
  325. srunner_run_all (sr, CK_NORMAL);
  326. number_failed += srunner_ntests_failed (sr);
  327. srunner_free (sr);
  328. return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
  329. }