check_nodestore.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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_StatusCode createNode(UA_Node** p, UA_Int16 nsid, UA_Int32 id) {
  28. *p = (UA_Node *)UA_VariableNode_new();
  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_STATUSCODE_GOOD;
  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_STATUSCODE_GOOD);
  50. ck_assert_ptr_eq((void*)nr, (void*)n1);
  51. // finally
  52. UA_NodeStore_release(n1);
  53. UA_NodeStore_release(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_STATUSCODE_GOOD);
  75. // finally
  76. UA_Node_delete(n);
  77. UA_NodeStore_release(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_STATUSCODE_GOOD);
  103. ck_assert_ptr_eq((void*)nr, (void*)n3);
  104. // finally
  105. UA_NodeStore_release(n3);
  106. UA_NodeStore_release(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. // when
  127. zeroCnt = 0;
  128. visitCnt = 0;
  129. UA_NodeStore_iterate(ns,checkZeroVisitor);
  130. // then
  131. ck_assert_int_eq(zeroCnt, 0);
  132. ck_assert_int_eq(visitCnt, 6);
  133. // finally
  134. UA_NodeStore_delete(ns);
  135. #ifdef MULTITHREADING
  136. rcu_unregister_thread();
  137. #endif
  138. }
  139. END_TEST
  140. START_TEST(findNodeInExpandedNamespace) {
  141. #ifdef MULTITHREADING
  142. rcu_register_thread();
  143. #endif
  144. // given
  145. UA_NodeStore *ns;
  146. UA_NodeStore_new(&ns);
  147. UA_Node* n;
  148. UA_Int32 i=0;
  149. for (; i<200; i++) {
  150. createNode(&n,0,i); UA_NodeStore_insert(ns, &n, 0);
  151. }
  152. const UA_Node* nr = UA_NULL;
  153. UA_Int32 retval;
  154. // when
  155. createNode(&n,0,25);
  156. retval = UA_NodeStore_get(ns,&(n->nodeId),&nr);
  157. // then
  158. ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
  159. ck_assert_int_eq(nr->nodeId.identifier.numeric,n->nodeId.identifier.numeric);
  160. // finally
  161. UA_free((void*)n);
  162. UA_NodeStore_release(nr);
  163. UA_NodeStore_delete(ns);
  164. #ifdef MULTITHREADING
  165. rcu_unregister_thread();
  166. #endif
  167. }
  168. END_TEST
  169. START_TEST(iterateOverExpandedNamespaceShallNotVisitEmptyNodes) {
  170. #ifdef MULTITHREADING
  171. rcu_register_thread();
  172. #endif
  173. // given
  174. UA_NodeStore *ns;
  175. UA_NodeStore_new(&ns);
  176. UA_Node* n;
  177. UA_Int32 i=0;
  178. for (; i<200; i++) {
  179. createNode(&n,0,i); UA_NodeStore_insert(ns, &n, 0);
  180. }
  181. // when
  182. zeroCnt = 0;
  183. visitCnt = 0;
  184. UA_NodeStore_iterate(ns,checkZeroVisitor);
  185. // then
  186. ck_assert_int_eq(zeroCnt, 0);
  187. ck_assert_int_eq(visitCnt, 200);
  188. // finally
  189. UA_NodeStore_delete(ns);
  190. #ifdef MULTITHREADING
  191. rcu_unregister_thread();
  192. #endif
  193. }
  194. END_TEST
  195. START_TEST(failToFindNonExistantNodeInUA_NodeStoreWithSeveralEntries) {
  196. #ifdef MULTITHREADING
  197. rcu_register_thread();
  198. #endif
  199. // given
  200. UA_NodeStore *ns;
  201. UA_NodeStore_new(&ns);
  202. UA_Node* n1; createNode(&n1,0,2253); UA_NodeStore_insert(ns, &n1, 0);
  203. UA_Node* n2; createNode(&n2,0,2255); UA_NodeStore_insert(ns, &n2, 0);
  204. UA_Node* n3; createNode(&n3,0,2257); UA_NodeStore_insert(ns, &n3, 0);
  205. UA_Node* n4; createNode(&n4,0,2200); UA_NodeStore_insert(ns, &n4, 0);
  206. UA_Node* n5; createNode(&n5,0,1); UA_NodeStore_insert(ns, &n5, 0);
  207. UA_Node* n6; createNode(&n6,0,12);
  208. const UA_Node* nr = UA_NULL;
  209. UA_Int32 retval;
  210. // when
  211. retval = UA_NodeStore_get(ns, &(n6->nodeId), &nr);
  212. // then
  213. ck_assert_int_ne(retval, UA_STATUSCODE_GOOD);
  214. // finally
  215. UA_free((void *)n6);
  216. UA_NodeStore_delete(ns);
  217. #ifdef MULTITHREADING
  218. rcu_unregister_thread();
  219. #endif
  220. }
  221. END_TEST
  222. /************************************/
  223. /* Performance Profiling Test Cases */
  224. /************************************/
  225. #ifdef MULTITHREADING
  226. struct UA_NodeStoreProfileTest {
  227. UA_NodeStore *ns;
  228. UA_Int32 min_val;
  229. UA_Int32 max_val;
  230. UA_Int32 rounds;
  231. };
  232. void *profileGetThread(void *arg) {
  233. rcu_register_thread();
  234. struct UA_NodeStoreProfileTest *test = (struct UA_NodeStoreProfileTest*) arg;
  235. UA_NodeId id = NS0NODEID(0);
  236. const UA_Node *cn;
  237. UA_Int32 max_val = test->max_val;
  238. UA_NodeStore *ns = test->ns;
  239. for(UA_Int32 x = 0; x<test->rounds; x++) {
  240. for (UA_Int32 i=test->min_val; i<max_val; i++) {
  241. id.identifier.numeric = i;
  242. UA_NodeStore_get(ns,&id, &cn);
  243. UA_NodeStore_release(cn);
  244. }
  245. }
  246. rcu_unregister_thread();
  247. return UA_NULL;
  248. }
  249. #endif
  250. START_TEST(profileGetDelete) {
  251. #ifdef MULTITHREADING
  252. rcu_register_thread();
  253. #endif
  254. #define N 1000000
  255. UA_NodeStore *ns;
  256. UA_NodeStore_new(&ns);
  257. UA_Int32 i=0;
  258. UA_Node *n;
  259. for (; i<N; i++) {
  260. createNode(&n,0,i); UA_NodeStore_insert(ns, &n, 0);
  261. }
  262. clock_t begin, end;
  263. begin = clock();
  264. #ifdef MULTITHREADING
  265. #define THREADS 4
  266. pthread_t t[THREADS];
  267. struct UA_NodeStoreProfileTest p[THREADS];
  268. for (int i = 0; i < THREADS; i++) {
  269. p[i] = (struct UA_NodeStoreProfileTest){ns, i*(N/THREADS), (i+1)*(N/THREADS), 50};
  270. pthread_create(&t[i], NULL, profileGetThread, &p[i]);
  271. }
  272. for (int i = 0; i < THREADS; i++)
  273. pthread_join(t[i], NULL);
  274. end = clock();
  275. printf("Time for %d create/get/delete on %d threads in a namespace: %fs.\n", N, THREADS, (double)(end - begin) / CLOCKS_PER_SEC);
  276. #else
  277. const UA_Node *cn;
  278. UA_NodeId id = NS0NODEID(0);
  279. for(UA_Int32 x = 0; x<50; x++) {
  280. for(i=0; i<N; i++) {
  281. id.identifier.numeric = i;
  282. UA_NodeStore_get(ns,&id, &cn);
  283. UA_NodeStore_release(cn);
  284. }
  285. }
  286. end = clock();
  287. printf("Time for single-threaded %d create/get/delete in a namespace: %fs.\n", N, (double)(end - begin) / CLOCKS_PER_SEC);
  288. #endif
  289. UA_NodeStore_delete(ns);
  290. #ifdef MULTITHREADING
  291. rcu_unregister_thread();
  292. #endif
  293. }
  294. END_TEST
  295. Suite * namespace_suite (void) {
  296. Suite *s = suite_create ("UA_NodeStore");
  297. TCase *tc_cd = tcase_create ("Create/Delete");
  298. tcase_add_test (tc_cd, test_UA_NodeStore);
  299. suite_add_tcase (s, tc_cd);
  300. TCase* tc_find = tcase_create ("Find");
  301. tcase_add_test (tc_find, findNodeInUA_NodeStoreWithSingleEntry);
  302. tcase_add_test (tc_find, findNodeInUA_NodeStoreWithSeveralEntries);
  303. tcase_add_test (tc_find, findNodeInExpandedNamespace);
  304. tcase_add_test (tc_find, failToFindNonExistantNodeInUA_NodeStoreWithSeveralEntries);
  305. tcase_add_test (tc_find, failToFindNodeInOtherUA_NodeStore);
  306. suite_add_tcase (s, tc_find);
  307. TCase* tc_iterate = tcase_create ("Iterate");
  308. tcase_add_test (tc_iterate, iterateOverUA_NodeStoreShallNotVisitEmptyNodes);
  309. tcase_add_test (tc_iterate, iterateOverExpandedNamespaceShallNotVisitEmptyNodes);
  310. suite_add_tcase (s, tc_iterate);
  311. /* TCase* tc_profile = tcase_create ("Profile"); */
  312. /* tcase_add_test (tc_profile, profileGetDelete); */
  313. /* suite_add_tcase (s, tc_profile); */
  314. return s;
  315. }
  316. int main (void) {
  317. int number_failed =0;
  318. Suite *s = namespace_suite ();
  319. SRunner *sr = srunner_create (s);
  320. srunner_set_fork_status(sr,CK_NOFORK);
  321. srunner_run_all (sr, CK_NORMAL);
  322. number_failed += srunner_ntests_failed (sr);
  323. srunner_free (sr);
  324. return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
  325. }