check_namespace.c 9.1 KB

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